1 /*-
2 * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
3 * Copyright (c) 2003-2007 Tim Kientzle
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "archive_platform.h"
28
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STRING_H
33 #include <string.h>
34 #endif
35 #ifdef HAVE_ZLIB_H
36 #include <zlib.h>
37 #endif
38 #ifdef HAVE_LZMA_H
39 #include <lzma.h>
40 #endif
41 #ifdef HAVE_BZLIB_H
42 #include <bzlib.h>
43 #endif
44 #ifdef HAVE_LZ4_H
45 #include <lz4.h>
46 #endif
47 #ifdef HAVE_ZSTD_H
48 #include <zstd.h>
49 #include <stdio.h>
50 #endif
51 #ifdef HAVE_LZO_LZOCONF_H
52 #include <lzo/lzoconf.h>
53 #endif
54 #if HAVE_LIBXML_XMLVERSION_H
55 #include <libxml/xmlversion.h>
56 #elif HAVE_BSDXML_H
57 #include <bsdxml.h>
58 #elif HAVE_EXPAT_H
59 #include <expat.h>
60 #endif
61 #if HAVE_MBEDTLS_VERSION_H
62 #include <mbedtls/version.h>
63 #endif
64 #if HAVE_NETTLE_VERSION_H
65 #include <nettle/version.h>
66 #include <stdio.h>
67 #endif
68 #if HAVE_OPENSSL_OPENSSLV_H
69 #include <openssl/opensslv.h>
70 #include <stdio.h>
71 #endif
72 #if HAVE_ICONV_H
73 #include <iconv.h>
74 #endif
75 #if HAVE_PCRE_H
76 #include <pcre.h>
77 #endif
78 #if HAVE_PCRE2_H
79 #include <pcre2.h>
80 #endif
81
82 #include "archive.h"
83 #include "archive_private.h"
84 #include "archive_string.h"
85 #include "archive_cryptor_private.h"
86 #include "archive_digest_private.h"
87
88 static void
archive_regex_version(struct archive_string * str)89 archive_regex_version(struct archive_string* str)
90 {
91 #if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
92 archive_strcat(str, " libpcre/");
93 archive_strcat(str, archive_libpcre_version());
94 #elif HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
95 archive_strcat(str, " libpcre2/");
96 archive_strcat(str, archive_libpcre2_version());
97 #else
98 (void)str; /* UNUSED */
99 #endif
100 }
101
102 static void
archive_xml_version(struct archive_string * str)103 archive_xml_version(struct archive_string* str)
104 {
105 #if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2
106 archive_strcat(str, " libxml2/");
107 archive_strcat(str, archive_libxml2_version());
108 #elif HAVE_BSDXML_H && HAVE_LIBBSDXML
109 archive_strcat(str, " bsdxml/");
110 archive_strcat(str, archive_libbsdxml_version());
111 #elif HAVE_EXPAT_H && HAVE_LIBEXPAT
112 archive_strcat(str, " expat/");
113 archive_strcat(str, archive_libexpat_version());
114 #else
115 (void)str; /* UNUSED */
116 #endif
117 }
118
119 static void
archive_libb2_version(struct archive_string * str)120 archive_libb2_version(struct archive_string* str)
121 {
122 archive_strcat(str, " libb2/");
123 #if HAVE_BLAKE2_H && HAVE_LIBB2
124 #if defined(LIBB2_PKGCONFIG_VERSION)
125 archive_strcat(str, LIBB2_PKGCONFIG_VERSION);
126 #else
127 archive_strcat(str, "system");
128 #endif
129 #else
130 archive_strcat(str, "bundled");
131 #endif
132 }
133
134 static void
archive_crypto_version(struct archive_string * str)135 archive_crypto_version(struct archive_string* str)
136 {
137 #if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto)
138 archive_strcat(str, " CommonCrypto/");
139 archive_strcat(str, archive_commoncrypto_version());
140 #endif
141 #if defined(ARCHIVE_CRYPTOR_USE_CNG)
142 archive_strcat(str, " cng/");
143 archive_strcat(str, archive_cng_version());
144 #endif
145 #if defined(ARCHIVE_CRYPTOR_USE_MBED)
146 archive_strcat(str, " mbedtls/");
147 archive_strcat(str, archive_mbedtls_version());
148 #endif
149 #if defined(ARCHIVE_CRYPTOR_USE_NETTLE)
150 archive_strcat(str, " nettle/");
151 archive_strcat(str, archive_nettle_version());
152 #endif
153 #if defined(ARCHIVE_CRYPTOR_USE_OPENSSL)
154 archive_strcat(str, " openssl/");
155 archive_strcat(str, archive_openssl_version());
156 #endif
157 #if defined(ARCHIVE_CRYPTOR_USE_LIBMD)
158 archive_strcat(str, " libmd/");
159 archive_strcat(str, archive_libmd_version());
160 #endif
161 #if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT)
162 archive_strcat(str, " WinCrypt/");
163 archive_strcat(str, archive_wincrypt_version());
164 #endif
165 // Just in case
166 (void)str; /* UNUSED */
167 }
168
169 const char *
archive_version_details(void)170 archive_version_details(void)
171 {
172 static struct archive_string str;
173 static int init = 0;
174 const char *zlib = archive_zlib_version();
175 const char *liblzma = archive_liblzma_version();
176 const char *bzlib = archive_bzlib_version();
177 const char *liblz4 = archive_liblz4_version();
178 const char *libzstd = archive_libzstd_version();
179 const char *liblzo = archive_liblzo2_version();
180 const char *libiconv = archive_libiconv_version();
181 const char *libacl = archive_libacl_version();
182 const char *librichacl = archive_librichacl_version();
183 const char *libattr = archive_libacl_version();
184
185 if (!init) {
186 archive_string_init(&str);
187
188 archive_strcat(&str, ARCHIVE_VERSION_STRING);
189 if (zlib) {
190 archive_strcat(&str, " zlib/");
191 archive_strcat(&str, zlib);
192 }
193 if (liblzma) {
194 archive_strcat(&str, " liblzma/");
195 archive_strcat(&str, liblzma);
196 }
197 if (bzlib) {
198 const char *p = bzlib;
199 const char *sep = strchr(p, ',');
200 if (sep == NULL)
201 sep = p + strlen(p);
202 archive_strcat(&str, " bz2lib/");
203 archive_strncat(&str, p, sep - p);
204 }
205 if (liblz4) {
206 archive_strcat(&str, " liblz4/");
207 archive_strcat(&str, liblz4);
208 }
209 if (libzstd) {
210 archive_strcat(&str, " libzstd/");
211 archive_strcat(&str, libzstd);
212 }
213 if (liblzo) {
214 archive_strcat(&str, " liblzo2/");
215 archive_strcat(&str, liblzo);
216 }
217 archive_xml_version(&str);
218 archive_regex_version(&str);
219 archive_crypto_version(&str);
220 archive_libb2_version(&str);
221 if (librichacl) {
222 archive_strcat(&str, " librichacl/");
223 archive_strcat(&str, librichacl);
224 }
225 if (libacl) {
226 archive_strcat(&str, " libacl/");
227 archive_strcat(&str, libacl);
228 }
229 if (libattr) {
230 archive_strcat(&str, " libattr/");
231 archive_strcat(&str, libattr);
232 }
233 if (libiconv) {
234 archive_strcat(&str, " libiconv/");
235 archive_strcat(&str, libiconv);
236 }
237 }
238 return str.s;
239 }
240
241 const char *
archive_zlib_version(void)242 archive_zlib_version(void)
243 {
244 #if HAVE_ZLIB_H && HAVE_LIBZ
245 return zlibVersion();
246 #else
247 return NULL;
248 #endif
249 }
250
251 const char *
archive_liblzma_version(void)252 archive_liblzma_version(void)
253 {
254 #if HAVE_LZMA_H && HAVE_LIBLZMA
255 return lzma_version_string();
256 #else
257 return NULL;
258 #endif
259 }
260
261 const char *
archive_bzlib_version(void)262 archive_bzlib_version(void)
263 {
264 #if HAVE_BZLIB_H && HAVE_LIBBZ2
265 return BZ2_bzlibVersion();
266 #else
267 return NULL;
268 #endif
269 }
270
271 const char *
archive_liblz4_version(void)272 archive_liblz4_version(void)
273 {
274 #if HAVE_LZ4_H && HAVE_LIBLZ4
275 #if LZ4_VERSION_NUMBER > 10705
276 return LZ4_versionString();
277 #elif LZ4_VERSION_NUMBER > 10300
278 div_t major = div(LZ4_versionNumber(), 10000);
279 div_t minor = div(major.rem, 100);
280 static char lz4_version[9];
281 snprintf(lz4_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
282 return lz4_version;
283 #else
284 #define str(s) #s
285 #define NUMBER(x) str(x)
286 return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
287 #undef NUMBER
288 #undef str
289 #endif
290 #else
291 return NULL;
292 #endif
293 }
294
295 const char *
archive_libzstd_version(void)296 archive_libzstd_version(void)
297 {
298 #if HAVE_ZSTD_H && HAVE_LIBZSTD
299 #if ZSTD_VERSION_NUMBER > 10300
300 return ZSTD_versionString();
301 #else
302 div_t major = div(ZSTD_versionNumber(), 10000);
303 div_t minor = div(major.rem, 100);
304 static char zstd_version[9];
305 snprintf(zstd_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem);
306 return zstd_version;
307 #endif
308 #else
309 return NULL;
310 #endif
311 }
312
313 const char *
archive_liblzo2_version(void)314 archive_liblzo2_version(void)
315 {
316 #if HAVE_LZO_LZOCONF_H && HAVE_LIBLZO2
317 return LZO_VERSION_STRING;
318 #else
319 return NULL;
320 #endif
321 }
322
323 const char *
archive_libbsdxml_version(void)324 archive_libbsdxml_version(void)
325 {
326 #if HAVE_BSDXML_H && HAVE_LIBBSDXML
327 return XML_ExpatVersion();
328 #else
329 return NULL;
330 #endif
331 }
332
333 const char *
archive_libxml2_version(void)334 archive_libxml2_version(void)
335 {
336 #if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2
337 return LIBXML_DOTTED_VERSION;
338 #else
339 return NULL;
340 #endif
341 }
342
343 const char *
archive_libexpat_version(void)344 archive_libexpat_version(void)
345 {
346 #if HAVE_EXPAT_H && HAVE_LIBEXPAT
347 return XML_ExpatVersion();
348 #else
349 return NULL;
350 #endif
351 }
352
353 const char *
archive_mbedtls_version(void)354 archive_mbedtls_version(void)
355 {
356 #if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_CRYPTO_MBED)
357 static char mbed_version[9];
358 mbedtls_version_get_string(mbed_version);
359 return mbed_version;
360 #else
361 return NULL;
362 #endif
363 }
364
365 const char *
archive_nettle_version(void)366 archive_nettle_version(void)
367 {
368 #if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_CRYPTO_NETTLE)
369 static char nettle_version[6];
370 snprintf(nettle_version, 6, "%d.%d", nettle_version_major(), nettle_version_minor());
371 return nettle_version;
372 #else
373 return NULL;
374 #endif
375 }
376
377 const char *
archive_openssl_version(void)378 archive_openssl_version(void)
379 {
380 #if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_CRYPTO_OPENSSL)
381 #ifdef OPENSSL_VERSION_STR
382 return OPENSSL_VERSION_STR;
383 #else
384 #define OPENSSL_MAJOR (OPENSSL_VERSION_NUMBER >> 28)
385 #define OPENSSL_MINOR ((OPENSSL_VERSION_NUMBER >> 20) & 0xFF)
386 static char openssl_version[6];
387 snprintf(openssl_version, 6, "%ld.%ld", OPENSSL_MAJOR, OPENSSL_MINOR);
388 return openssl_version;
389 #undef OPENSSL_MAJOR
390 #undef OPENSSL_MINOR
391 #endif
392 #else
393 return NULL;
394 #endif
395 }
396
397 const char *
archive_libmd_version(void)398 archive_libmd_version(void)
399 {
400 #if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_CRYPTO_LIBMD)
401 return "system";
402 #else
403 return NULL;
404 #endif
405 }
406
407 const char *
archive_commoncrypto_version(void)408 archive_commoncrypto_version(void)
409 {
410 #if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_CRYPTO_CommonCrypto)
411 return "system";
412 #else
413 return NULL;
414 #endif
415 }
416
417 const char *
archive_cng_version(void)418 archive_cng_version(void)
419 {
420 #if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_CRYPTO_CNG)
421 #ifdef BCRYPT_HASH_INTERFACE_MAJORVERSION_2
422 return "2.0";
423 #else
424 return "1.0";
425 #endif
426 #else
427 return NULL;
428 #endif
429 }
430
431 const char *
archive_wincrypt_version(void)432 archive_wincrypt_version(void)
433 {
434 #if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT)
435 HCRYPTPROV prov;
436 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
437 if (GetLastError() != (DWORD)NTE_BAD_KEYSET)
438 return NULL;
439 if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
440 return NULL;
441 }
442 DWORD version, length = sizeof(version);
443 if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) {
444 return NULL;
445 } else {
446 char major = (version >> 8) & 0xFF;
447 char minor = version & 0xFF;
448 static char wincrypt_version[6];
449 snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor);
450 return wincrypt_version;
451 }
452 #else
453 return NULL;
454 #endif
455 }
456
457 const char *
archive_librichacl_version(void)458 archive_librichacl_version(void)
459 {
460 #if HAVE_LIBRICHACL
461 #if defined(LIBRICHACL_PKGCONFIG_VERSION)
462 return LIBRICHACL_PKGCONFIG_VERSION;
463 #else
464 return "system";
465 #endif
466 #else
467 return NULL;
468 #endif
469 }
470
471 const char *
archive_libacl_version(void)472 archive_libacl_version(void)
473 {
474 #if HAVE_LIBACL
475 #if defined(LIBACL_PKGCONFIG_VERSION)
476 return LIBACL_PKGCONFIG_VERSION;
477 #else
478 return "system";
479 #endif
480 #else
481 return NULL;
482 #endif
483 }
484
485 const char *
archive_libattr_version(void)486 archive_libattr_version(void)
487 {
488 #if HAVE_LIBATTR
489 #if defined(LIBATTR_PKGCONFIG_VERSION)
490 return LIBATTR_PKGCONFIG_VERSION;
491 #else
492 return "system";
493 #endif
494 #else
495 return NULL;
496 #endif
497 }
498
499 const char *
archive_libiconv_version(void)500 archive_libiconv_version(void)
501 {
502 #if HAVE_LIBCHARSET && HAVE_ICONV_H
503 char major = _libiconv_version >> 8;
504 char minor = _libiconv_version & 0xFF;
505 static char charset_version[6];
506 snprintf(charset_version, 6, "%hhd.%hhd", major, minor);
507 return charset_version;
508 #else
509 return NULL;
510 #endif
511 }
512
513 const char *
archive_libpcre_version(void)514 archive_libpcre_version(void)
515 {
516 #if HAVE_LIBPCREPOSIX && HAVE_PCRE_H
517 #define str(s) #s
518 #define NUMBER(x) str(x)
519 return NUMBER(PCRE_MAJOR) "." NUMBER(PCRE_MINOR);
520 #undef NUMBER
521 #undef str
522 #else
523 return NULL;
524 #endif
525 }
526
527 const char *
archive_libpcre2_version(void)528 archive_libpcre2_version(void)
529 {
530 #if HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H
531 #define str(s) #s
532 #define NUMBER(x) str(x)
533 return NUMBER(PCRE2_MAJOR) "." NUMBER(PCRE2_MINOR);
534 #undef NUMBER
535 #undef str
536 #else
537 return NULL;
538 #endif
539 }
540