/*- * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA * Copyright (c) 2003-2007 Tim Kientzle * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "archive_platform.h" #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_ZLIB_H #include #endif #ifdef HAVE_LZMA_H #include #endif #ifdef HAVE_BZLIB_H #include #endif #ifdef HAVE_LZ4_H #include #endif #ifdef HAVE_ZSTD_H #include #include #endif #ifdef HAVE_LZO_LZOCONF_H #include #endif #if HAVE_LIBXML_XMLVERSION_H #include #elif HAVE_BSDXML_H #include #elif HAVE_EXPAT_H #include #endif #if HAVE_MBEDTLS_VERSION_H #include #endif #if HAVE_NETTLE_VERSION_H #include #include #endif #if HAVE_OPENSSL_OPENSSLV_H #include #include #endif #if HAVE_ICONV_H #include #endif #if HAVE_PCRE_H #include #endif #if HAVE_PCRE2_H #include #endif #include "archive.h" #include "archive_private.h" #include "archive_string.h" #include "archive_cryptor_private.h" #include "archive_digest_private.h" static void archive_regex_version(struct archive_string* str) { #if HAVE_LIBPCREPOSIX && HAVE_PCRE_H archive_strcat(str, " libpcre/"); archive_strcat(str, archive_libpcre_version()); #elif HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H archive_strcat(str, " libpcre2/"); archive_strcat(str, archive_libpcre2_version()); #else (void)str; /* UNUSED */ #endif } static void archive_xml_version(struct archive_string* str) { #if HAVE_LIBXML_XMLVERSION_H && HAVE_LIBXML2 archive_strcat(str, " libxml2/"); archive_strcat(str, archive_libxml2_version()); #elif HAVE_BSDXML_H && HAVE_LIBBSDXML archive_strcat(str, " bsdxml/"); archive_strcat(str, archive_libbsdxml_version()); #elif HAVE_EXPAT_H && HAVE_LIBEXPAT archive_strcat(str, " expat/"); archive_strcat(str, archive_libexpat_version()); #else (void)str; /* UNUSED */ #endif } static void archive_libb2_version(struct archive_string* str) { archive_strcat(str, " libb2/"); #if HAVE_BLAKE2_H && HAVE_LIBB2 #if defined(LIBB2_PKGCONFIG_VERSION) archive_strcat(str, LIBB2_PKGCONFIG_VERSION); #else archive_strcat(str, "system"); #endif #else archive_strcat(str, "bundled"); #endif } static void archive_crypto_version(struct archive_string* str) { #if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) archive_strcat(str, " CommonCrypto/"); archive_strcat(str, archive_commoncrypto_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_CNG) archive_strcat(str, " cng/"); archive_strcat(str, archive_cng_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_MBED) archive_strcat(str, " mbedtls/"); archive_strcat(str, archive_mbedtls_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_NETTLE) archive_strcat(str, " nettle/"); archive_strcat(str, archive_nettle_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) archive_strcat(str, " openssl/"); archive_strcat(str, archive_openssl_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_LIBMD) archive_strcat(str, " libmd/"); archive_strcat(str, archive_libmd_version()); #endif #if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) archive_strcat(str, " WinCrypt/"); archive_strcat(str, archive_wincrypt_version()); #endif // Just in case (void)str; /* UNUSED */ } const char * archive_version_details(void) { static struct archive_string str; static int init = 0; const char *zlib = archive_zlib_version(); const char *liblzma = archive_liblzma_version(); const char *bzlib = archive_bzlib_version(); const char *liblz4 = archive_liblz4_version(); const char *libzstd = archive_libzstd_version(); const char *liblzo = archive_liblzo2_version(); const char *libiconv = archive_libiconv_version(); const char *libacl = archive_libacl_version(); const char *librichacl = archive_librichacl_version(); const char *libattr = archive_libacl_version(); if (!init) { archive_string_init(&str); archive_strcat(&str, ARCHIVE_VERSION_STRING); if (zlib) { archive_strcat(&str, " zlib/"); archive_strcat(&str, zlib); } if (liblzma) { archive_strcat(&str, " liblzma/"); archive_strcat(&str, liblzma); } if (bzlib) { const char *p = bzlib; const char *sep = strchr(p, ','); if (sep == NULL) sep = p + strlen(p); archive_strcat(&str, " bz2lib/"); archive_strncat(&str, p, sep - p); } if (liblz4) { archive_strcat(&str, " liblz4/"); archive_strcat(&str, liblz4); } if (libzstd) { archive_strcat(&str, " libzstd/"); archive_strcat(&str, libzstd); } if (liblzo) { archive_strcat(&str, " liblzo2/"); archive_strcat(&str, liblzo); } archive_xml_version(&str); archive_regex_version(&str); archive_crypto_version(&str); archive_libb2_version(&str); if (librichacl) { archive_strcat(&str, " librichacl/"); archive_strcat(&str, librichacl); } if (libacl) { archive_strcat(&str, " libacl/"); archive_strcat(&str, libacl); } if (libattr) { archive_strcat(&str, " libattr/"); archive_strcat(&str, libattr); } if (libiconv) { archive_strcat(&str, " libiconv/"); archive_strcat(&str, libiconv); } } return str.s; } const char * archive_zlib_version(void) { #if HAVE_ZLIB_H && HAVE_LIBZ return zlibVersion(); #else return NULL; #endif } const char * archive_liblzma_version(void) { #if HAVE_LZMA_H && HAVE_LIBLZMA return lzma_version_string(); #else return NULL; #endif } const char * archive_bzlib_version(void) { #if HAVE_BZLIB_H && HAVE_LIBBZ2 return BZ2_bzlibVersion(); #else return NULL; #endif } const char * archive_liblz4_version(void) { #if HAVE_LZ4_H && HAVE_LIBLZ4 #if LZ4_VERSION_NUMBER > 10705 return LZ4_versionString(); #elif LZ4_VERSION_NUMBER > 10300 div_t major = div(LZ4_versionNumber(), 10000); div_t minor = div(major.rem, 100); static char lz4_version[9]; snprintf(lz4_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem); return lz4_version; #else #define str(s) #s #define NUMBER(x) str(x) return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE); #undef NUMBER #undef str #endif #else return NULL; #endif } const char * archive_libzstd_version(void) { #if HAVE_ZSTD_H && HAVE_LIBZSTD #if ZSTD_VERSION_NUMBER > 10300 return ZSTD_versionString(); #else div_t major = div(ZSTD_versionNumber(), 10000); div_t minor = div(major.rem, 100); static char zstd_version[9]; snprintf(zstd_version, 9, "%d.%d.%d", major.quot, minor.quot, minor.rem); return zstd_version; #endif #else return NULL; #endif } const char * archive_liblzo2_version(void) { #if HAVE_LZO_LZOCONF_H && HAVE_LIBLZO2 return LZO_VERSION_STRING; #else return NULL; #endif } const char * archive_libbsdxml_version(void) { #if HAVE_BSDXML_H && HAVE_LIBBSDXML return XML_ExpatVersion(); #else return NULL; #endif } const char * archive_libxml2_version(void) { #if HAVE_LIBXML_XMLREADER_H && HAVE_LIBXML2 return LIBXML_DOTTED_VERSION; #else return NULL; #endif } const char * archive_libexpat_version(void) { #if HAVE_EXPAT_H && HAVE_LIBEXPAT return XML_ExpatVersion(); #else return NULL; #endif } const char * archive_mbedtls_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_MBED) || defined(ARCHIVE_CRYPTO_MBED) static char mbed_version[9]; mbedtls_version_get_string(mbed_version); return mbed_version; #else return NULL; #endif } const char * archive_nettle_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_NETTLE) || defined(ARCHIVE_CRYPTO_NETTLE) static char nettle_version[6]; snprintf(nettle_version, 6, "%d.%d", nettle_version_major(), nettle_version_minor()); return nettle_version; #else return NULL; #endif } const char * archive_openssl_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_OPENSSL) || defined(ARCHIVE_CRYPTO_OPENSSL) #ifdef OPENSSL_VERSION_STR return OPENSSL_VERSION_STR; #else #define OPENSSL_MAJOR (OPENSSL_VERSION_NUMBER >> 28) #define OPENSSL_MINOR ((OPENSSL_VERSION_NUMBER >> 20) & 0xFF) static char openssl_version[6]; snprintf(openssl_version, 6, "%ld.%ld", OPENSSL_MAJOR, OPENSSL_MINOR); return openssl_version; #undef OPENSSL_MAJOR #undef OPENSSL_MINOR #endif #else return NULL; #endif } const char * archive_libmd_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_LIBMD) || defined(ARCHIVE_CRYPTO_LIBMD) return "system"; #else return NULL; #endif } const char * archive_commoncrypto_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_Apple_CommonCrypto) || defined(ARCHIVE_CRYPTO_CommonCrypto) return "system"; #else return NULL; #endif } const char * archive_cng_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_CNG) || defined(ARCHIVE_CRYPTO_CNG) #ifdef BCRYPT_HASH_INTERFACE_MAJORVERSION_2 return "2.0"; #else return "1.0"; #endif #else return NULL; #endif } const char * archive_wincrypt_version(void) { #if defined(ARCHIVE_CRYPTOR_USE_WINCRYPT) || defined(ARCHIVE_CRYPTO_WINCRYPT) HCRYPTPROV prov; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { if (GetLastError() != (DWORD)NTE_BAD_KEYSET) return NULL; if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) return NULL; } DWORD version, length = sizeof(version); if (!CryptGetProvParam(prov, PP_VERSION, (BYTE *)&version, &length, 0)) { return NULL; } else { char major = (version >> 8) & 0xFF; char minor = version & 0xFF; static char wincrypt_version[6]; snprintf(wincrypt_version, 6, "%hhd.%hhd", major, minor); return wincrypt_version; } #else return NULL; #endif } const char * archive_librichacl_version(void) { #if HAVE_LIBRICHACL #if defined(LIBRICHACL_PKGCONFIG_VERSION) return LIBRICHACL_PKGCONFIG_VERSION; #else return "system"; #endif #else return NULL; #endif } const char * archive_libacl_version(void) { #if HAVE_LIBACL #if defined(LIBACL_PKGCONFIG_VERSION) return LIBACL_PKGCONFIG_VERSION; #else return "system"; #endif #else return NULL; #endif } const char * archive_libattr_version(void) { #if HAVE_LIBATTR #if defined(LIBATTR_PKGCONFIG_VERSION) return LIBATTR_PKGCONFIG_VERSION; #else return "system"; #endif #else return NULL; #endif } const char * archive_libiconv_version(void) { #if HAVE_LIBCHARSET && HAVE_ICONV_H char major = _libiconv_version >> 8; char minor = _libiconv_version & 0xFF; static char charset_version[6]; snprintf(charset_version, 6, "%hhd.%hhd", major, minor); return charset_version; #else return NULL; #endif } const char * archive_libpcre_version(void) { #if HAVE_LIBPCREPOSIX && HAVE_PCRE_H #define str(s) #s #define NUMBER(x) str(x) return NUMBER(PCRE_MAJOR) "." NUMBER(PCRE_MINOR); #undef NUMBER #undef str #else return NULL; #endif } const char * archive_libpcre2_version(void) { #if HAVE_LIBPCRE2POSIX && HAVE_PCRE2_H #define str(s) #s #define NUMBER(x) str(x) return NUMBER(PCRE2_MAJOR) "." NUMBER(PCRE2_MINOR); #undef NUMBER #undef str #else return NULL; #endif }