Decode status nibble
[freeradius.git] / src / main / version.c
1 /*
2  * version.c    Print version number and exit.
3  *
4  * Version:     $Id$
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$")
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
32 #ifdef HAVE_OPENSSL_CRYPTO_H
33 #  include <openssl/crypto.h>
34 #  include <openssl/opensslv.h>
35
36 static long ssl_built = OPENSSL_VERSION_NUMBER;
37
38 /** Check built and linked versions of OpenSSL match
39  *
40  * OpenSSL version number consists of:
41  * MNNFFPPS: major minor fix patch status
42  *
43  * Where status >= 0 && < 10 means beta, and status 10 means release.
44  *
45  * Startup check for whether the linked version of OpenSSL matches the
46  * version the server was built against.
47  *
48  * @return 0 if ok, else -1
49  */
50 int ssl_check_consistency(void)
51 {
52         long ssl_linked;
53
54         ssl_linked = SSLeay();
55
56         /*
57          *      Status mismatch always triggers error.
58          */
59         if ((ssl_linked & 0x0000000f) != (ssl_built & 0x0000000f)) {
60         mismatch:
61                 ERROR("libssl version mismatch.  built: %lx linked: %lx",
62                       (unsigned long) ssl_built,
63                       (unsigned long) ssl_linked);
64
65                 return -1;
66         }
67
68         /*
69          *      Use the OpenSSH approach and relax fix checks after version
70          *      1.0.0 and only allow moving backwards within a patch
71          *      series.
72          */
73         if (ssl_built & 0xf00000000) {
74                 if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000) ||
75                     (ssl_built & 0x00000ff0) > (ssl_linked & 0x00000ff0)) goto mismatch;
76         /*
77          *      Before 1.0.0 we require the same major minor and fix version
78          *      and ignore the patch number.
79          */
80         } else if ((ssl_built & 0xfffff000) != (ssl_linked & 0xfffff000)) goto mismatch;
81
82         return 0;
83 }
84
85 /** Convert a version number to a text string
86  *
87  * @note Not thread safe.
88  *
89  * @param v version to convert.
90  * @return pointer to a static buffer containing the version string.
91  */
92 char const *ssl_version_by_num(uint32_t v)
93 {
94         /* 2 (%s) + 1 (.) + 2 (%i) + 1 (.) + 2 (%i) + 1 (c) + 8 (%s) + \0 */
95         static char buffer[18];
96         char *p = buffer;
97
98         p += sprintf(p, "%u.%u.%u",
99                      (0xf0000000 & v) >> 28,
100                      (0x0ff00000 & v) >> 20,
101                      (0x000ff000 & v) >> 12);
102
103         if ((0x00000ff0 & v) >> 4) {
104                 *p++ =  (char) (0x60 + ((0x00000ff0 & v) >> 4));
105         }
106
107         *p++ = ' ';
108
109         /*
110          *      Development (0)
111          */
112         if ((0x0000000f & v) == 0) {
113                 strcpy(p, "dev");
114         /*
115          *      Beta (1-14)
116          */
117         } else if ((0x0000000f & v) <= 14) {
118                 sprintf(p, "beta %u", 0x0000000f & v);
119         } else {
120                 strcpy(p, "release");
121         }
122
123         return buffer;
124 }
125
126 /** Convert two openssl version numbers into a range string
127  *
128  * @note Not thread safe.
129  *
130  * @param low version to convert.
131  * @param high version to convert.
132  * @return pointer to a static buffer containing the version range string.
133  */
134 char const *ssl_version_range(uint32_t low, uint32_t high)
135 {
136         /* 12 (version) + 3 ( - ) + 12 (version) */
137         static char buffer[28];
138         char *p = buffer;
139
140         p += strlcpy(p, ssl_version_by_num(low), sizeof(buffer));
141         p += strlcpy(p, " - ", sizeof(buffer) - (p - buffer));
142         strlcpy(p, ssl_version_by_num(high), sizeof(buffer) - (p - buffer));
143
144         return buffer;
145 }
146
147 /** Print the current linked version of Openssl
148  *
149  * Print the currently linked version of the OpenSSL library.
150  *
151  * @note Not thread safe.
152  * @return pointer to a static buffer containing libssl version information.
153  */
154 char const *ssl_version(void)
155 {
156         static char buffer[256];
157
158         uint32_t v = SSLeay();
159
160         snprintf(buffer, sizeof(buffer), "%s 0x%.8x (%s)",
161                  SSLeay_version(SSLEAY_VERSION),                /* Not all builds include a useful version number */
162                  v,
163                  ssl_version_by_num(v));
164
165         return buffer;
166 }
167 #  else
168 int ssl_check_consistency(void) {
169         return 0;
170 }
171
172 char const *ssl_version()
173 {
174         return "not linked";
175 }
176 #endif /* ifdef HAVE_OPENSSL_CRYPTO_H */
177
178
179 /** Check if the application linking to the library has the correct magic number
180  *
181  * @param magic number as defined by RADIUSD_MAGIC_NUMBER
182  * @returns 0 on success, -1 on prefix mismatch, -2 on version mismatch -3 on commit mismatch.
183  */
184 int rad_check_lib_magic(uint64_t magic)
185 {
186         if (MAGIC_PREFIX(magic) != MAGIC_PREFIX(libmagic)) {
187                 ERROR("Application and libfreeradius-server magic number (prefix) mismatch."
188                       "  application: %x library: %x",
189                       MAGIC_PREFIX(magic), MAGIC_PREFIX(libmagic));
190                 return -1;
191         }
192
193         if (MAGIC_VERSION(magic) != MAGIC_VERSION(libmagic)) {
194                 ERROR("Application and libfreeradius-server magic number (version) mismatch."
195                       "  application: %lx library: %lx",
196                       (unsigned long) MAGIC_VERSION(magic), (unsigned long) MAGIC_VERSION(libmagic));
197                 return -2;
198         }
199
200         if (MAGIC_COMMIT(magic) != MAGIC_COMMIT(libmagic)) {
201                 ERROR("Application and libfreeradius-server magic number (commit) mismatch."
202                       "  application: %lx library: %lx",
203                       (unsigned long) MAGIC_COMMIT(magic), (unsigned long) MAGIC_COMMIT(libmagic));
204                 return -3;
205         }
206
207         return 0;
208 }
209
210 /*
211  *      Display the revision number for this program
212  */
213 void version(void)
214 {
215         INFO("%s: %s", progname, radiusd_version);
216
217         DEBUG3("Server was built with: ");
218
219 #ifdef WITH_ACCOUNTING
220         DEBUG3("  accounting");
221 #endif
222         DEBUG3("  authentication"); /* always enabled */
223
224 #ifdef WITH_ASCEND_BINARY
225         DEBUG3("  ascend binary attributes");
226 #endif
227 #ifdef WITH_COA
228         DEBUG3("  coa");
229 #endif
230 #ifdef WITH_COMMAND_SOCKET
231         DEBUG3("  control-socket");
232 #endif
233 #ifdef WITH_DETAIL
234         DEBUG3("  detail");
235 #endif
236 #ifdef WITH_DHCP
237         DEBUG3("  dhcp");
238 #endif
239 #ifdef WITH_DYNAMIC_CLIENTS
240         DEBUG3("  dynamic clients");
241 #endif
242 #ifdef OSFC2
243         DEBUG3("  OSFC2");
244 #endif
245 #ifdef WITH_PROXY
246         DEBUG3("  proxy");
247 #endif
248 #ifdef HAVE_PCRE
249         DEBUG3("  regex-pcre");
250 #else
251 #  ifdef HAVE_REGEX
252 #    ifdef HAVE_REG_EXTENDED
253         DEBUG3("  regex-posix-extended");
254 #    else
255         DEBUG3("  regex-posix");
256 #    endif
257 #  endif
258 #endif
259
260 #ifdef WITH_SESSION_MGMT
261         DEBUG3("  session-management");
262 #endif
263 #ifdef WITH_STATS
264         DEBUG3("  stats");
265 #endif
266 #ifdef WITH_TCP
267         DEBUG3("  tcp");
268 #endif
269 #ifdef WITH_THREADS
270         DEBUG3("  threads");
271 #endif
272 #ifdef WITH_TLS
273         DEBUG3("  tls");
274 #endif
275 #ifdef WITH_UNLANG
276         DEBUG3("  unlang");
277 #endif
278 #ifdef WITH_VMPS
279         DEBUG3("  vmps");
280 #endif
281 #ifndef NDEBUG
282         DEBUG3("  developer");
283 #endif
284
285         DEBUG3("Server core libs:");
286         DEBUG3("  talloc : %i.%i.*", talloc_version_major(), talloc_version_minor());
287         DEBUG3("  ssl    : %s", ssl_version());
288
289         DEBUG3("Library magic number:");
290         DEBUG3("  0x%llx", (unsigned long long) libmagic);
291
292         DEBUG3("Endianess:");
293 #if defined(RADIUS_LITTLE_ENDIAN)
294         DEBUG3("  little");
295 #elif defined(RADIUS_BIG_ENDIAN)
296         DEBUG3("  big");
297 #else
298         DEBUG3("  unknown");
299 #endif
300
301         INFO("Copyright (C) 1999-2014 The FreeRADIUS server project and contributors");
302         INFO("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A");
303         INFO("PARTICULAR PURPOSE");
304         INFO("You may redistribute copies of FreeRADIUS under the terms of the");
305         INFO("GNU General Public License");
306         INFO("For more information about these matters, see the file named COPYRIGHT");
307
308         fflush(NULL);
309 }
310