diff -r 000000000000 -r 1918ee327afb src/network/ssl/qsslsocket_openssl_symbols.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp Mon Jan 11 14:00:40 2010 +0000 @@ -0,0 +1,828 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qsslsocket_openssl_symbols_p.h" + +#include +#include +#include +#include +#if defined(Q_OS_UNIX) +#include +#endif + +QT_BEGIN_NAMESPACE + +/* + Note to maintainer: + ------------------- + + We load OpenSSL symbols dynamically. Because symbols are known to + disappear, and signatures sometimes change, between releases, we need to + be careful about how this is done. To ensure we don't end up dereferencing + null function pointers, and continue running even if certain functions are + missing, we define helper functions for each of the symbols we load from + OpenSSL, all prefixed with "q_" (declared in + qsslsocket_openssl_symbols_p.h). So instead of calling SSL_connect + directly, we call q_SSL_connect, which is a function that checks if the + actual SSL_connect fptr is null, and returns a failure if it is, or calls + SSL_connect if it isn't. + + This requires a somewhat tedious process of declaring each function we + want to call in OpenSSL thrice: once with the q_, in _p.h, once using the + DEFINEFUNC macros below, and once in the function that actually resolves + the symbols, below the DEFINEFUNC declarations below. + + There's one DEFINEFUNC macro declared for every number of arguments + exposed by OpenSSL (feel free to extend when needed). The easiest thing to + do is to find an existing entry that matches the arg count of the function + you want to import, and do the same. + + The first macro arg is the function return type. The second is the + verbatim name of the function/symbol. Then follows a list of N pairs of + argument types with a variable name, and just the variable name (char *a, + a, char *b, b, etc). Finally there's two arguments - a suitable return + statement for the error case (for an int function, return 0 or return -1 + is usually right). Then either just "return" or DUMMYARG, the latter being + for void functions. + + Note: Take into account that these macros and declarations are processed + at compile-time, and the result depends on the OpenSSL headers the + compiling host has installed, but the symbols are resolved at run-time, + possibly with a different version of OpenSSL. +*/ + +#ifdef SSLEAY_MACROS +DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return) +#endif +DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return) +DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return) +DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return) +DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return) +DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return) +DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return) +DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return) +DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return) +DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return) +DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return) +DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return) +DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG) +DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG) +DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG) +DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER < 0x00908000L +DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, unsigned char **b, b, long c, c, return 0, return) +#else // 0.9.8 broke SC and BC by changing this signature. +DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return) +#endif +DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return) +DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) +DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) +DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) +DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) +DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return) +DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) +#ifdef SSLEAY_MACROS +DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) +DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) +#else +DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +#endif +DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) +DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) +DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) +DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) +DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) +DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) +DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return) +DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG) +DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return) +#else +DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG) +DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return) +#endif +DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return) +DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return) +DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return) +DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return) +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +// 0.9.8 broke SC and BC by changing this function's signature. +DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return) +#else +DEFINEFUNC(int, SSL_CTX_check_private_key, SSL_CTX *a, a, return -1, return) +#endif +DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return) +DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return) +#else +DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return) +#endif +DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return) +DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return) +DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG) +DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUMMYARG) +DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return) +DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) +DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return) +DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) +DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) +DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +// 0.9.8 broke SC and BC by changing this function's signature. +DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return) +#else +DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, SSL *a, a, return 0, return) +#endif +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return) +#else +DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return) +#endif +DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) +DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return) +DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return) +#if OPENSSL_VERSION_NUMBER >= 0x00908000L +// 0.9.8 broke SC and BC by changing this function's signature. +DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) +#else +DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return) +#endif +DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return) +DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG) +DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return) +DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return) +DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG) +DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG) +DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG) +DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return) +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return) +#else +DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return) +#endif +DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return) +DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return) +#ifndef SSLEAY_MACROS +DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return) +#endif +DEFINEFUNC(ASN1_OBJECT *, X509_EXTENSION_get_object, X509_EXTENSION *a, a, return 0, return) +DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG) +DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return 0, return) +DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return) +DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return 0, return) +DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return) +DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return) +DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return) +DEFINEFUNC3(char *, X509_NAME_oneline, X509_NAME *a, a, char *b, b, int c, c, return 0, return) +DEFINEFUNC(EVP_PKEY *, X509_PUBKEY_get, X509_PUBKEY *a, a, return 0, return) +DEFINEFUNC(void, X509_STORE_free, X509_STORE *a, a, return, DUMMYARG) +DEFINEFUNC(X509_STORE *, X509_STORE_new, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC2(int, X509_STORE_add_cert, X509_STORE *a, a, X509 *b, b, return 0, return) +DEFINEFUNC(void, X509_STORE_CTX_free, X509_STORE_CTX *a, a, return, DUMMYARG) +DEFINEFUNC4(int, X509_STORE_CTX_init, X509_STORE_CTX *a, a, X509_STORE *b, b, X509 *c, c, STACK_OF(X509) *d, d, return -1, return) +DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, return -1, return) +DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return) +#ifdef SSLEAY_MACROS +DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return) +DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return) +DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return) +DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return) +#endif +DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG) +DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG) + +#ifdef Q_OS_SYMBIAN +#define RESOLVEFUNC(func, ordinal, lib) \ + if (!(_q_##func = _q_PTR_##func(lib->resolve(#ordinal)))) \ + qWarning("QSslSocket: cannot resolve "#func); +#else +#define RESOLVEFUNC(func) \ + if (!(_q_##func = _q_PTR_##func(libs.first->resolve(#func))) \ + && !(_q_##func = _q_PTR_##func(libs.second->resolve(#func)))) \ + qWarning("QSslSocket: cannot resolve "#func); +#endif + +#if !defined QT_LINKED_OPENSSL + +#ifdef QT_NO_LIBRARY +bool q_resolveOpenSslSymbols() +{ + qWarning("QSslSocket: unable to resolve symbols. " + "QT_NO_LIBRARY is defined which means runtime resolving of " + "libraries won't work."); + qWarning("Either compile Qt statically or with support for runtime resolving " + "of libraries."); + return false; +} +#else + +# ifdef Q_OS_UNIX +static bool libGreaterThan(const QString &lhs, const QString &rhs) +{ + QStringList lhsparts = lhs.split(QLatin1Char('.')); + QStringList rhsparts = rhs.split(QLatin1Char('.')); + Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1); + + for (int i = 1; i < rhsparts.count(); ++i) { + if (lhsparts.count() <= i) + // left hand side is shorter, so it's less than rhs + return false; + + bool ok = false; + int b = 0; + int a = lhsparts.at(i).toInt(&ok); + if (ok) + b = rhsparts.at(i).toInt(&ok); + if (ok) { + // both toInt succeeded + if (a == b) + continue; + return a > b; + } else { + // compare as strings; + if (lhsparts.at(i) == rhsparts.at(i)) + continue; + return lhsparts.at(i) > rhsparts.at(i); + } + } + + // they compared strictly equally so far + // lhs cannot be less than rhs + return true; +} + +static QStringList findAllLibSsl() +{ + QStringList paths; +# ifdef Q_OS_DARWIN + paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")) + .split(QLatin1Char(':'), QString::SkipEmptyParts); +# else + paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")) + .split(QLatin1Char(':'), QString::SkipEmptyParts); +# endif + paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib"); + + QStringList foundSsls; + foreach (const QString &path, paths) { + QDir dir = QDir(path); + QStringList entryList = dir.entryList(QStringList() << QLatin1String("libssl.*"), QDir::Files); + + qSort(entryList.begin(), entryList.end(), libGreaterThan); + foreach (const QString &entry, entryList) + foundSsls << path + QLatin1Char('/') + entry; + } + + return foundSsls; +} +# endif + +static QPair loadOpenSsl() +{ + QPair pair; + pair.first = 0; + pair.second = 0; + +# ifdef Q_OS_WIN + QLibrary *ssleay32 = new QLibrary(QLatin1String("ssleay32")); + if (!ssleay32->load()) { + // Cannot find ssleay32.dll + delete ssleay32; + return pair; + } + + QLibrary *libeay32 = new QLibrary(QLatin1String("libeay32")); + if (!libeay32->load()) { + delete ssleay32; + delete libeay32; + return pair; + } + + pair.first = ssleay32; + pair.second = libeay32; + return pair; +# elif defined(Q_OS_SYMBIAN) + QLibrary *libssl = new QLibrary(QLatin1String("libssl")); + if (!libssl->load()) { + // Cannot find ssleay32.dll + delete libssl; + return pair; + } + + QLibrary *libcrypto = new QLibrary(QLatin1String("libcrypto")); + if (!libcrypto->load()) { + delete libcrypto; + delete libssl; + return pair; + } + + pair.first = libssl; + pair.second = libcrypto; + return pair; +# elif defined(Q_OS_UNIX) + QLibrary *&libssl = pair.first; + QLibrary *&libcrypto = pair.second; + libssl = new QLibrary; + libcrypto = new QLibrary; + + // Try to find the libssl library on the system. + // + // Up until Qt 4.3, this only searched for the "ssl" library at version -1, that + // is, libssl.so on most Unix systems. However, the .so file isn't present in + // user installations because it's considered a development file. + // + // The right thing to do is to load the library at the major version we know how + // to work with: the SHLIB_VERSION_NUMBER version (macro defined in opensslv.h) + // + // However, OpenSSL is a well-known case of binary-compatibility breakage. To + // avoid such problems, many system integrators and Linux distributions change + // the soname of the binary, letting the full version number be the soname. So + // we'll find libssl.so.0.9.7, libssl.so.0.9.8, etc. in the system. For that + // reason, we will search a few common paths (see findAllLibSsl() above) in hopes + // we find one that works. + // + // It is important, however, to try the canonical name and the unversioned name + // without going through the loop. By not specifying a path, we let the system + // dlopen(3) function determine it for us. This will include any DT_RUNPATH or + // DT_RPATH tags on our library header as well as other system-specific search + // paths. See the man page for dlopen(3) on your system for more information. + +#ifdef Q_OS_OPENBSD + libcrypto->setLoadHints(QLibrary::ExportExternalSymbolsHint); +#endif +#ifdef SHLIB_VERSION_NUMBER + // first attempt: the canonical name is libssl.so. + libssl->setFileNameAndVersion(QLatin1String("ssl"), QLatin1String(SHLIB_VERSION_NUMBER)); + libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER)); + if (libcrypto->load() && libssl->load()) { + // libssl.so. and libcrypto.so. found + return pair; + } else { + libssl->unload(); + libcrypto->unload(); + } +#endif + + // second attempt: find the development files libssl.so and libcrypto.so + libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); + libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); + if (libcrypto->load() && libssl->load()) { + // libssl.so.0 and libcrypto.so.0 found + return pair; + } else { + libssl->unload(); + libcrypto->unload(); + } + + // third attempt: loop on the most common library paths and find libssl + QStringList sslList = findAllLibSsl(); + foreach (const QString &ssl, sslList) { + QString crypto = ssl; + crypto.replace(QLatin1String("ssl"), QLatin1String("crypto")); + libssl->setFileNameAndVersion(ssl, -1); + libcrypto->setFileNameAndVersion(crypto, -1); + if (libcrypto->load() && libssl->load()) { + // libssl.so.0 and libcrypto.so.0 found + return pair; + } else { + libssl->unload(); + libcrypto->unload(); + } + } + + // failed to load anything + delete libssl; + delete libcrypto; + libssl = libcrypto = 0; + return pair; + +# else + // not implemented for this platform yet + return pair; +# endif +} + +bool q_resolveOpenSslSymbols() +{ + static volatile bool symbolsResolved = false; + static volatile bool triedToResolveSymbols = false; +#ifndef QT_NO_THREAD + QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init)); +#endif + if (symbolsResolved) + return true; + if (triedToResolveSymbols) + return false; + triedToResolveSymbols = true; + + QPair libs = loadOpenSsl(); + if (!libs.first || !libs.second) + // failed to load them + return false; + +#ifdef Q_OS_SYMBIAN +#ifdef SSLEAY_MACROS + RESOLVEFUNC(ASN1_dup, 125, libs.second ) +#endif + RESOLVEFUNC(ASN1_INTEGER_get, 48, libs.second ) + RESOLVEFUNC(ASN1_STRING_data, 71, libs.second ) + RESOLVEFUNC(ASN1_STRING_length, 76, libs.second ) + RESOLVEFUNC(BIO_ctrl, 184, libs.second ) + RESOLVEFUNC(BIO_free, 209, libs.second ) + RESOLVEFUNC(BIO_new, 222, libs.second ) + RESOLVEFUNC(BIO_new_mem_buf, 230, libs.second ) + RESOLVEFUNC(BIO_read, 244, libs.second ) + RESOLVEFUNC(BIO_s_mem, 251, libs.second ) + RESOLVEFUNC(BIO_write, 269, libs.second ) + RESOLVEFUNC(BN_num_bits, 387, libs.second ) + RESOLVEFUNC(CRYPTO_free, 469, libs.second ) + RESOLVEFUNC(CRYPTO_num_locks, 500, libs.second ) + RESOLVEFUNC(CRYPTO_set_id_callback, 513, libs.second ) + RESOLVEFUNC(CRYPTO_set_locking_callback, 516, libs.second ) + RESOLVEFUNC(DSA_free, 594, libs.second ) + RESOLVEFUNC(ERR_error_string, 744, libs.second ) + RESOLVEFUNC(ERR_get_error, 749, libs.second ) + RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second ) + RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second ) + RESOLVEFUNC(EVP_PKEY_free, 867, libs.second ) + RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second ) + RESOLVEFUNC(EVP_PKEY_get1_RSA, 870, libs.second ) + RESOLVEFUNC(EVP_PKEY_new, 876, libs.second ) + RESOLVEFUNC(EVP_PKEY_type, 882, libs.second ) + RESOLVEFUNC(OBJ_nid2sn, 1036, libs.second ) + RESOLVEFUNC(OBJ_obj2nid, 1037, libs.second ) +#ifdef SSLEAY_MACROS // ### verify + RESOLVEFUNC(PEM_ASN1_read_bio, 1180, libs.second ) +#else + RESOLVEFUNC(PEM_read_bio_DSAPrivateKey, 1219, libs.second ) + RESOLVEFUNC(PEM_read_bio_RSAPrivateKey, 1228, libs.second ) + RESOLVEFUNC(PEM_write_bio_DSAPrivateKey, 1260, libs.second ) + RESOLVEFUNC(PEM_write_bio_RSAPrivateKey, 1271, libs.second ) +#endif + RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY, 1220, libs.second ) + RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY, 1230, libs.second ) + RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY, 1261, libs.second ) + RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY, 1273, libs.second ) + RESOLVEFUNC(RAND_seed, 1426, libs.second ) + RESOLVEFUNC(RAND_status, 1429, libs.second ) + RESOLVEFUNC(RSA_free, 1450, libs.second ) + RESOLVEFUNC(sk_free, 2571, libs.second ) + RESOLVEFUNC(sk_num, 2576, libs.second ) + RESOLVEFUNC(sk_pop_free, 2578, libs.second ) + RESOLVEFUNC(sk_value, 2585, libs.second ) + RESOLVEFUNC(SSL_CIPHER_description, 11, libs.first ) + RESOLVEFUNC(SSL_CTX_check_private_key, 21, libs.first ) + RESOLVEFUNC(SSL_CTX_ctrl, 22, libs.first ) + RESOLVEFUNC(SSL_CTX_free, 24, libs.first ) + RESOLVEFUNC(SSL_CTX_new, 35, libs.first ) + RESOLVEFUNC(SSL_CTX_set_cipher_list, 40, libs.first ) + RESOLVEFUNC(SSL_CTX_set_default_verify_paths, 44, libs.first ) + RESOLVEFUNC(SSL_CTX_set_verify, 56, libs.first ) + RESOLVEFUNC(SSL_CTX_set_verify_depth, 57, libs.first ) + RESOLVEFUNC(SSL_CTX_use_certificate, 64, libs.first ) + RESOLVEFUNC(SSL_CTX_use_certificate_file, 67, libs.first ) + RESOLVEFUNC(SSL_CTX_use_PrivateKey, 58, libs.first ) + RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey, 61, libs.first ) + RESOLVEFUNC(SSL_CTX_use_PrivateKey_file, 60, libs.first ) + RESOLVEFUNC(SSL_accept, 82, libs.first ) + RESOLVEFUNC(SSL_clear, 92, libs.first ) + RESOLVEFUNC(SSL_connect, 93, libs.first ) + RESOLVEFUNC(SSL_free, 99, libs.first ) + RESOLVEFUNC(SSL_get_ciphers, 104, libs.first ) + RESOLVEFUNC(SSL_get_current_cipher, 106, libs.first ) + RESOLVEFUNC(SSL_get_error, 110, libs.first ) + RESOLVEFUNC(SSL_get_peer_cert_chain, 117, libs.first ) + RESOLVEFUNC(SSL_get_peer_certificate, 118, libs.first ) + RESOLVEFUNC(SSL_get_verify_result, 132, libs.first ) + RESOLVEFUNC(SSL_library_init, 137, libs.first ) + RESOLVEFUNC(SSL_load_error_strings, 139, libs.first ) + RESOLVEFUNC(SSL_new, 140, libs.first ) + RESOLVEFUNC(SSL_read, 143, libs.first ) + RESOLVEFUNC(SSL_set_accept_state, 148, libs.first ) + RESOLVEFUNC(SSL_set_bio, 149, libs.first ) + RESOLVEFUNC(SSL_set_connect_state, 152, libs.first ) + RESOLVEFUNC(SSL_shutdown, 173, libs.first ) + RESOLVEFUNC(SSL_write, 188, libs.first ) + RESOLVEFUNC(SSLv2_client_method, 192, libs.first ) + RESOLVEFUNC(SSLv3_client_method, 195, libs.first ) + RESOLVEFUNC(SSLv23_client_method, 189, libs.first ) + RESOLVEFUNC(TLSv1_client_method, 198, libs.first ) + RESOLVEFUNC(SSLv2_server_method, 194, libs.first ) + RESOLVEFUNC(SSLv3_server_method, 197, libs.first ) + RESOLVEFUNC(SSLv23_server_method, 191, libs.first ) + RESOLVEFUNC(TLSv1_server_method, 200, libs.first ) + RESOLVEFUNC(X509_NAME_oneline, 1830, libs.second ) + RESOLVEFUNC(X509_PUBKEY_get, 1844, libs.second ) + RESOLVEFUNC(X509_STORE_free, 1939, libs.second ) + RESOLVEFUNC(X509_STORE_new, 1942, libs.second ) + RESOLVEFUNC(X509_STORE_add_cert, 1936, libs.second ) + RESOLVEFUNC(X509_STORE_CTX_free, 1907, libs.second ) + RESOLVEFUNC(X509_STORE_CTX_init, 1919, libs.second ) + RESOLVEFUNC(X509_STORE_CTX_new, 1920, libs.second ) + RESOLVEFUNC(X509_STORE_CTX_set_purpose, 1931, libs.second ) + RESOLVEFUNC(X509_cmp, 1992, libs.second ) +#ifndef SSLEAY_MACROS + RESOLVEFUNC(X509_dup, 1997, libs.second ) +#endif + RESOLVEFUNC(X509_EXTENSION_get_object, 1785, libs.second ) + RESOLVEFUNC(X509_free, 2001, libs.second ) + RESOLVEFUNC(X509_get_ext, 2012, libs.second ) + RESOLVEFUNC(X509_get_ext_count, 2016, libs.second ) + RESOLVEFUNC(X509_get_ext_d2i, 2017, libs.second ) + RESOLVEFUNC(X509_get_issuer_name, 2018, libs.second ) + RESOLVEFUNC(X509_get_subject_name, 2022, libs.second ) + RESOLVEFUNC(X509_verify_cert, 2069, libs.second ) + RESOLVEFUNC(d2i_X509, 2309, libs.second ) + RESOLVEFUNC(i2d_X509, 2489, libs.second ) +#ifdef SSLEAY_MACROS + RESOLVEFUNC(i2d_DSAPrivateKey, 2395, libs.second ) + RESOLVEFUNC(i2d_RSAPrivateKey, 2476, libs.second ) + RESOLVEFUNC(d2i_DSAPrivateKey, 2220, libs.second ) + RESOLVEFUNC(d2i_RSAPrivateKey, 2296, libs.second ) +#endif + RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf, 1153, libs.second ) + RESOLVEFUNC(OPENSSL_add_all_algorithms_conf, 1152, libs.second ) +#else // Q_OS_SYMBIAN +#ifdef SSLEAY_MACROS + RESOLVEFUNC(ASN1_dup) +#endif + RESOLVEFUNC(ASN1_INTEGER_get) + RESOLVEFUNC(ASN1_STRING_data) + RESOLVEFUNC(ASN1_STRING_length) + RESOLVEFUNC(BIO_ctrl) + RESOLVEFUNC(BIO_free) + RESOLVEFUNC(BIO_new) + RESOLVEFUNC(BIO_new_mem_buf) + RESOLVEFUNC(BIO_read) + RESOLVEFUNC(BIO_s_mem) + RESOLVEFUNC(BIO_write) + RESOLVEFUNC(BN_num_bits) + RESOLVEFUNC(CRYPTO_free) + RESOLVEFUNC(CRYPTO_num_locks) + RESOLVEFUNC(CRYPTO_set_id_callback) + RESOLVEFUNC(CRYPTO_set_locking_callback) + RESOLVEFUNC(DSA_free) + RESOLVEFUNC(ERR_error_string) + RESOLVEFUNC(ERR_get_error) + RESOLVEFUNC(EVP_des_ede3_cbc) + RESOLVEFUNC(EVP_PKEY_assign) + RESOLVEFUNC(EVP_PKEY_free) + RESOLVEFUNC(EVP_PKEY_get1_DSA) + RESOLVEFUNC(EVP_PKEY_get1_RSA) + RESOLVEFUNC(EVP_PKEY_new) + RESOLVEFUNC(EVP_PKEY_type) + RESOLVEFUNC(OBJ_nid2sn) + RESOLVEFUNC(OBJ_obj2nid) +#ifdef SSLEAY_MACROS // ### verify + RESOLVEFUNC(PEM_ASN1_read_bio) +#else + RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) + RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) +#endif + RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) + RESOLVEFUNC(RAND_seed) + RESOLVEFUNC(RAND_status) + RESOLVEFUNC(RSA_free) + RESOLVEFUNC(sk_free) + RESOLVEFUNC(sk_num) + RESOLVEFUNC(sk_pop_free) + RESOLVEFUNC(sk_value) + RESOLVEFUNC(SSL_CIPHER_description) + RESOLVEFUNC(SSL_CTX_check_private_key) + RESOLVEFUNC(SSL_CTX_ctrl) + RESOLVEFUNC(SSL_CTX_free) + RESOLVEFUNC(SSL_CTX_new) + RESOLVEFUNC(SSL_CTX_set_cipher_list) + RESOLVEFUNC(SSL_CTX_set_default_verify_paths) + RESOLVEFUNC(SSL_CTX_set_verify) + RESOLVEFUNC(SSL_CTX_set_verify_depth) + RESOLVEFUNC(SSL_CTX_use_certificate) + RESOLVEFUNC(SSL_CTX_use_certificate_file) + RESOLVEFUNC(SSL_CTX_use_PrivateKey) + RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) + RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) + RESOLVEFUNC(SSL_accept) + RESOLVEFUNC(SSL_clear) + RESOLVEFUNC(SSL_connect) + RESOLVEFUNC(SSL_free) + RESOLVEFUNC(SSL_get_ciphers) + RESOLVEFUNC(SSL_get_current_cipher) + RESOLVEFUNC(SSL_get_error) + RESOLVEFUNC(SSL_get_peer_cert_chain) + RESOLVEFUNC(SSL_get_peer_certificate) + RESOLVEFUNC(SSL_get_verify_result) + RESOLVEFUNC(SSL_library_init) + RESOLVEFUNC(SSL_load_error_strings) + RESOLVEFUNC(SSL_new) + RESOLVEFUNC(SSL_read) + RESOLVEFUNC(SSL_set_accept_state) + RESOLVEFUNC(SSL_set_bio) + RESOLVEFUNC(SSL_set_connect_state) + RESOLVEFUNC(SSL_shutdown) + RESOLVEFUNC(SSL_write) + RESOLVEFUNC(SSLv2_client_method) + RESOLVEFUNC(SSLv3_client_method) + RESOLVEFUNC(SSLv23_client_method) + RESOLVEFUNC(TLSv1_client_method) + RESOLVEFUNC(SSLv2_server_method) + RESOLVEFUNC(SSLv3_server_method) + RESOLVEFUNC(SSLv23_server_method) + RESOLVEFUNC(TLSv1_server_method) + RESOLVEFUNC(X509_NAME_oneline) + RESOLVEFUNC(X509_PUBKEY_get) + RESOLVEFUNC(X509_STORE_free) + RESOLVEFUNC(X509_STORE_new) + RESOLVEFUNC(X509_STORE_add_cert) + RESOLVEFUNC(X509_STORE_CTX_free) + RESOLVEFUNC(X509_STORE_CTX_init) + RESOLVEFUNC(X509_STORE_CTX_new) + RESOLVEFUNC(X509_STORE_CTX_set_purpose) + RESOLVEFUNC(X509_cmp) +#ifndef SSLEAY_MACROS + RESOLVEFUNC(X509_dup) +#endif + RESOLVEFUNC(X509_EXTENSION_get_object) + RESOLVEFUNC(X509_free) + RESOLVEFUNC(X509_get_ext) + RESOLVEFUNC(X509_get_ext_count) + RESOLVEFUNC(X509_get_ext_d2i) + RESOLVEFUNC(X509_get_issuer_name) + RESOLVEFUNC(X509_get_subject_name) + RESOLVEFUNC(X509_verify_cert) + RESOLVEFUNC(d2i_X509) + RESOLVEFUNC(i2d_X509) +#ifdef SSLEAY_MACROS + RESOLVEFUNC(i2d_DSAPrivateKey) + RESOLVEFUNC(i2d_RSAPrivateKey) + RESOLVEFUNC(d2i_DSAPrivateKey) + RESOLVEFUNC(d2i_RSAPrivateKey) +#endif + RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf) + RESOLVEFUNC(OPENSSL_add_all_algorithms_conf) +#endif // Q_OS_SYMBIAN + symbolsResolved = true; + delete libs.first; + delete libs.second; + return true; +} +#endif // QT_NO_LIBRARY + +#else // !defined QT_LINKED_OPENSSL + +bool q_resolveOpenSslSymbols() +{ +#ifdef QT_NO_SSL + return false; +#endif + return true; +} +#endif // !defined QT_LINKED_OPENSSL + +//============================================================================== +// contributed by Jay Case of Sarvega, Inc.; http://sarvega.com/ +// Based on X509_cmp_time() for intitial buffer hacking. +//============================================================================== +QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) +{ + char lBuffer[24]; + char *pBuffer = lBuffer; + + size_t lTimeLength = aTime->length; + char *pString = (char *) aTime->data; + + if (aTime->type == V_ASN1_UTCTIME) { + if ((lTimeLength < 11) || (lTimeLength > 17)) + return QDateTime(); + + memcpy(pBuffer, pString, 10); + pBuffer += 10; + pString += 10; + } else { + if (lTimeLength < 13) + return QDateTime(); + + memcpy(pBuffer, pString, 12); + pBuffer += 12; + pString += 12; + } + + if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) { + *pBuffer++ = '0'; + *pBuffer++ = '0'; + } else { + *pBuffer++ = *pString++; + *pBuffer++ = *pString++; + // Skip any fractional seconds... + if (*pString == '.') { + pString++; + while ((*pString >= '0') && (*pString <= '9')) + pString++; + } + } + + *pBuffer++ = 'Z'; + *pBuffer++ = '\0'; + + time_t lSecondsFromUCT; + if (*pString == 'Z') { + lSecondsFromUCT = 0; + } else { + if ((*pString != '+') && (*pString != '-')) + return QDateTime(); + + lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60; + lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0'); + lSecondsFromUCT *= 60; + if (*pString == '-') + lSecondsFromUCT = -lSecondsFromUCT; + } + + tm lTime; + lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0'); + lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0'); + lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0'); + lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0'); + lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1; + lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0'); + if (lTime.tm_year < 50) + lTime.tm_year += 100; // RFC 2459 + + QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday); + QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec); + QDateTime result(resDate, resTime, Qt::UTC); + result = result.addSecs(lSecondsFromUCT); + return result; +} + +QT_END_NAMESPACE