All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
version.c
Go to the documentation of this file.
1 /*
2  * version.c Print version number and exit.
3  *
4  * Version: $Id: 8d7cf68f92c9bd689dfe86ae087a491cf9f13793 $
5  *
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.
10  *
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.
15  *
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
19  *
20  * Copyright 1999-2014 The FreeRADIUS server project
21  * Copyright 2012 Alan DeKok <aland@ox.org>
22  * Copyright 2000 Chris Parker <cparker@starnetusa.com>
23  */
24 
25 RCSID("$Id: 8d7cf68f92c9bd689dfe86ae087a491cf9f13793 $")
26 
27 #include <freeradius-devel/radiusd.h>
28 USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */
29 
30 static uint64_t libmagic = RADIUSD_MAGIC_NUMBER;
31 char const *radiusd_version_short = RADIUSD_VERSION_STRING;
32 
33 #ifdef HAVE_OPENSSL_CRYPTO_H
34 # include <openssl/crypto.h>
35 # include <openssl/opensslv.h>
36 # include <openssl/engine.h>
37 
38 static long ssl_built = OPENSSL_VERSION_NUMBER;
39 
40 /** Check built and linked versions of OpenSSL match
41  *
42  * OpenSSL version number consists of:
43  * MNNFFPPS: major minor fix patch status
44  *
45  * Where status >= 0 && < 10 means beta, and status 10 means release.
46  *
47  * Startup check for whether the linked version of OpenSSL matches the
48  * version the server was built against.
49  *
50  * @return
51  * - 0 if ok.
52  * - -1 if not ok.
53  */
54 int ssl_check_consistency(void)
55 {
56  long ssl_linked;
57 
58  ssl_linked = SSLeay();
59 
60  /*
61  * Status mismatch always triggers error.
62  */
63  if ((ssl_linked & 0x0000000f) != (ssl_built & 0x0000000f)) {
64  mismatch:
65  ERROR("libssl version mismatch. built: %lx linked: %lx",
66  (unsigned long) ssl_built,
67  (unsigned long) ssl_linked);
68 
69  return -1;
70  }
71 
72  /*
73  * Use the OpenSSH approach and relax fix checks after version
74  * 1.0.0 and only allow moving backwards within a patch
75  * series.
76  */
77  if (ssl_built & 0xf0000000) {
78  if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000) ||
79  (ssl_built & 0x00000ff0) > (ssl_linked & 0x00000ff0)) goto mismatch;
80  /*
81  * Before 1.0.0 we require the same major minor and fix version
82  * and ignore the patch number.
83  */
84  } else if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000)) goto mismatch;
85 
86  return 0;
87 }
88 
89 /** Convert a version number to a text string
90  *
91  * @note Not thread safe.
92  *
93  * @param v version to convert.
94  * @return pointer to a static buffer containing the version string.
95  */
96 char const *ssl_version_by_num(uint32_t v)
97 {
98  /* 2 (%s) + 1 (.) + 2 (%i) + 1 (.) + 2 (%i) + 1 (c) + 8 (%s) + \0 */
99  static char buffer[18];
100  char *p = buffer;
101 
102  p += sprintf(p, "%u.%u.%u",
103  (0xf0000000 & v) >> 28,
104  (0x0ff00000 & v) >> 20,
105  (0x000ff000 & v) >> 12);
106 
107  if ((0x00000ff0 & v) >> 4) {
108  *p++ = (char) (0x60 + ((0x00000ff0 & v) >> 4));
109  }
110 
111  *p++ = ' ';
112 
113  /*
114  * Development (0)
115  */
116  if ((0x0000000f & v) == 0) {
117  strcpy(p, "dev");
118  /*
119  * Beta (1-14)
120  */
121  } else if ((0x0000000f & v) <= 14) {
122  sprintf(p, "beta %u", 0x0000000f & v);
123  } else {
124  strcpy(p, "release");
125  }
126 
127  return buffer;
128 }
129 
130 /** Return the linked SSL version number as a string
131  *
132  * @return pointer to a static buffer containing the version string.
133  */
134 char const *ssl_version_num(void)
135 {
136  long ssl_linked;
137 
138  ssl_linked = SSLeay();
139  return ssl_version_by_num((uint32_t)ssl_linked);
140 }
141 
142 /** Convert two openssl version numbers into a range string
143  *
144  * @note Not thread safe.
145  *
146  * @param low version to convert.
147  * @param high version to convert.
148  * @return pointer to a static buffer containing the version range string.
149  */
150 char const *ssl_version_range(uint32_t low, uint32_t high)
151 {
152  /* 12 (version) + 3 ( - ) + 12 (version) */
153  static char buffer[28];
154  char *p = buffer;
155 
156  p += strlcpy(p, ssl_version_by_num(low), sizeof(buffer));
157  p += strlcpy(p, " - ", sizeof(buffer) - (p - buffer));
158  strlcpy(p, ssl_version_by_num(high), sizeof(buffer) - (p - buffer));
159 
160  return buffer;
161 }
162 
163 /** Print the current linked version of Openssl
164  *
165  * Print the currently linked version of the OpenSSL library.
166  *
167  * @note Not thread safe.
168  * @return pointer to a static buffer containing libssl version information.
169  */
170 char const *ssl_version(void)
171 {
172  static char buffer[256];
173 
174  uint32_t v = SSLeay();
175 
176  snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
177  SSLeay_version(SSLEAY_VERSION), /* Not all builds include a useful version number */
178  v,
179  ssl_version_by_num(v));
180 
181  return buffer;
182 }
183 # else
185  return 0;
186 }
187 
188 char const *ssl_version_num(void)
189 {
190  return "not linked";
191 }
192 
193 char const *ssl_version()
194 {
195  return "not linked";
196 }
197 #endif /* ifdef HAVE_OPENSSL_CRYPTO_H */
198 
199 /** Check if the application linking to the library has the correct magic number
200  *
201  * @param magic number as defined by RADIUSD_MAGIC_NUMBER
202  * @returns
203  * - 0 on success.
204  * - -1 on prefix mismatch.
205  * - -2 on version mismatch.
206  * - -3 on commit mismatch.
207  */
208 int rad_check_lib_magic(uint64_t magic)
209 {
210  if (MAGIC_PREFIX(magic) != MAGIC_PREFIX(libmagic)) {
211  ERROR("Application and libfreeradius-server magic number (prefix) mismatch."
212  " application: %x library: %x",
213  MAGIC_PREFIX(magic), MAGIC_PREFIX(libmagic));
214  return -1;
215  }
216 
217  if (MAGIC_VERSION(magic) != MAGIC_VERSION(libmagic)) {
218  ERROR("Application and libfreeradius-server magic number (version) mismatch."
219  " application: %lx library: %lx",
220  (unsigned long) MAGIC_VERSION(magic), (unsigned long) MAGIC_VERSION(libmagic));
221  return -2;
222  }
223 
224  if (MAGIC_COMMIT(magic) != MAGIC_COMMIT(libmagic)) {
225  ERROR("Application and libfreeradius-server magic number (commit) mismatch."
226  " application: %lx library: %lx",
227  (unsigned long) MAGIC_COMMIT(magic), (unsigned long) MAGIC_COMMIT(libmagic));
228  return -3;
229  }
230 
231  return 0;
232 }
233 
234 /** Add a feature flag to the main configuration
235  *
236  * Add a feature flag (yes/no) to the 'feature' subsection
237  * off the main config.
238  *
239  * This allows the user to create configurations that work with
240  * across multiple environments.
241  *
242  * @param cs to add feature pair to.
243  * @param name of feature.
244  * @param enabled Whether the feature is present/enabled.
245  * @return
246  * - 0 on success.
247  * - -1 on failure.
248  */
249 int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled)
250 {
251  if (!cs) return -1;
252 
253  if (!cf_pair_find(cs, name)) {
254  CONF_PAIR *cp;
255 
256  cp = cf_pair_alloc(cs, name, enabled ? "yes" : "no",
258  if (!cp) return -1;
259  cf_pair_add(cs, cp);
260  }
261 
262  return 0;
263 }
264 
265 /** Add a library/server version pair to the main configuration
266  *
267  * Add a version number to the 'version' subsection off the main
268  * config.
269  *
270  * Because of the optimisations in the configuration parser, these
271  * may be checked using regular expressions without a performance
272  * penalty.
273  *
274  * The version pairs are there primarily to work around defects
275  * in libraries or the server.
276  *
277  * @param cs to add feature pair to.
278  * @param name of library or feature.
279  * @param version Humanly readable version text.
280  * @return
281  * - 0 on success.
282  * - -1 on failure.
283  */
284 int version_add_number(CONF_SECTION *cs, char const *name, char const *version)
285 {
286  CONF_PAIR *old;
287 
288  if (!cs) return -1;
289 
290  old = cf_pair_find(cs, name);
291  if (!old) {
292  CONF_PAIR *cp;
293 
294  cp = cf_pair_alloc(cs, name, version, T_OP_EQ, T_BARE_WORD, T_SINGLE_QUOTED_STRING);
295  if (!cp) return -1;
296 
297  cf_pair_add(cs, cp);
298  } else {
299  WARN("Replacing user version.%s (%s) with %s", name, cf_pair_value(old), version);
300 
301  cf_pair_replace(cs, old, version);
302  }
303 
304  return 0;
305 }
306 
307 
308 /** Initialise core feature flags
309  *
310  * @param cs Where to add the CONF_PAIRS, if null pairs will be added
311  * to the 'feature' section of the main config.
312  */
314 {
315  version_add_feature(cs, "accounting",
316 #ifdef WITH_ACCOUNTING
317  true
318 #else
319  false
320 #endif
321  );
322 
323  version_add_feature(cs, "authentication", true);
324 
325  version_add_feature(cs, "ascend-binary-attributes",
326 #ifdef WITH_ASCEND_BINARY
327  true
328 #else
329  false
330 #endif
331  );
332 
333  version_add_feature(cs, "coa",
334 #ifdef WITH_COA
335  true
336 #else
337  false
338 #endif
339  );
340 
341 
342  version_add_feature(cs, "control-socket",
343 #ifdef WITH_COMMAND_SOCKET
344  true
345 #else
346  false
347 #endif
348  );
349 
350 
351  version_add_feature(cs, "detail",
352 #ifdef WITH_DETAIL
353  true
354 #else
355  false
356 #endif
357  );
358 
359  version_add_feature(cs, "dhcp",
360 #ifdef WITH_DHCP
361  true
362 #else
363  false
364 #endif
365  );
366 
367  version_add_feature(cs, "dynamic-clients",
368 #ifdef WITH_DYNAMIC_CLIENTS
369  true
370 #else
371  false
372 #endif
373  );
374 
375  version_add_feature(cs, "osfc2",
376 #ifdef OSFC2
377  true
378 #else
379  false
380 #endif
381  );
382 
383  version_add_feature(cs, "proxy",
384 #ifdef WITH_PROXY
385  true
386 #else
387  false
388 #endif
389  );
390 
391  version_add_feature(cs, "regex-pcre",
392 #ifdef HAVE_PCRE
393  true
394 #else
395  false
396 #endif
397  );
398 
399 #if !defined(HAVE_PCRE) && defined(HAVE_REGEX)
400  version_add_feature(cs, "regex-posix", true);
401  version_add_feature(cs, "regex-posix-extended",
402 # ifdef HAVE_REG_EXTENDED
403  true
404 # else
405  false
406 # endif
407  );
408 #else
409  version_add_feature(cs, "regex-posix", false);
410  version_add_feature(cs, "regex-posix-extended", false);
411 #endif
412 
413  version_add_feature(cs, "session-management",
414 #ifdef WITH_SESSION_MGMT
415  true
416 #else
417  false
418 #endif
419  );
420 
421  version_add_feature(cs, "stats",
422 #ifdef WITH_STATS
423  true
424 #else
425  false
426 #endif
427  );
428 
429  version_add_feature(cs, "tcp",
430 #ifdef WITH_TCP
431  true
432 #else
433  false
434 #endif
435  );
436 
437  version_add_feature(cs, "threads",
438 #ifdef WITH_THREADS
439  true
440 #else
441  false
442 #endif
443  );
444 
445  version_add_feature(cs, "tls",
446 #ifdef WITH_TLS
447  true
448 #else
449  false
450 #endif
451  );
452 
453  version_add_feature(cs, "unlang",
454 #ifdef WITH_UNLANG
455  true
456 #else
457  false
458 #endif
459  );
460 
461  version_add_feature(cs, "vmps",
462 #ifdef WITH_VMPS
463  true
464 #else
465  false
466 #endif
467  );
468 
469  version_add_feature(cs, "developer",
470 #ifndef NDEBUG
471  true
472 #else
473  false
474 #endif
475  );
476 
477  version_add_feature(cs, "socket-timestamps",
478 #ifdef SO_TIMESTAMP
479  true
480 #else
481  false
482 #endif
483  );
484 }
485 
486 /** Initialise core version flags
487  *
488  * @param cs Where to add the CONF_PAIRS, if null pairs will be added
489  * to the 'version' section of the main config.
490  */
492 {
493  char buffer[128];
494 
495  version_add_number(cs, "freeradius-server", radiusd_version_short);
496 
497  snprintf(buffer, sizeof(buffer), "%i.%i.*", talloc_version_major(), talloc_version_minor());
498  version_add_number(cs, "talloc", buffer);
499 
500  version_add_number(cs, "ssl", ssl_version_num());
501 
502 #if defined(HAVE_REGEX) && defined(HAVE_PCRE)
503  version_add_number(cs, "pcre", pcre_version());
504 #endif
505 }
506 
507 static char const *spaces = " "; /* 40 */
508 
509 /*
510  * Display the revision number for this program
511  */
512 void version_print(void)
513 {
514  CONF_SECTION *features, *versions;
515  CONF_ITEM *ci;
516  CONF_PAIR *cp;
517 
518  if (DEBUG_ENABLED2) {
519 #ifdef WITH_TLS
520  ENGINE *engine;
521  char const *engine_id;
522 #endif
523  int max = 0, len;
524 
525  MEM(features = cf_section_alloc(NULL, "feature", NULL));
526  version_init_features(features);
527 
528  MEM(versions = cf_section_alloc(NULL, "version", NULL));
529  version_init_numbers(versions);
530 
531  DEBUG2("Server was built with: ");
532 
533  for (ci = cf_item_find_next(features, NULL);
534  ci;
535  ci = cf_item_find_next(features, ci)) {
536  len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
537  if (max < len) max = len;
538  }
539 
540  for (ci = cf_item_find_next(versions, NULL);
541  ci;
542  ci = cf_item_find_next(versions, ci)) {
543  len = talloc_array_length(cf_pair_attr(cf_item_to_pair(ci)));
544  if (max < len) max = len;
545  }
546 
547 #ifdef WITH_TLS
548  for (engine = ENGINE_get_first();
549  engine;
550  engine = ENGINE_get_next(engine)) {
551  len = strlen(ENGINE_get_id(engine) + 1);
552  if (max < len) max = len;
553  }
554 #endif
555 
556  for (ci = cf_item_find_next(features, NULL);
557  ci;
558  ci = cf_item_find_next(features, ci)) {
559  char const *attr;
560 
561  cp = cf_item_to_pair(ci);
562  attr = cf_pair_attr(cp);
563 
564  DEBUG2(" %s%.*s : %s", attr,
565  (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
566  }
567 
568  talloc_free(features);
569 
570  DEBUG2("Server core libs:");
571 
572  for (ci = cf_item_find_next(versions, NULL);
573  ci;
574  ci = cf_item_find_next(versions, ci)) {
575  char const *attr;
576 
577  cp = cf_item_to_pair(ci);
578  attr = cf_pair_attr(cp);
579 
580  DEBUG2(" %s%.*s : %s", attr,
581  (int)(max - talloc_array_length(attr)), spaces, cf_pair_value(cp));
582  }
583 
584 #ifdef WITH_TLS
585  DEBUG3("OpenSSL engines:");
586  for (engine = ENGINE_get_first();
587  engine;
588  engine = ENGINE_get_next(engine)) {
589  engine_id = ENGINE_get_id(engine);
590 
591  DEBUG3(" %s%.*s : %s", engine_id, (int)(max - (strlen(engine_id) + 1)), spaces,
592  ENGINE_get_name(engine));
593  }
594 #endif
595 
596  talloc_free(versions);
597 
598  DEBUG2("Endianness:");
599 #ifdef WORDS_BIGENDIAN
600  DEBUG2(" big");
601 #else
602  DEBUG2(" little");
603 #endif
604 
605  DEBUG2("Compilation flags:");
606 #ifdef BUILT_WITH_CPPFLAGS
607  DEBUG2(" cppflags : " BUILT_WITH_CPPFLAGS);
608 #endif
609 #ifdef BUILT_WITH_CFLAGS
610  DEBUG2(" cflags : " BUILT_WITH_CFLAGS);
611 #endif
612 #ifdef BUILT_WITH_LDFLAGS
613  DEBUG2(" ldflags : " BUILT_WITH_LDFLAGS);
614 #endif
615 #ifdef BUILT_WITH_LIBS
616  DEBUG2(" libs : " BUILT_WITH_LIBS);
617 #endif
618  DEBUG2(" ");
619  }
620  INFO("Copyright (C) 1999-2015 The FreeRADIUS server project and contributors");
621  INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
622  INFO("PARTICULAR PURPOSE");
623  INFO("You may redistribute copies of FreeRADIUS under the terms of the");
624  INFO("GNU General Public License");
625  INFO("For more information about these matters, see the file named COPYRIGHT");
626 
627  fflush(NULL);
628 }
629 
static char const * spaces
Definition: version.c:507
int ssl_check_consistency(void)
Definition: version.c:184
#define DEBUG3(fmt,...)
Definition: log.h:177
#define MAGIC_PREFIX(_x)
Definition: libradius.h:53
int rad_check_lib_magic(uint64_t magic)
Check if the application linking to the library has the correct magic number.
Definition: version.c:208
#define MEM(x)
Definition: radiusd.h:396
#define INFO(fmt,...)
Definition: log.h:143
static char const * name
void cf_pair_add(CONF_SECTION *parent, CONF_PAIR *cp)
Add a configuration pair to a section.
Definition: conffile.c:612
void version_print(void)
Definition: version.c:512
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
#define MAGIC_COMMIT(_x)
Definition: libradius.h:55
char const * ssl_version_by_num(uint32_t version)
Definition: token.h:46
CONF_PAIR * cf_pair_find(CONF_SECTION const *, char const *name)
Definition: conffile.c:3478
char const * cf_pair_value(CONF_PAIR const *pair)
Definition: conffile.c:3506
unsigned int version
Definition: proto_bfd.c:192
int version_add_number(CONF_SECTION *cs, char const *name, char const *version)
Add a library/server version pair to the main configuration.
Definition: version.c:284
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: conffile.c:768
char const * cf_pair_attr(CONF_PAIR const *pair)
Definition: conffile.c:3497
char const * ssl_version_range(uint32_t low, uint32_t high)
static USES_APPLE_DEPRECATED_API uint64_t libmagic
Definition: version.c:30
char const * radiusd_version_short
Definition: version.c:31
char const * ssl_version()
Definition: version.c:193
#define DEBUG2(fmt,...)
Definition: log.h:176
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_PAIR.
Definition: conffile.c:181
Configuration AVP similar to a VALUE_PAIR.
Definition: conffile.c:82
CONF_PAIR * cf_pair_alloc(CONF_SECTION *parent, char const *attr, char const *value, FR_TOKEN op, FR_TOKEN lhs_type, FR_TOKEN rhs_type)
Allocate a CONF_PAIR.
Definition: conffile.c:546
char const * ssl_version_num(void)
Definition: version.c:188
void version_init_numbers(CONF_SECTION *cs)
Initialise core version flags.
Definition: version.c:491
int version_add_feature(CONF_SECTION *cs, char const *name, bool enabled)
Add a feature flag to the main configuration.
Definition: version.c:249
CONF_SECTION * cf_section_alloc(CONF_SECTION *parent, char const *name1, char const *name2)
Allocate a CONF_SECTION.
Definition: conffile.c:626
#define WARN(fmt,...)
Definition: log.h:144
CONF_ITEM * cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item)
Return the next item after a CONF_ITEM.
Definition: conffile.c:3850
void version_init_features(CONF_SECTION *cs)
Initialise core feature flags.
Definition: version.c:313
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
#define RCSID(id)
Definition: build.h:135
#define ERROR(fmt,...)
Definition: log.h:145
#define USES_APPLE_DEPRECATED_API
Definition: build.h:122
#define MAGIC_VERSION(_x)
Definition: libradius.h:54
#define RADIUSD_MAGIC_NUMBER
Definition: libradius.h:51
#define DEBUG_ENABLED2
True if global debug level 1-2 messages are enabled.
Definition: log.h:170