diff --git a/kio/kssl/kopenssl.cpp b/kio/kssl/kopenssl.cpp index e3ca535b25..8f8b921159 100644 --- a/kio/kssl/kopenssl.cpp +++ b/kio/kssl/kopenssl.cpp @@ -1,1590 +1,1784 @@ /* This file is part of the KDE libraries Copyright (C) 2001-2003 George Staikos This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kopenssl.h" #include #include #ifdef KSSL_HAVE_SSL #include #endif #include #include #include #include #include #include #include #include #include extern "C" { #ifdef KSSL_HAVE_SSL static int (*K_SSL_connect) (SSL *) = 0L; static int (*K_SSL_accept) (SSL *) = 0L; static int (*K_SSL_read) (SSL *, void *, int) = 0L; static int (*K_SSL_write) (SSL *, const void *, int) = 0L; static SSL *(*K_SSL_new) (SSL_CTX *) = 0L; static void (*K_SSL_free) (SSL *) = 0L; static int (*K_SSL_shutdown) (SSL *) = 0L; static SSL_CTX *(*K_SSL_CTX_new)(SSL_METHOD *) = 0L; static void (*K_SSL_CTX_free) (SSL_CTX *) = 0L; static int (*K_SSL_set_fd) (SSL *, int) = 0L; static int (*K_SSL_pending) (SSL *) = 0L; static int (*K_SSL_peek) (SSL *, void *, int) = 0L; static int (*K_SSL_CTX_set_cipher_list)(SSL_CTX *, const char *) = 0L; static void (*K_SSL_CTX_set_verify)(SSL_CTX *, int, int (*)(int, X509_STORE_CTX *)) = 0L; static int (*K_SSL_use_certificate)(SSL *, X509 *) = 0L; static SSL_CIPHER *(*K_SSL_get_current_cipher)(SSL *) = 0L; static long (*K_SSL_ctrl) (SSL *,int, long, char *) = 0L; static int (*K_RAND_egd) (const char *) = 0L; static const char* (*K_RAND_file_name) (char *, size_t) = 0L; static int (*K_RAND_load_file) (const char *, long) = 0L; static int (*K_RAND_write_file) (const char *) = 0L; static SSL_METHOD * (*K_TLSv1_client_method) () = 0L; static SSL_METHOD * (*K_SSLv23_client_method) () = 0L; static X509 * (*K_SSL_get_peer_certificate) (SSL *) = 0L; static int (*K_SSL_CIPHER_get_bits) (SSL_CIPHER *,int *) = 0L; static char * (*K_SSL_CIPHER_get_version) (SSL_CIPHER *) = 0L; static const char * (*K_SSL_CIPHER_get_name) (SSL_CIPHER *) = 0L; static char * (*K_SSL_CIPHER_description) (SSL_CIPHER *, char *, int) = 0L; static X509 * (*K_d2i_X509) (X509 **,unsigned char **,long) = 0L; static int (*K_i2d_X509) (X509 *,unsigned char **) = 0L; static int (*K_X509_cmp) (X509 *, X509 *) = 0L; static void (*K_X509_STORE_CTX_free) (X509_STORE_CTX *) = 0L; static int (*K_X509_verify_cert) (X509_STORE_CTX *) = 0L; static X509_STORE_CTX *(*K_X509_STORE_CTX_new) (void) = 0L; static void (*K_X509_STORE_free) (X509_STORE *) = 0L; +static void (*K_X509_STORE_set_verify_cb)(X509_STORE *, int (*)(int, X509_STORE_CTX *)) = 0L; static X509_STORE *(*K_X509_STORE_new) (void) = 0L; static void (*K_X509_free) (X509 *) = 0L; static char *(*K_X509_NAME_oneline) (X509_NAME *,char *,int) = 0L; static X509_NAME *(*K_X509_get_subject_name) (X509 *) = 0L; static X509_NAME *(*K_X509_get_issuer_name) (X509 *) = 0L; +static void (*K_X509_get0_signature)(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *x) = 0L; static X509_LOOKUP *(*K_X509_STORE_add_lookup) (X509_STORE *, X509_LOOKUP_METHOD *) = 0L; static X509_LOOKUP_METHOD *(*K_X509_LOOKUP_file)(void) = 0L; static void (*K_X509_LOOKUP_free)(X509_LOOKUP *) = 0L; static int (*K_X509_LOOKUP_ctrl)(X509_LOOKUP *, int, const char *, long, char **) = 0L; static void (*K_X509_STORE_CTX_init)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *) = 0L; +#if OPENSSL_VERSION_NUMBER < 0x10100000L static void (*K_CRYPTO_free) (void *) = 0L; +#else +static void (*K_CRYPTO_free)(void *, const char *, int) = 0L; +#endif static X509* (*K_X509_dup) (X509 *) = 0L; +static ASN1_TIME *(*K_X509_getm_notBefore)(const X509 *) = 0L; +static ASN1_TIME *(*K_X509_getm_notAfter)(const X509 *) = 0L; static BIO_METHOD *(*K_BIO_s_mem) (void) = 0L; static BIO* (*K_BIO_new) (BIO_METHOD *) = 0L; static BIO* (*K_BIO_new_fp) (FILE *, int) = 0L; static BIO* (*K_BIO_new_mem_buf) (void *, int) = 0L; static int (*K_BIO_free) (BIO *) = 0L; static long (*K_BIO_ctrl) (BIO *,int,long,void *) = 0L; static int (*K_BIO_write) (BIO *b, const void *data, int len) = 0L; static int (*K_PEM_ASN1_write_bio) (int (*)(),const char *,BIO *,char *, const EVP_CIPHER *,unsigned char *,int , pem_password_cb *, void *) = 0L; static int (*K_ASN1_item_i2d_fp)(ASN1_ITEM *,FILE *,unsigned char *) = 0L; static ASN1_ITEM *K_NETSCAPE_X509_it = 0L; static int (*K_X509_print_fp) (FILE *, X509*) = 0L; static int (*K_i2d_PKCS12) (PKCS12*, unsigned char**) = 0L; static int (*K_i2d_PKCS12_fp) (FILE *, PKCS12*) = 0L; static int (*K_PKCS12_newpass) (PKCS12*, char*, char*) = 0L; static PKCS12* (*K_d2i_PKCS12_fp) (FILE*, PKCS12**) = 0L; static PKCS12* (*K_PKCS12_new) (void) = 0L; static void (*K_PKCS12_free) (PKCS12 *) = 0L; static int (*K_PKCS12_parse) (PKCS12*, const char *, EVP_PKEY**, X509**, STACK_OF(X509)**) = 0L; static void (*K_EVP_PKEY_free) (EVP_PKEY *) = 0L; static EVP_PKEY* (*K_EVP_PKEY_new) () = 0L; static void (*K_X509_REQ_free) (X509_REQ *) = 0L; static X509_REQ* (*K_X509_REQ_new) () = 0L; static int (*K_SSL_CTX_use_PrivateKey) (SSL_CTX*, EVP_PKEY*) = 0L; static int (*K_SSL_CTX_use_certificate) (SSL_CTX*, X509*) = 0L; static int (*K_SSL_get_error) (SSL*, int) = 0L; static STACK_OF(X509)* (*K_SSL_get_peer_cert_chain) (SSL*) = 0L; static void (*K_X509_STORE_CTX_set_chain) (X509_STORE_CTX *, STACK_OF(X509)*) = 0L; static void (*K_X509_STORE_CTX_set_purpose) (X509_STORE_CTX *, int) = 0L; -static void (*K_sk_free) (STACK*) = 0L; -static int (*K_sk_num) (STACK*) = 0L; -static char* (*K_sk_pop) (STACK*) = 0L; -static char* (*K_sk_value) (STACK*, int) = 0L; -static STACK* (*K_sk_new) (int (*)()) = 0L; -static int (*K_sk_push) (STACK*, char*) = 0L; -static STACK* (*K_sk_dup) (STACK *) = 0L; +static X509 *(*K_X509_STORE_CTX_get_current_cert)(X509_STORE_CTX *) = 0L; +static void (*K_X509_STORE_CTX_set_error)(X509_STORE_CTX *, int) = 0L; +static int (*K_X509_STORE_CTX_get_error)(X509_STORE_CTX *) = 0L; +static void (*K_OPENSSL_sk_free)(STACK *) = 0L; +static int (*K_OPENSSL_sk_num)(STACK *) = 0L; +static char *(*K_OPENSSL_sk_pop)(STACK *) = 0L; +static char *(*K_OPENSSL_sk_value)(STACK *, int) = 0L; +static STACK *(*K_OPENSSL_sk_new)(int (*)()) = 0L; +static int (*K_OPENSSL_sk_push)(STACK *, char *) = 0L; +static STACK *(*K_OPENSSL_sk_dup)(STACK *) = 0L; static char * (*K_i2s_ASN1_INTEGER) (X509V3_EXT_METHOD *, ASN1_INTEGER *) =0L; static ASN1_INTEGER * (*K_X509_get_serialNumber) (X509 *) = 0L; static EVP_PKEY *(*K_X509_get_pubkey)(X509 *) = 0L; static int (*K_i2d_PublicKey)(EVP_PKEY *, unsigned char **) = 0L; static int (*K_X509_check_private_key)(X509 *, EVP_PKEY *) = 0L; static char * (*K_BN_bn2hex)(const BIGNUM *) = 0L; static int (*K_X509_digest)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *) = 0L; static EVP_MD* (*K_EVP_md5)() = 0L; static void (*K_ASN1_INTEGER_free)(ASN1_INTEGER *) = 0L; static int (*K_OBJ_obj2nid)(ASN1_OBJECT *) = 0L; static const char * (*K_OBJ_nid2ln)(int) = 0L; static int (*K_X509_get_ext_count)(X509*) = 0L; static int (*K_X509_get_ext_by_NID)(X509*, int, int) = 0L; static int (*K_X509_get_ext_by_OBJ)(X509*,ASN1_OBJECT*,int) = 0L; static X509_EXTENSION *(*K_X509_get_ext)(X509*, int loc) = 0L; static X509_EXTENSION *(*K_X509_delete_ext)(X509*, int) = 0L; static int (*K_X509_add_ext)(X509*, X509_EXTENSION*, int) = 0L; static void *(*K_X509_get_ext_d2i)(X509*, int, int*, int*) = 0L; static char *(*K_i2s_ASN1_OCTET_STRING)(X509V3_EXT_METHOD*, ASN1_OCTET_STRING*) = 0L; static int (*K_ASN1_BIT_STRING_get_bit)(ASN1_BIT_STRING*, int) = 0L; static PKCS7 *(*K_PKCS7_new)() = 0L; static void (*K_PKCS7_free)(PKCS7*) = 0L; static void (*K_PKCS7_content_free)(PKCS7*) = 0L; static int (*K_i2d_PKCS7)(PKCS7*, unsigned char**) = 0L; static PKCS7 *(*K_d2i_PKCS7)(PKCS7**, unsigned char**,long) = 0L; static int (*K_i2d_PKCS7_fp)(FILE*,PKCS7*) = 0L; static PKCS7* (*K_d2i_PKCS7_fp)(FILE*,PKCS7**) = 0L; static int (*K_i2d_PKCS7_bio)(BIO *bp,PKCS7 *p7) = 0L; static PKCS7 *(*K_d2i_PKCS7_bio)(BIO *bp,PKCS7 **p7) = 0L; static PKCS7* (*K_PKCS7_dup)(PKCS7*) = 0L; static STACK_OF(X509_NAME) *(*K_SSL_load_client_CA_file)(const char*) = 0L; static STACK_OF(X509_INFO) *(*K_PEM_X509_INFO_read)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void*) = 0L; static char *(*K_ASN1_d2i_fp)(char *(*)(),char *(*)(),FILE*,unsigned char**) = 0L; static X509 *(*K_X509_new)() = 0L; static int (*K_X509_PURPOSE_get_count)() = 0L; static int (*K_X509_PURPOSE_get_id)(X509_PURPOSE *) = 0L; static int (*K_X509_check_purpose)(X509*,int,int) = 0L; static X509_PURPOSE* (*K_X509_PURPOSE_get0)(int) = 0L; static int (*K_EVP_PKEY_assign)(EVP_PKEY*, int, char*) = 0L; +static int (*K_EVP_PKEY_base_id)(EVP_PKEY *) = 0L; +static RSA *(*K_EVP_PKEY_get0_RSA)(EVP_PKEY *) = 0L; +static void (*K_RSA_get0_key)(RSA *, const BIGNUM **, const BIGNUM **, const BIGNUM **) = 0L; +static DSA *(*K_EVP_PKEY_get0_DSA)(EVP_PKEY *) = 0L; +static void (*K_DSA_get0_pqg)(DSA *, const BIGNUM **, const BIGNUM **, const BIGNUM **) = 0L; +static void (*K_DSA_get0_key)(DSA *, const BIGNUM **, const BIGNUM **) = 0L; static int (*K_X509_REQ_set_pubkey)(X509_REQ*, EVP_PKEY*) = 0L; static RSA *(*K_RSA_generate_key)(int, unsigned long, void (*)(int,int,void *), void *) = 0L; static int (*K_i2d_X509_REQ_fp)(FILE*, X509_REQ*) = 0L; static void (*K_ERR_clear_error)() = 0L; static unsigned long (*K_ERR_get_error)() = 0L; static void (*K_ERR_print_errors_fp)(FILE*) = 0L; static PKCS7 *(*K_PKCS7_sign)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int) = 0L; static int (*K_PKCS7_verify)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int) = 0L; static STACK_OF(X509) *(*K_PKCS7_get0_signers)(PKCS7 *, STACK_OF(X509) *, int) = 0L; static PKCS7 *(*K_PKCS7_encrypt)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int) = 0L; static int (*K_PKCS7_decrypt)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int) = 0L; static SSL_SESSION* (*K_SSL_get1_session)(SSL*) = 0L; static void (*K_SSL_SESSION_free)(SSL_SESSION*) = 0L; static int (*K_SSL_set_session)(SSL*,SSL_SESSION*) = 0L; static SSL_SESSION* (*K_d2i_SSL_SESSION)(SSL_SESSION**,unsigned char**, long) = 0L; static int (*K_i2d_SSL_SESSION)(SSL_SESSION*,unsigned char**) = 0L; static STACK *(*K_X509_get1_email)(X509 *x) = 0L; static void (*K_X509_email_free)(STACK *sk) = 0L; static EVP_CIPHER *(*K_EVP_des_ede3_cbc)() = 0L; static EVP_CIPHER *(*K_EVP_des_cbc)() = 0L; static EVP_CIPHER *(*K_EVP_rc2_cbc)() = 0L; static EVP_CIPHER *(*K_EVP_rc2_64_cbc)() = 0L; static EVP_CIPHER *(*K_EVP_rc2_40_cbc)() = 0L; static int (*K_i2d_PrivateKey_fp)(FILE*,EVP_PKEY*) = 0L; static int (*K_i2d_PKCS8PrivateKey_fp)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*) = 0L; static void (*K_RSA_free)(RSA*) = 0L; static EVP_CIPHER *(*K_EVP_bf_cbc)() = 0L; static int (*K_X509_REQ_sign)(X509_REQ*, EVP_PKEY*, const EVP_MD*) = 0L; static int (*K_X509_NAME_add_entry_by_txt)(X509_NAME*, char*, int, unsigned char*, int, int, int) = 0L; static X509_NAME *(*K_X509_NAME_new)() = 0L; static int (*K_X509_REQ_set_subject_name)(X509_REQ*,X509_NAME*) = 0L; static unsigned char *(*K_ASN1_STRING_data)(ASN1_STRING*) = 0L; static int (*K_ASN1_STRING_length)(ASN1_STRING*) = 0L; static STACK_OF(SSL_CIPHER) *(*K_SSL_get_ciphers)(const SSL *ssl) = 0L; #endif } class KOpenSSLProxyPrivate { public: KOpenSSLProxyPrivate() : sslLib(0), cryptoLib(0), ok(false) {} KLibrary *sslLib; KLibrary *cryptoLib; bool ok; static KOpenSSLProxy *sSelf; static void cleanupKOpenSSLProxy() { delete KOpenSSLProxyPrivate::sSelf; } }; KOpenSSLProxy *KOpenSSLProxyPrivate::sSelf = 0; bool KOpenSSLProxy::hasLibSSL() const { return d->sslLib != 0L; } bool KOpenSSLProxy::hasLibCrypto() const { return d->cryptoLib != 0L; } void KOpenSSLProxy::destroy() { KOpenSSLProxy *x = KOpenSSLProxyPrivate::sSelf; KOpenSSLProxyPrivate::sSelf = 0; delete x; } #ifdef __OpenBSD__ #include #include #include static QString findMostRecentLib(QString dir, QString name) { // Grab all shared libraries in the directory QString filter = "lib"+name+".so.*"; QDir d(dir, filter); if (!d.exists()) return 0L; QStringList l = d.entryList(); // Find the best one int bestmaj = -1; int bestmin = -1; QString best = 0L; // where do we start uint s = filter.length()-1; for (QStringList::const_iterator it = l.begin(); it != l.end(); ++it) { QString numberpart = (*it).mid(s); uint endmaj = numberpart.indexOf('.'); if (endmaj == -1) continue; bool ok; int maj = numberpart.left(endmaj).toInt(&ok); if (!ok) continue; int min = numberpart.mid(endmaj+1).toInt(&ok); if (!ok) continue; if (maj > bestmaj || (maj == bestmaj && min > bestmin)) { bestmaj = maj; bestmin = min; best = (*it); } } if (best.isNull()) return 0L; else return dir+'/'+best; } #endif KOpenSSLProxy::KOpenSSLProxy() : d(new KOpenSSLProxyPrivate()) { QStringList libpaths, libnamesc, libnamess; d->cryptoLib = 0L; d->sslLib = 0L; KConfig cfg("cryptodefaults", KConfig::NoGlobals ); KConfigGroup cg(&cfg, "OpenSSL"); QString upath = cg.readPathEntry("Path", QString()); if (!upath.isEmpty()) libpaths << upath; #ifdef Q_OS_WIN d->cryptoLib = new KLibrary("libeay32.dll"); if (!d->cryptoLib->load()) { delete d->cryptoLib; d->cryptoLib = 0; } #elif defined(__OpenBSD__) { QString libname = findMostRecentLib("/usr/lib" KDELIBSUFF, "crypto"); if (!libname.isNull()) { d->cryptoLib = new KLibrary(libname); d->cryptoLib->setLoadHints(QLibrary::ExportExternalSymbolsHint); if (!d->cryptoLib->load()) { delete d->cryptoLib; d->cryptoLib = 0; } } } #elif defined(__CYGWIN__) libpaths << "/usr/bin/" << ""; libnamess << "cygssl-0.9.8.dll" << "cygssl-0.9.7.dll" << ""; libnamesc << "cygcrypto-0.9.8.dll" << "cygcrypto-0.9.7.dll" << ""; #else libpaths #ifdef _AIX << "/opt/freeware/lib/" #endif << "/usr/lib" KDELIBSUFF "/" << "/usr/ssl/lib" KDELIBSUFF "/" << "/usr/local/lib" KDELIBSUFF "/" << "/usr/local/openssl/lib" KDELIBSUFF "/" << "/usr/local/ssl/lib" KDELIBSUFF "/" << "/opt/openssl/lib" KDELIBSUFF "/" << "/lib" KDELIBSUFF "/" << ""; // FIXME: #define here for the various OS types to optimize libnamess #ifdef hpux << "libssl.sl" #elif defined(_AIX) << "libssl.a(libssl.so.0)" #elif defined(__APPLE__) << "libssl.dylib" << "libssl.0.9.dylib" #else #ifdef SHLIB_VERSION_NUMBER << "libssl.so." SHLIB_VERSION_NUMBER #endif << "libssl.so" << "libssl.so.0" #endif ; libnamesc #ifdef hpux << "libcrypto.sl" #elif defined(_AIX) << "libcrypto.a(libcrypto.so.0)" #elif defined(__APPLE__) << "libcrypto.dylib" << "libcrypto.0.9.dylib" #else #ifdef SHLIB_VERSION_NUMBER << "libcrypto.so." SHLIB_VERSION_NUMBER #endif << "libcrypto.so" << "libcrypto.so.0" #endif ; #endif for (QStringList::const_iterator it = libpaths.constBegin(); it != libpaths.constEnd(); ++it) { for (QStringList::const_iterator shit = libnamesc.constBegin(); shit != libnamesc.constEnd(); ++shit) { QString alib = *it; if (!alib.isEmpty() && !alib.endsWith('/')) alib += '/'; alib += *shit; // someone knows why this is needed? QString tmpStr(alib.toLatin1().constData()); tmpStr.remove(QRegExp("\\(.*\\)")); if (!access(tmpStr.toLatin1(), R_OK)) { d->cryptoLib = new KLibrary(alib); d->cryptoLib->setLoadHints(QLibrary::ExportExternalSymbolsHint); } if (d->cryptoLib && d->cryptoLib->load()) { break; } else { delete d->cryptoLib; d->cryptoLib = 0; } } if (d->cryptoLib) break; } if (d->cryptoLib) { #ifdef KSSL_HAVE_SSL K_X509_free = (void (*) (X509 *)) d->cryptoLib->resolveFunction("X509_free"); K_RAND_egd = (int (*)(const char *)) d->cryptoLib->resolveFunction("RAND_egd"); K_RAND_load_file = (int (*)(const char *, long)) d->cryptoLib->resolveFunction("RAND_load_file"); K_RAND_file_name = (const char* (*)(char *, size_t)) d->cryptoLib->resolveFunction("RAND_file_name"); K_RAND_write_file = (int (*)(const char *)) d->cryptoLib->resolveFunction("RAND_write_file"); +#if OPENSSL_VERSION_NUMBER < 0x10100000L K_CRYPTO_free = (void (*) (void *)) d->cryptoLib->resolveFunction("CRYPTO_free"); +#else + K_CRYPTO_free = (void (*)(void *, const char *, int)) d->cryptoLib->resolveFunction("CRYPTO_free"); +#endif K_d2i_X509 = (X509 * (*)(X509 **,unsigned char **,long)) d->cryptoLib->resolveFunction("d2i_X509"); K_i2d_X509 = (int (*)(X509 *,unsigned char **)) d->cryptoLib->resolveFunction("i2d_X509"); K_X509_cmp = (int (*)(X509 *, X509 *)) d->cryptoLib->resolveFunction("X509_cmp"); K_X509_STORE_CTX_new = (X509_STORE_CTX * (*) (void)) d->cryptoLib->resolveFunction("X509_STORE_CTX_new"); K_X509_STORE_CTX_free = (void (*) (X509_STORE_CTX *)) d->cryptoLib->resolveFunction("X509_STORE_CTX_free"); K_X509_verify_cert = (int (*) (X509_STORE_CTX *)) d->cryptoLib->resolveFunction("X509_verify_cert"); K_X509_STORE_new = (X509_STORE * (*) (void)) d->cryptoLib->resolveFunction("X509_STORE_new"); K_X509_STORE_free = (void (*) (X509_STORE *)) d->cryptoLib->resolveFunction("X509_STORE_free"); + K_X509_STORE_set_verify_cb = (void (*)(X509_STORE *, int (*)(int, X509_STORE_CTX *))) d->cryptoLib->resolveFunction("X509_STORE_set_verify_cb"); K_X509_NAME_oneline = (char * (*) (X509_NAME *,char *,int)) d->cryptoLib->resolveFunction("X509_NAME_oneline"); K_X509_get_subject_name = (X509_NAME * (*) (X509 *)) d->cryptoLib->resolveFunction("X509_get_subject_name"); K_X509_get_issuer_name = (X509_NAME * (*) (X509 *)) d->cryptoLib->resolveFunction("X509_get_issuer_name"); + K_X509_get0_signature = (void (*)(const ASN1_BIT_STRING **, const X509_ALGOR **, const X509 *)) d->cryptoLib->resolveFunction("X509_get0_signature"); K_X509_STORE_add_lookup = (X509_LOOKUP *(*) (X509_STORE *, X509_LOOKUP_METHOD *)) d->cryptoLib->resolveFunction("X509_STORE_add_lookup"); K_X509_LOOKUP_file = (X509_LOOKUP_METHOD *(*)(void)) d->cryptoLib->resolveFunction("X509_LOOKUP_file"); K_X509_LOOKUP_free = (void (*)(X509_LOOKUP *)) d->cryptoLib->resolveFunction("X509_LOOKUP_free"); K_X509_LOOKUP_ctrl = (int (*)(X509_LOOKUP *, int, const char *, long, char **)) d->cryptoLib->resolveFunction("X509_LOOKUP_ctrl"); K_X509_STORE_CTX_init = (void (*)(X509_STORE_CTX *, X509_STORE *, X509 *, STACK_OF(X509) *)) d->cryptoLib->resolveFunction("X509_STORE_CTX_init"); K_X509_dup = (X509* (*)(X509*)) d->cryptoLib->resolveFunction("X509_dup"); + K_X509_getm_notBefore = (ASN1_TIME *(*)(const X509 *)) d->cryptoLib->resolveFunction("X509_getm_notBefore"); + K_X509_getm_notAfter = (ASN1_TIME *(*)(const X509 *)) d->cryptoLib->resolveFunction("X509_getm_notAfter"); K_BIO_s_mem = (BIO_METHOD *(*) (void)) d->cryptoLib->resolveFunction("BIO_s_mem"); K_BIO_new = (BIO* (*)(BIO_METHOD *)) d->cryptoLib->resolveFunction("BIO_new"); K_BIO_new_fp = (BIO* (*)(FILE*, int)) d->cryptoLib->resolveFunction("BIO_new_fp"); K_BIO_new_mem_buf = (BIO* (*)(void *, int)) d->cryptoLib->resolveFunction("BIO_new_mem_buf"); K_BIO_free = (int (*)(BIO*)) d->cryptoLib->resolveFunction("BIO_free"); K_BIO_ctrl = (long (*) (BIO *,int,long,void *)) d->cryptoLib->resolveFunction("BIO_ctrl"); K_BIO_write = (int (*) (BIO *b, const void *data, int len)) d->cryptoLib->resolveFunction("BIO_write"); K_PEM_ASN1_write_bio = (int (*)(int (*)(), const char *,BIO*, char*, const EVP_CIPHER *, unsigned char *, int, pem_password_cb *, void *)) d->cryptoLib->resolveFunction("PEM_ASN1_write_bio"); K_ASN1_item_i2d_fp = (int (*)(ASN1_ITEM *, FILE*, unsigned char *)) d->cryptoLib->resolveFunction("ASN1_item_i2d_fp"); K_NETSCAPE_X509_it = (ASN1_ITEM *) d->cryptoLib->resolveFunction("NETSCAPE_X509_it"); K_X509_print_fp = (int (*)(FILE*, X509*)) d->cryptoLib->resolveFunction("X509_print_fp"); K_i2d_PKCS12 = (int (*)(PKCS12*, unsigned char**)) d->cryptoLib->resolveFunction("i2d_PKCS12"); K_i2d_PKCS12_fp = (int (*)(FILE *, PKCS12*)) d->cryptoLib->resolveFunction("i2d_PKCS12_fp"); K_PKCS12_newpass = (int (*)(PKCS12*, char*, char*)) d->cryptoLib->resolveFunction("PKCS12_newpass"); K_d2i_PKCS12_fp = (PKCS12* (*)(FILE*, PKCS12**)) d->cryptoLib->resolveFunction("d2i_PKCS12_fp"); K_PKCS12_new = (PKCS12* (*)()) d->cryptoLib->resolveFunction("PKCS12_new"); K_PKCS12_free = (void (*)(PKCS12 *)) d->cryptoLib->resolveFunction("PKCS12_free"); K_PKCS12_parse = (int (*)(PKCS12*, const char *, EVP_PKEY**, X509**, STACK_OF(X509)**)) d->cryptoLib->resolveFunction("PKCS12_parse"); K_EVP_PKEY_free = (void (*) (EVP_PKEY *)) d->cryptoLib->resolveFunction("EVP_PKEY_free"); K_EVP_PKEY_new = (EVP_PKEY* (*)()) d->cryptoLib->resolveFunction("EVP_PKEY_new"); K_X509_REQ_free = (void (*)(X509_REQ*)) d->cryptoLib->resolveFunction("X509_REQ_free"); K_X509_REQ_new = (X509_REQ* (*)()) d->cryptoLib->resolveFunction("X509_REQ_new"); K_X509_STORE_CTX_set_chain = (void (*)(X509_STORE_CTX *, STACK_OF(X509)*)) d->cryptoLib->resolveFunction("X509_STORE_CTX_set_chain"); K_X509_STORE_CTX_set_purpose = (void (*)(X509_STORE_CTX *, int)) d->cryptoLib->resolveFunction("X509_STORE_CTX_set_purpose"); - K_sk_free = (void (*) (STACK *)) d->cryptoLib->resolveFunction("sk_free"); - K_sk_num = (int (*) (STACK *)) d->cryptoLib->resolveFunction("sk_num"); - K_sk_pop = (char* (*) (STACK *)) d->cryptoLib->resolveFunction("sk_pop"); - K_sk_value = (char* (*) (STACK *, int)) d->cryptoLib->resolveFunction("sk_value"); - K_sk_new = (STACK* (*) (int (*)())) d->cryptoLib->resolveFunction("sk_new"); - K_sk_push = (int (*) (STACK*, char*)) d->cryptoLib->resolveFunction("sk_push"); - K_sk_dup = (STACK* (*) (STACK *)) d->cryptoLib->resolveFunction("sk_dup"); + K_X509_STORE_CTX_get_current_cert = (X509 * (*)(X509_STORE_CTX *)) d->cryptoLib->resolveFunction("X509_STORE_CTX_get_current_cert"); + K_X509_STORE_CTX_set_error = (void (*)(X509_STORE_CTX *, int)) d->cryptoLib->resolveFunction("X509_STORE_CTX_set_error"); + K_X509_STORE_CTX_get_error = (int (*)(X509_STORE_CTX *)) d->cryptoLib->resolveFunction("X509_STORE_CTX_get_error"); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + K_OPENSSL_sk_free = (void (*)(STACK *)) d->cryptoLib->resolveFunction("OPENSSL_sk_free"); + K_OPENSSL_sk_num = (int (*)(STACK *)) d->cryptoLib->resolveFunction("OPENSSL_sk_num"); + K_OPENSSL_sk_pop = (char *(*)(STACK *)) d->cryptoLib->resolveFunction("OPENSSL_sk_pop"); + K_OPENSSL_sk_value = (char *(*)(STACK *, int)) d->cryptoLib->resolveFunction("OPENSSL_sk_value"); + K_OPENSSL_sk_new = (STACK * (*)(int (*)())) d->cryptoLib->resolveFunction("OPENSSL_sk_new"); + K_OPENSSL_sk_push = (int (*)(STACK *, char *)) d->cryptoLib->resolveFunction("OPENSSL_sk_push"); + K_OPENSSL_sk_dup = (STACK * (*)(STACK *)) d->cryptoLib->resolveFunction("OPENSSL_sk_dup"); +#else + K_OPENSSL_sk_free = (void (*)(STACK *)) d->cryptoLib->resolveFunction("sk_free"); + K_OPENSSL_sk_num = (int (*)(STACK *)) d->cryptoLib->resolveFunction("sk_num"); + K_OPENSSL_sk_pop = (char *(*)(STACK *)) d->cryptoLib->resolveFunction("sk_pop"); + K_OPENSSL_sk_value = (char *(*)(STACK *, int)) d->cryptoLib->resolveFunction("sk_value"); + K_OPENSSL_sk_new = (STACK * (*)(int (*)())) d->cryptoLib->resolveFunction("sk_new"); + K_OPENSSL_sk_push = (int (*)(STACK *, char *)) d->cryptoLib->resolveFunction("sk_push"); + K_OPENSSL_sk_dup = (STACK * (*)(STACK *)) d->cryptoLib->resolveFunction("sk_dup"); +#endif K_i2s_ASN1_INTEGER = (char *(*) (X509V3_EXT_METHOD *, ASN1_INTEGER *)) d->cryptoLib->resolveFunction("i2s_ASN1_INTEGER"); K_X509_get_serialNumber = (ASN1_INTEGER * (*) (X509 *)) d->cryptoLib->resolveFunction("X509_get_serialNumber"); K_X509_get_pubkey = (EVP_PKEY *(*)(X509 *)) d->cryptoLib->resolveFunction("X509_get_pubkey"); K_i2d_PublicKey = (int (*)(EVP_PKEY *, unsigned char **)) d->cryptoLib->resolveFunction("i2d_PublicKey"); K_X509_check_private_key = (int (*)(X509 *, EVP_PKEY *)) d->cryptoLib->resolveFunction("X509_check_private_key"); K_BN_bn2hex = (char *(*)(const BIGNUM *)) d->cryptoLib->resolveFunction("BN_bn2hex"); K_X509_digest = (int (*)(const X509 *,const EVP_MD *, unsigned char *, unsigned int *)) d->cryptoLib->resolveFunction("X509_digest"); K_EVP_md5 = (EVP_MD *(*)()) d->cryptoLib->resolveFunction("EVP_md5"); K_ASN1_INTEGER_free = (void (*)(ASN1_INTEGER *)) d->cryptoLib->resolveFunction("ASN1_INTEGER_free"); K_OBJ_obj2nid = (int (*)(ASN1_OBJECT *)) d->cryptoLib->resolveFunction("OBJ_obj2nid"); K_OBJ_nid2ln = (const char *(*)(int)) d->cryptoLib->resolveFunction("OBJ_nid2ln"); K_X509_get_ext_count = (int (*)(X509*)) d->cryptoLib->resolveFunction("X509_get_ext_count"); K_X509_get_ext_by_NID = (int (*)(X509*,int,int)) d->cryptoLib->resolveFunction("X509_get_ext_by_NID"); K_X509_get_ext_by_OBJ = (int (*)(X509*,ASN1_OBJECT*,int)) d->cryptoLib->resolveFunction("X509_get_ext_by_OBJ"); K_X509_get_ext = (X509_EXTENSION* (*)(X509*,int)) d->cryptoLib->resolveFunction("X509_get_ext"); K_X509_delete_ext = (X509_EXTENSION* (*)(X509*,int)) d->cryptoLib->resolveFunction("X509_delete_ext"); K_X509_add_ext = (int (*)(X509*,X509_EXTENSION*,int)) d->cryptoLib->resolveFunction("X509_add_ext"); K_X509_get_ext_d2i = (void* (*)(X509*,int,int*,int*)) d->cryptoLib->resolveFunction("X509_get_ext_d2i"); K_i2s_ASN1_OCTET_STRING = (char *(*)(X509V3_EXT_METHOD*,ASN1_OCTET_STRING*)) d->cryptoLib->resolveFunction("i2s_ASN1_OCTET_STRING"); K_ASN1_BIT_STRING_get_bit = (int (*)(ASN1_BIT_STRING*,int)) d->cryptoLib->resolveFunction("ASN1_BIT_STRING_get_bit"); K_PKCS7_new = (PKCS7 *(*)()) d->cryptoLib->resolveFunction("PKCS7_new"); K_PKCS7_free = (void (*)(PKCS7*)) d->cryptoLib->resolveFunction("PKCS7_free"); K_PKCS7_content_free = (void (*)(PKCS7*)) d->cryptoLib->resolveFunction("PKCS7_content_free"); K_i2d_PKCS7 = (int (*)(PKCS7*, unsigned char**)) d->cryptoLib->resolveFunction("i2d_PKCS7"); K_i2d_PKCS7_fp = (int (*)(FILE*,PKCS7*)) d->cryptoLib->resolveFunction("i2d_PKCS7_fp"); K_i2d_PKCS7_bio = (int (*)(BIO *bp,PKCS7 *p7)) d->cryptoLib->resolveFunction("i2d_PKCS7_bio"); K_d2i_PKCS7 = (PKCS7* (*)(PKCS7**,unsigned char**,long)) d->cryptoLib->resolveFunction("d2i_PKCS7"); K_d2i_PKCS7_fp = (PKCS7 *(*)(FILE *,PKCS7**)) d->cryptoLib->resolveFunction("d2i_PKCS7_fp"); K_d2i_PKCS7_bio = (PKCS7 *(*)(BIO *bp,PKCS7 **p7)) d->cryptoLib->resolveFunction("d2i_PKCS7_bio"); K_PKCS7_dup = (PKCS7* (*)(PKCS7*)) d->cryptoLib->resolveFunction("PKCS7_dup"); K_PKCS7_sign = (PKCS7 *(*)(X509*, EVP_PKEY*, STACK_OF(X509)*, BIO*, int)) d->cryptoLib->resolveFunction("PKCS7_sign"); K_PKCS7_verify = (int (*)(PKCS7*,STACK_OF(X509)*,X509_STORE*,BIO*,BIO*,int)) d->cryptoLib->resolveFunction("PKCS7_verify"); K_PKCS7_get0_signers = (STACK_OF(X509) *(*)(PKCS7 *, STACK_OF(X509) *, int)) d->cryptoLib->resolveFunction("PKCS7_get0_signers"); K_PKCS7_encrypt = (PKCS7* (*)(STACK_OF(X509) *, BIO *, EVP_CIPHER *, int)) d->cryptoLib->resolveFunction("PKCS7_encrypt"); K_PKCS7_decrypt = (int (*)(PKCS7 *, EVP_PKEY *, X509 *, BIO *, int)) d->cryptoLib->resolveFunction("PKCS7_decrypt"); K_PEM_X509_INFO_read = (STACK_OF(X509_INFO) *(*)(FILE*, STACK_OF(X509_INFO)*, pem_password_cb*, void *)) d->cryptoLib->resolveFunction("PEM_X509_INFO_read"); K_ASN1_d2i_fp = (char *(*)(char *(*)(),char *(*)(),FILE*,unsigned char**)) d->cryptoLib->resolveFunction("ASN1_d2i_fp"); K_X509_new = (X509 *(*)()) d->cryptoLib->resolveFunction("X509_new"); K_X509_PURPOSE_get_count = (int (*)()) d->cryptoLib->resolveFunction("X509_PURPOSE_get_count"); K_X509_PURPOSE_get_id = (int (*)(X509_PURPOSE *)) d->cryptoLib->resolveFunction("X509_PURPOSE_get_id"); K_X509_check_purpose = (int (*)(X509*,int,int)) d->cryptoLib->resolveFunction("X509_check_purpose"); K_X509_PURPOSE_get0 = (X509_PURPOSE *(*)(int)) d->cryptoLib->resolveFunction("X509_PURPOSE_get0"); K_EVP_PKEY_assign = (int (*)(EVP_PKEY*, int, char*)) d->cryptoLib->resolveFunction("EVP_PKEY_assign"); + K_EVP_PKEY_base_id = (int (*)(EVP_PKEY *)) d->cryptoLib->resolveFunction("EVP_PKEY_base_id"); + K_EVP_PKEY_get0_RSA = (RSA *(*)(EVP_PKEY *)) d->cryptoLib->resolveFunction("EVP_PKEY_get0_RSA"); + K_RSA_get0_key = (void (*)(RSA *, const BIGNUM **, const BIGNUM **, const BIGNUM **)) d->cryptoLib->resolveFunction("ESA_get0_key"); + K_EVP_PKEY_get0_DSA = (DSA *(*)(EVP_PKEY *)) d->cryptoLib->resolveFunction("EVP_PKEY_get0_DSA"); + K_DSA_get0_pqg = (void (*)(DSA *, const BIGNUM **, const BIGNUM **, const BIGNUM **)) d->cryptoLib->resolveFunction("DSA_get0_pqg"); + K_DSA_get0_key = (void (*)(DSA *, const BIGNUM **, const BIGNUM **)) d->cryptoLib->resolveFunction("DSA_get0_key"); K_X509_REQ_set_pubkey = (int (*)(X509_REQ*, EVP_PKEY*)) d->cryptoLib->resolveFunction("X509_REQ_set_pubkey"); K_RSA_generate_key = (RSA* (*)(int, unsigned long, void (*)(int,int,void *), void *)) d->cryptoLib->resolveFunction("RSA_generate_key"); K_i2d_X509_REQ_fp = (int (*)(FILE *, X509_REQ *)) d->cryptoLib->resolveFunction("i2d_X509_REQ_fp"); K_ERR_clear_error = (void (*)()) d->cryptoLib->resolveFunction("ERR_clear_error"); K_ERR_get_error = (unsigned long (*)()) d->cryptoLib->resolveFunction("ERR_get_error"); K_ERR_print_errors_fp = (void (*)(FILE*)) d->cryptoLib->resolveFunction("ERR_print_errors_fp"); K_X509_get1_email = (STACK *(*)(X509 *x)) d->cryptoLib->resolveFunction("X509_get1_email"); K_X509_email_free = (void (*)(STACK *sk)) d->cryptoLib->resolveFunction("X509_email_free"); K_EVP_des_ede3_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_des_ede3_cbc"); K_EVP_des_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_des_cbc"); K_EVP_rc2_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_rc2_cbc"); K_EVP_rc2_64_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_rc2_64_cbc"); K_EVP_rc2_40_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_rc2_40_cbc"); K_i2d_PrivateKey_fp = (int (*)(FILE*,EVP_PKEY*)) d->cryptoLib->resolveFunction("i2d_PrivateKey_fp"); K_i2d_PKCS8PrivateKey_fp = (int (*)(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*)) d->cryptoLib->resolveFunction("i2d_PKCS8PrivateKey_fp"); K_RSA_free = (void (*)(RSA*)) d->cryptoLib->resolveFunction("RSA_free"); K_EVP_bf_cbc = (EVP_CIPHER *(*)()) d->cryptoLib->resolveFunction("EVP_bf_cbc"); K_X509_REQ_sign = (int (*)(X509_REQ*, EVP_PKEY*, const EVP_MD*)) d->cryptoLib->resolveFunction("X509_REQ_sign"); K_X509_NAME_add_entry_by_txt = (int (*)(X509_NAME*, char*, int, unsigned char*, int, int, int)) d->cryptoLib->resolveFunction("X509_NAME_add_entry_by_txt"); K_X509_NAME_new = (X509_NAME *(*)()) d->cryptoLib->resolveFunction("X509_NAME_new"); K_X509_REQ_set_subject_name = (int (*)(X509_REQ*,X509_NAME*)) d->cryptoLib->resolveFunction("X509_REQ_set_subject_name"); K_ASN1_STRING_data = (unsigned char *(*)(ASN1_STRING*)) d->cryptoLib->resolveFunction("ASN1_STRING_data"); K_ASN1_STRING_length = (int (*)(ASN1_STRING*)) d->cryptoLib->resolveFunction("ASN1_STRING_length"); #endif } #ifdef Q_OS_WIN d->sslLib = new KLibrary("ssleay32.dll"); if (!d->sslLib->load()) { delete d->sslLib; d->sslLib = 0; } #elif defined(__OpenBSD__) { QString libname = findMostRecentLib("/usr/lib", "ssl"); if (!libname.isNull()) { d->sslLib = new KLibrary(libname); d->sslLib->setLoadHints(QLibrary::ExportExternalSymbolsHint); if (!d->sslLib->load()) { delete d->sslLib; d->sslLib = 0; } } } #else for (QStringList::const_iterator it = libpaths.constBegin(); it != libpaths.constEnd(); ++it) { for (QStringList::const_iterator shit = libnamess.constBegin(); shit != libnamess.constEnd(); ++shit) { QString alib = *it; if (!alib.isEmpty() && !alib.endsWith('/')) alib += '/'; alib += *shit; QString tmpStr(alib.toLatin1()); tmpStr.remove(QRegExp("\\(.*\\)")); if (!access(tmpStr.toLatin1(), R_OK)) { d->sslLib = new KLibrary(alib); d->sslLib->setLoadHints(QLibrary::ExportExternalSymbolsHint); } if (d->sslLib && d->sslLib->load()) { break; } else { delete d->sslLib; d->sslLib = 0; } } if (d->sslLib) break; } #endif if (d->sslLib) { #ifdef KSSL_HAVE_SSL // stand back from your monitor and look at this. it's fun! :) K_SSL_connect = (int (*)(SSL *)) d->sslLib->resolveFunction("SSL_connect"); K_SSL_accept = (int (*)(SSL *)) d->sslLib->resolveFunction("SSL_accept"); K_SSL_read = (int (*)(SSL *, void *, int)) d->sslLib->resolveFunction("SSL_read"); K_SSL_write = (int (*)(SSL *, const void *, int)) d->sslLib->resolveFunction("SSL_write"); K_SSL_new = (SSL* (*)(SSL_CTX *)) d->sslLib->resolveFunction("SSL_new"); K_SSL_free = (void (*)(SSL *)) d->sslLib->resolveFunction("SSL_free"); K_SSL_shutdown = (int (*)(SSL *)) d->sslLib->resolveFunction("SSL_shutdown"); K_SSL_CTX_new = (SSL_CTX* (*)(SSL_METHOD*)) d->sslLib->resolveFunction("SSL_CTX_new"); K_SSL_CTX_free = (void (*)(SSL_CTX*)) d->sslLib->resolveFunction("SSL_CTX_free"); K_SSL_set_fd = (int (*)(SSL *, int)) d->sslLib->resolveFunction("SSL_set_fd"); K_SSL_pending = (int (*)(SSL *)) d->sslLib->resolveFunction("SSL_pending"); K_SSL_CTX_set_cipher_list = (int (*)(SSL_CTX *, const char *)) d->sslLib->resolveFunction("SSL_CTX_set_cipher_list"); K_SSL_CTX_set_verify = (void (*)(SSL_CTX*, int, int (*)(int, X509_STORE_CTX*))) d->sslLib->resolveFunction("SSL_CTX_set_verify"); K_SSL_use_certificate = (int (*)(SSL*, X509*)) d->sslLib->resolveFunction("SSL_CTX_use_certificate"); K_SSL_get_current_cipher = (SSL_CIPHER *(*)(SSL *)) d->sslLib->resolveFunction("SSL_get_current_cipher"); K_SSL_ctrl = (long (*)(SSL * ,int, long, char *)) d->sslLib->resolveFunction("SSL_ctrl"); K_TLSv1_client_method = (SSL_METHOD *(*)()) d->sslLib->resolveFunction("TLSv1_client_method"); K_SSLv23_client_method = (SSL_METHOD *(*)()) d->sslLib->resolveFunction("SSLv23_client_method"); K_SSL_get_peer_certificate = (X509 *(*)(SSL *)) d->sslLib->resolveFunction("SSL_get_peer_certificate"); K_SSL_CIPHER_get_bits = (int (*)(SSL_CIPHER *,int *)) d->sslLib->resolveFunction("SSL_CIPHER_get_bits"); K_SSL_CIPHER_get_version = (char * (*)(SSL_CIPHER *)) d->sslLib->resolveFunction("SSL_CIPHER_get_version"); K_SSL_CIPHER_get_name = (const char * (*)(SSL_CIPHER *)) d->sslLib->resolveFunction("SSL_CIPHER_get_name"); K_SSL_CIPHER_description = (char * (*)(SSL_CIPHER *, char *, int)) d->sslLib->resolveFunction("SSL_CIPHER_description"); K_SSL_CTX_use_PrivateKey = (int (*)(SSL_CTX*, EVP_PKEY*)) d->sslLib->resolveFunction("SSL_CTX_use_PrivateKey"); K_SSL_CTX_use_certificate = (int (*)(SSL_CTX*, X509*)) d->sslLib->resolveFunction("SSL_CTX_use_certificate"); K_SSL_get_error = (int (*)(SSL*, int)) d->sslLib->resolveFunction("SSL_get_error"); K_SSL_get_peer_cert_chain = (STACK_OF(X509)* (*)(SSL*)) d->sslLib->resolveFunction("SSL_get_peer_cert_chain"); K_SSL_load_client_CA_file = (STACK_OF(X509_NAME)* (*)(const char *)) d->sslLib->resolveFunction("SSL_load_client_CA_file"); K_SSL_peek = (int (*)(SSL*,void*,int)) d->sslLib->resolveFunction("SSL_peek"); K_SSL_get1_session = (SSL_SESSION* (*)(SSL*)) d->sslLib->resolveFunction("SSL_get1_session"); K_SSL_SESSION_free = (void (*)(SSL_SESSION*)) d->sslLib->resolveFunction("SSL_SESSION_free"); K_SSL_set_session = (int (*)(SSL*,SSL_SESSION*)) d->sslLib->resolveFunction("SSL_set_session"); K_d2i_SSL_SESSION = (SSL_SESSION* (*)(SSL_SESSION**,unsigned char**, long)) d->sslLib->resolveFunction("d2i_SSL_SESSION"); K_i2d_SSL_SESSION = (int (*)(SSL_SESSION*,unsigned char**)) d->sslLib->resolveFunction("i2d_SSL_SESSION"); K_SSL_get_ciphers = (STACK_OF(SSL_CIPHER) *(*)(const SSL*)) d->sslLib->resolveFunction("SSL_get_ciphers"); #endif // Initialize the library (once only!) KLibrary::void_function_ptr x; x = d->sslLib->resolveFunction("SSL_library_init"); if (d->cryptoLib) { if (x) ((int (*)())x)(); x = d->cryptoLib->resolveFunction("OpenSSL_add_all_algorithms"); if (!x) x = d->cryptoLib->resolveFunction("OPENSSL_add_all_algorithms"); if (x) { ((void (*)())x)(); } else { x = d->cryptoLib->resolveFunction("OpenSSL_add_all_algorithms_conf"); if (!x) x = d->cryptoLib->resolveFunction("OPENSSL_add_all_algorithms_conf"); if (x) { ((void (*)())x)(); } else { x = d->cryptoLib->resolveFunction("OpenSSL_add_all_algorithms_noconf"); if (!x) x = d->cryptoLib->resolveFunction("OPENSSL_add_all_algorithms_noconf"); if (x) ((void (*)())x)(); } } x = d->cryptoLib->resolveFunction("OpenSSL_add_all_ciphers"); if (!x) x = d->cryptoLib->resolveFunction("OPENSSL_add_all_ciphers"); if (x) ((void (*)())x)(); x = d->cryptoLib->resolveFunction("OpenSSL_add_all_digests"); if (!x) x = d->cryptoLib->resolveFunction("OPENSSL_add_all_digests"); if (x) ((void (*)())x)(); } } } KOpenSSLProxy::~KOpenSSLProxy() { if (d->sslLib) { d->sslLib->unload(); } if (d->cryptoLib) { d->cryptoLib->unload(); } KOpenSSLProxyPrivate::sSelf = 0; delete d; } // FIXME: we should check "ok" and allow this to init the lib if !ok. KOpenSSLProxy *KOpenSSLProxy::self() { #ifdef KSSL_HAVE_SSL if(!KOpenSSLProxyPrivate::sSelf) { KOpenSSLProxyPrivate::sSelf = new KOpenSSLProxy(); qAddPostRoutine(KOpenSSLProxyPrivate::cleanupKOpenSSLProxy); } #endif return KOpenSSLProxyPrivate::sSelf; } #ifdef KSSL_HAVE_SSL int KOpenSSLProxy::SSL_connect(SSL *ssl) { if (K_SSL_connect) return (K_SSL_connect)(ssl); return -1; } int KOpenSSLProxy::SSL_accept(SSL *ssl) { if (K_SSL_accept) return (K_SSL_accept)(ssl); return -1; } int KOpenSSLProxy::SSL_read(SSL *ssl, void *buf, int num) { if (K_SSL_read) return (K_SSL_read)(ssl, buf, num); return -1; } int KOpenSSLProxy::SSL_write(SSL *ssl, const void *buf, int num) { if (K_SSL_write) return (K_SSL_write)(ssl, buf, num); return -1; } SSL *KOpenSSLProxy::SSL_new(SSL_CTX *ctx) { if (K_SSL_new) return (K_SSL_new)(ctx); return 0L; } void KOpenSSLProxy::SSL_free(SSL *ssl) { if (K_SSL_free) (K_SSL_free)(ssl); } int KOpenSSLProxy::SSL_shutdown(SSL *ssl) { if (K_SSL_shutdown) return (K_SSL_shutdown)(ssl); return -1; } SSL_CTX *KOpenSSLProxy::SSL_CTX_new(SSL_METHOD *method) { if (K_SSL_CTX_new) return (K_SSL_CTX_new)(method); return 0L; } void KOpenSSLProxy::SSL_CTX_free(SSL_CTX *ctx) { if (K_SSL_CTX_free) (K_SSL_CTX_free)(ctx); } int KOpenSSLProxy::SSL_set_fd(SSL *ssl, int fd) { if (K_SSL_set_fd) return (K_SSL_set_fd)(ssl, fd); return -1; } int KOpenSSLProxy::SSL_pending(SSL *ssl) { if (K_SSL_pending) return (K_SSL_pending)(ssl); return -1; } int KOpenSSLProxy::SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) { if (K_SSL_CTX_set_cipher_list) return (K_SSL_CTX_set_cipher_list)(ctx, str); return -1; } void KOpenSSLProxy::SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *)) { if (K_SSL_CTX_set_verify) (K_SSL_CTX_set_verify)(ctx, mode, verify_callback); } int KOpenSSLProxy::SSL_use_certificate(SSL *ssl, X509 *x) { if (K_SSL_use_certificate) return (K_SSL_use_certificate)(ssl, x); return -1; } SSL_CIPHER *KOpenSSLProxy::SSL_get_current_cipher(SSL *ssl) { if (K_SSL_get_current_cipher) return (K_SSL_get_current_cipher)(ssl); return 0L; } long KOpenSSLProxy::SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg) { if (K_SSL_ctrl) return (K_SSL_ctrl)(ssl, cmd, larg, parg); return -1; } int KOpenSSLProxy::RAND_egd(const char *path) { if (K_RAND_egd) return (K_RAND_egd)(path); return -1; } SSL_METHOD *KOpenSSLProxy::TLSv1_client_method() { if (K_TLSv1_client_method) return (K_TLSv1_client_method)(); return 0L; } SSL_METHOD *KOpenSSLProxy::SSLv23_client_method() { if (K_SSLv23_client_method) return (K_SSLv23_client_method)(); return 0L; } X509 *KOpenSSLProxy::SSL_get_peer_certificate(SSL *s) { if (K_SSL_get_peer_certificate) return (K_SSL_get_peer_certificate)(s); return 0L; } int KOpenSSLProxy::SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits) { if (K_SSL_CIPHER_get_bits) return (K_SSL_CIPHER_get_bits)(c, alg_bits); return -1; } char * KOpenSSLProxy::SSL_CIPHER_get_version(SSL_CIPHER *c) { if (K_SSL_CIPHER_get_version) return (K_SSL_CIPHER_get_version)(c); return 0L; } const char * KOpenSSLProxy::SSL_CIPHER_get_name(SSL_CIPHER *c) { if (K_SSL_CIPHER_get_name) return (K_SSL_CIPHER_get_name)(c); return 0L; } char * KOpenSSLProxy::SSL_CIPHER_description(SSL_CIPHER *c,char *buf,int size) { if (K_SSL_CIPHER_description) return (K_SSL_CIPHER_description)(c,buf,size); return 0L; } X509 * KOpenSSLProxy::d2i_X509(X509 **a,unsigned char **pp,long length) { if (K_d2i_X509) return (K_d2i_X509)(a,pp,length); return 0L; } int KOpenSSLProxy::i2d_X509(X509 *a,unsigned char **pp) { if (K_i2d_X509) return (K_i2d_X509)(a,pp); return -1; } int KOpenSSLProxy::X509_cmp(X509 *a, X509 *b) { if (K_X509_cmp) return (K_X509_cmp)(a,b); return 0; } X509_STORE *KOpenSSLProxy::X509_STORE_new(void) { if (K_X509_STORE_new) return (K_X509_STORE_new)(); return 0L; } void KOpenSSLProxy::X509_STORE_free(X509_STORE *v) { if (K_X509_STORE_free) (K_X509_STORE_free)(v); } +void KOpenSSLProxy::X509_STORE_set_verify_cb(X509_STORE *store, int (*verify_cb)(int, X509_STORE_CTX *)) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + X509_STORE_set_verify_cb_func(store, verify_cb); +#else + if (K_X509_STORE_set_verify_cb) (K_X509_STORE_set_verify_cb)(store, verify_cb); +#endif +} + + X509_STORE_CTX *KOpenSSLProxy::X509_STORE_CTX_new(void) { if (K_X509_STORE_CTX_new) return (K_X509_STORE_CTX_new)(); return 0L; } void KOpenSSLProxy::X509_STORE_CTX_free(X509_STORE_CTX *ctx) { if (K_X509_STORE_CTX_free) (K_X509_STORE_CTX_free)(ctx); } int KOpenSSLProxy::X509_verify_cert(X509_STORE_CTX *ctx) { if (K_X509_verify_cert) return (K_X509_verify_cert)(ctx); return -1; } void KOpenSSLProxy::X509_free(X509 *a) { if (K_X509_free) (K_X509_free)(a); } char *KOpenSSLProxy::X509_NAME_oneline(X509_NAME *a,char *buf,int size) { if (K_X509_NAME_oneline) return (K_X509_NAME_oneline)(a,buf,size); return 0L; } X509_NAME *KOpenSSLProxy::X509_get_subject_name(X509 *a) { if (K_X509_get_subject_name) return (K_X509_get_subject_name)(a); return 0L; } X509_NAME *KOpenSSLProxy::X509_get_issuer_name(X509 *a) { if (K_X509_get_issuer_name) return (K_X509_get_issuer_name)(a); return 0L; } +void KOpenSSLProxy::X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **algor, const X509 *x) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (psig) *psig = x->signature; + if (algor) *algor = x->sig_alg; +#else + if (K_X509_get0_signature) return (K_X509_get0_signature)(psig, algor, x); +#endif +} + + X509_LOOKUP *KOpenSSLProxy::X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m) { if (K_X509_STORE_add_lookup) return (K_X509_STORE_add_lookup)(v,m); return 0L; } X509_LOOKUP_METHOD *KOpenSSLProxy::X509_LOOKUP_file(void) { if (K_X509_LOOKUP_file) return (K_X509_LOOKUP_file)(); return 0L; } void KOpenSSLProxy::X509_LOOKUP_free(X509_LOOKUP *x) { if (K_X509_LOOKUP_free) (K_X509_LOOKUP_free)(x); } int KOpenSSLProxy::X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret) { if (K_X509_LOOKUP_ctrl) return (K_X509_LOOKUP_ctrl)(ctx,cmd,argc,argl,ret); return -1; } void KOpenSSLProxy::X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { if (K_X509_STORE_CTX_init) (K_X509_STORE_CTX_init)(ctx,store,x509,chain); } +#if OPENSSL_VERSION_NUMBER < 0x10100000L void KOpenSSLProxy::CRYPTO_free(void *x) { if (K_CRYPTO_free) (K_CRYPTO_free)(x); } +#else +void KOpenSSLProxy::CRYPTO_free(void *x, const char *file, int line) +{ + if (K_CRYPTO_free) K_CRYPTO_free(x, file, line); +} +#endif X509 *KOpenSSLProxy::X509_dup(X509 *x509) { if (K_X509_dup) return (K_X509_dup)(x509); return 0L; } +ASN1_TIME *KOpenSSLProxy::X509_getm_notBefore(const X509 *x) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return X509_get_notBefore(x); +#else + if (K_X509_getm_notBefore) return (K_X509_getm_notBefore)(x); + else return 0L; +#endif +} + + +ASN1_TIME *KOpenSSLProxy::X509_getm_notAfter(const X509 *x) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return X509_get_notAfter(x); +#else + if (K_X509_getm_notAfter) return (K_X509_getm_notAfter)(x); + else return 0L; +#endif +} + + BIO *KOpenSSLProxy::BIO_new(BIO_METHOD *type) { if (K_BIO_new) return (K_BIO_new)(type); else return 0L; } BIO_METHOD *KOpenSSLProxy::BIO_s_mem(void) { if (K_BIO_s_mem) return (K_BIO_s_mem)(); else return 0L; } BIO *KOpenSSLProxy::BIO_new_fp(FILE *stream, int close_flag) { if (K_BIO_new_fp) return (K_BIO_new_fp)(stream, close_flag); return 0L; } BIO *KOpenSSLProxy::BIO_new_mem_buf(void *buf, int len) { if (K_BIO_new_mem_buf) return (K_BIO_new_mem_buf)(buf,len); else return 0L; } int KOpenSSLProxy::BIO_free(BIO *a) { if (K_BIO_free) return (K_BIO_free)(a); return -1; } long KOpenSSLProxy::BIO_ctrl(BIO *bp,int cmd,long larg,void *parg) { if (K_BIO_ctrl) return (K_BIO_ctrl)(bp,cmd,larg,parg); else return 0; // failure return for BIO_ctrl is quite individual, maybe we should abort() instead } int KOpenSSLProxy::BIO_write(BIO *b, const void *data, int len) { if (K_BIO_write) return (K_BIO_write)(b, data, len); else return -1; } int KOpenSSLProxy::PEM_write_bio_X509(BIO *bp, X509 *x) { if (K_PEM_ASN1_write_bio) return (K_PEM_ASN1_write_bio) ((int (*)())K_i2d_X509, PEM_STRING_X509, bp, (char *)x, 0L, 0L, 0, 0L, 0L); else return -1; } int KOpenSSLProxy::ASN1_item_i2d_fp(FILE *out,unsigned char *x) { if (K_ASN1_item_i2d_fp && K_NETSCAPE_X509_it) return (K_ASN1_item_i2d_fp)(K_NETSCAPE_X509_it, out, x); else return -1; } int KOpenSSLProxy::X509_print(FILE *fp, X509 *x) { if (K_X509_print_fp) return (K_X509_print_fp)(fp, x); return -1; } PKCS12 *KOpenSSLProxy::d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { if (K_d2i_PKCS12_fp) return (K_d2i_PKCS12_fp)(fp, p12); else return 0L; } int KOpenSSLProxy::PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass) { if (K_PKCS12_newpass) return (K_PKCS12_newpass)(p12, oldpass, newpass); else return -1; } int KOpenSSLProxy::i2d_PKCS12(PKCS12 *p12, unsigned char **p) { if (K_i2d_PKCS12) return (K_i2d_PKCS12)(p12, p); else return -1; } int KOpenSSLProxy::i2d_PKCS12_fp(FILE *fp, PKCS12 *p12) { if (K_i2d_PKCS12_fp) return (K_i2d_PKCS12_fp)(fp, p12); else return -1; } PKCS12 *KOpenSSLProxy::PKCS12_new(void) { if (K_PKCS12_new) return (K_PKCS12_new)(); else return 0L; } void KOpenSSLProxy::PKCS12_free(PKCS12 *a) { if (K_PKCS12_free) (K_PKCS12_free)(a); } int KOpenSSLProxy::PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) { if (K_PKCS12_parse) return (K_PKCS12_parse) (p12, pass, pkey, cert, ca); else return -1; } void KOpenSSLProxy::EVP_PKEY_free(EVP_PKEY *x) { if (K_EVP_PKEY_free) (K_EVP_PKEY_free)(x); } EVP_PKEY* KOpenSSLProxy::EVP_PKEY_new() { if (K_EVP_PKEY_new) return (K_EVP_PKEY_new)(); else return 0L; } void KOpenSSLProxy::X509_REQ_free(X509_REQ *x) { if (K_X509_REQ_free) (K_X509_REQ_free)(x); } X509_REQ* KOpenSSLProxy::X509_REQ_new() { if (K_X509_REQ_new) return (K_X509_REQ_new)(); else return 0L; } int KOpenSSLProxy::SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) { if (K_SSL_CTX_use_PrivateKey) return (K_SSL_CTX_use_PrivateKey)(ctx,pkey); else return -1; } int KOpenSSLProxy::SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) { if (K_SSL_CTX_use_certificate) return (K_SSL_CTX_use_certificate)(ctx,x); else return -1; } int KOpenSSLProxy::SSL_get_error(SSL *ssl, int rc) { if (K_SSL_get_error) return (K_SSL_get_error)(ssl,rc); else return -1; } STACK_OF(X509) *KOpenSSLProxy::SSL_get_peer_cert_chain(SSL *s) { if (K_SSL_get_peer_cert_chain) return (K_SSL_get_peer_cert_chain)(s); else return 0L; } -void KOpenSSLProxy::sk_free(STACK *s) { - if (K_sk_free) (K_sk_free)(s); +void KOpenSSLProxy::OPENSSL_sk_free(STACK *s) { + if (K_OPENSSL_sk_free) (K_OPENSSL_sk_free)(s); } -int KOpenSSLProxy::sk_num(STACK *s) { - if (K_sk_num) return (K_sk_num)(s); +int KOpenSSLProxy::OPENSSL_sk_num(STACK *s) { + if (K_OPENSSL_sk_num) return (K_OPENSSL_sk_num)(s); else return -1; } -char *KOpenSSLProxy::sk_pop(STACK *s) { - if (K_sk_pop) return (K_sk_pop)(s); +char *KOpenSSLProxy::OPENSSL_sk_pop(STACK *s) { + if (K_OPENSSL_sk_pop) return (K_OPENSSL_sk_pop)(s); else return 0L; } -char *KOpenSSLProxy::sk_value(STACK *s, int n) { - if (K_sk_value) return (K_sk_value)(s, n); +char *KOpenSSLProxy::OPENSSL_sk_value(STACK *s, int n) { + if (K_OPENSSL_sk_value) return (K_OPENSSL_sk_value)(s, n); else return 0L; } void KOpenSSLProxy::X509_STORE_CTX_set_chain(X509_STORE_CTX *v, STACK_OF(X509)* x) { if (K_X509_STORE_CTX_set_chain) (K_X509_STORE_CTX_set_chain)(v,x); } void KOpenSSLProxy::X509_STORE_CTX_set_purpose(X509_STORE_CTX *v, int purpose) { if (K_X509_STORE_CTX_set_purpose) (K_X509_STORE_CTX_set_purpose)(v,purpose); } -STACK* KOpenSSLProxy::sk_dup(STACK *s) { - if (K_sk_dup) return (K_sk_dup)(s); +X509 *KOpenSSLProxy::X509_STORE_CTX_get_current_cert(X509_STORE_CTX *v) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return v->current_cert; +#else + if (K_X509_STORE_CTX_get_current_cert) return (K_X509_STORE_CTX_get_current_cert)(v); + else return 0L; +#endif +} + + +void KOpenSSLProxy::X509_STORE_CTX_set_error(X509_STORE_CTX *v, int error) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + v->error = error; +#else + if (K_X509_STORE_CTX_set_error) (K_X509_STORE_CTX_set_error)(v, error); +#endif +} + + +int KOpenSSLProxy::X509_STORE_CTX_get_error(X509_STORE_CTX *v) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return v->error; +#else + if (K_X509_STORE_CTX_get_error) return (K_X509_STORE_CTX_get_error)(v); + else return 0; +#endif +} + + +STACK* KOpenSSLProxy::OPENSSL_sk_dup(STACK *s) { + if (K_OPENSSL_sk_dup) return (K_OPENSSL_sk_dup)(s); else return 0L; } -STACK* KOpenSSLProxy::sk_new(int (*cmp)()) { - if (K_sk_new) return (K_sk_new)(cmp); +STACK* KOpenSSLProxy::OPENSSL_sk_new(int (*cmp)()) { + if (K_OPENSSL_sk_new) return (K_OPENSSL_sk_new)(cmp); else return 0L; } -int KOpenSSLProxy::sk_push(STACK* s, char* d) { - if (K_sk_push) return (K_sk_push)(s,d); +int KOpenSSLProxy::OPENSSL_sk_push(STACK* s, char* d) { + if (K_OPENSSL_sk_push) return (K_OPENSSL_sk_push)(s,d); else return -1; } char *KOpenSSLProxy::i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint) { if (K_i2s_ASN1_INTEGER) return (K_i2s_ASN1_INTEGER)(meth, aint); else return 0L; } ASN1_INTEGER *KOpenSSLProxy::X509_get_serialNumber(X509 *x) { if (K_X509_get_serialNumber) return (K_X509_get_serialNumber)(x); else return 0L; } EVP_PKEY *KOpenSSLProxy::X509_get_pubkey(X509 *x) { if (K_X509_get_pubkey) return (K_X509_get_pubkey)(x); else return 0L; } int KOpenSSLProxy::i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) { if (K_i2d_PublicKey) return (K_i2d_PublicKey)(a,pp); else return 0; } int KOpenSSLProxy::X509_check_private_key(X509 *x, EVP_PKEY *p) { if (K_X509_check_private_key) return (K_X509_check_private_key)(x,p); return -1; } char *KOpenSSLProxy::BN_bn2hex(const BIGNUM *a) { if (K_BN_bn2hex) return (K_BN_bn2hex)(a); else return 0L; } int KOpenSSLProxy::X509_digest(const X509 *x,const EVP_MD *t, unsigned char *md, unsigned int *len) { if (K_X509_digest) return (K_X509_digest)(x, t, md, len); else return -1; } EVP_MD *KOpenSSLProxy::EVP_md5() { if (K_EVP_md5) return (K_EVP_md5)(); return 0L; } void KOpenSSLProxy::ASN1_INTEGER_free(ASN1_INTEGER *a) { if (K_ASN1_INTEGER_free) (K_ASN1_INTEGER_free)(a); } int KOpenSSLProxy::OBJ_obj2nid(ASN1_OBJECT *o) { if (K_OBJ_obj2nid) return (K_OBJ_obj2nid)(o); else return -1; } const char * KOpenSSLProxy::OBJ_nid2ln(int n) { if (K_OBJ_nid2ln) return (K_OBJ_nid2ln)(n); else return 0L; } int KOpenSSLProxy::X509_get_ext_count(X509 *x) { if (K_X509_get_ext_count) return (K_X509_get_ext_count)(x); else return -1; } int KOpenSSLProxy::X509_get_ext_by_NID(X509 *x, int nid, int lastpos) { if (K_X509_get_ext_by_NID) return (K_X509_get_ext_by_NID)(x,nid,lastpos); else return -1; } int KOpenSSLProxy::X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos) { if (K_X509_get_ext_by_OBJ) return (K_X509_get_ext_by_OBJ)(x,obj,lastpos); else return -1; } X509_EXTENSION *KOpenSSLProxy::X509_get_ext(X509 *x, int loc) { if (K_X509_get_ext) return (K_X509_get_ext)(x,loc); else return 0L; } X509_EXTENSION *KOpenSSLProxy::X509_delete_ext(X509 *x, int loc) { if (K_X509_delete_ext) return (K_X509_delete_ext)(x,loc); else return 0L; } int KOpenSSLProxy::X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc) { if (K_X509_add_ext) return (K_X509_add_ext)(x,ex,loc); else return -1; } void *KOpenSSLProxy::X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx) { if (K_X509_get_ext_d2i) return (K_X509_get_ext_d2i)(x,nid,crit,idx); else return 0L; } char *KOpenSSLProxy::i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5) { if (K_i2s_ASN1_OCTET_STRING) return (K_i2s_ASN1_OCTET_STRING)(method,ia5); else return 0L; } int KOpenSSLProxy::ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n) { if (K_ASN1_BIT_STRING_get_bit) return (K_ASN1_BIT_STRING_get_bit)(a,n); else return -1; } PKCS7 *KOpenSSLProxy::PKCS7_new(void) { if (K_PKCS7_new) return (K_PKCS7_new)(); else return 0L; } void KOpenSSLProxy::PKCS7_free(PKCS7 *a) { if (K_PKCS7_free) (K_PKCS7_free)(a); } void KOpenSSLProxy::PKCS7_content_free(PKCS7 *a) { if (K_PKCS7_content_free) (K_PKCS7_content_free)(a); } int KOpenSSLProxy::i2d_PKCS7(PKCS7 *a, unsigned char **pp) { if (K_i2d_PKCS7) return (K_i2d_PKCS7)(a,pp); else return -1; } PKCS7 *KOpenSSLProxy::d2i_PKCS7(PKCS7 **a, unsigned char **pp,long length) { if (K_d2i_PKCS7) return (K_d2i_PKCS7)(a,pp,length); else return 0L; } int KOpenSSLProxy::i2d_PKCS7_fp(FILE *fp,PKCS7 *p7) { if (K_i2d_PKCS7_fp) return (K_i2d_PKCS7_fp)(fp,p7); else return -1; } PKCS7 *KOpenSSLProxy::d2i_PKCS7_fp(FILE *fp,PKCS7 **p7) { if (K_d2i_PKCS7_fp) return (K_d2i_PKCS7_fp)(fp,p7); else return 0L; } int KOpenSSLProxy::i2d_PKCS7_bio(BIO *bp,PKCS7 *p7) { if (K_i2d_PKCS7_bio) return (K_i2d_PKCS7_bio)(bp, p7); else return -1; } PKCS7 *KOpenSSLProxy::d2i_PKCS7_bio(BIO *bp,PKCS7 **p7) { if (K_d2i_PKCS7_bio) return (K_d2i_PKCS7_bio)(bp, p7); else return 0L; } PKCS7 *KOpenSSLProxy::PKCS7_dup(PKCS7 *p7) { if (K_PKCS7_dup) return (K_PKCS7_dup)(p7); else return 0L; } PKCS7 *KOpenSSLProxy::PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags) { if (K_PKCS7_sign) return (K_PKCS7_sign)(signcert,pkey,certs,data,flags); else return 0L; } int KOpenSSLProxy::PKCS7_verify(PKCS7* p, STACK_OF(X509)* st, X509_STORE* s, BIO* in, BIO *out, int flags) { if (K_PKCS7_verify) return (K_PKCS7_verify)(p,st,s,in,out,flags); else return 0; } STACK_OF(X509) *KOpenSSLProxy::PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags) { if (K_PKCS7_get0_signers) return (K_PKCS7_get0_signers)(p7,certs,flags); else return 0L; } PKCS7 *KOpenSSLProxy::PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, int flags) { if (K_PKCS7_encrypt) return (K_PKCS7_encrypt)(certs,in,cipher,flags); else return 0L; } int KOpenSSLProxy::PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) { if (K_PKCS7_decrypt) return (K_PKCS7_decrypt)(p7,pkey,cert,data,flags); else return 0; } STACK_OF(X509_NAME) *KOpenSSLProxy::SSL_load_client_CA_file(const char *file) { if (K_SSL_load_client_CA_file) return (K_SSL_load_client_CA_file)(file); else return 0L; } STACK_OF(X509_INFO) *KOpenSSLProxy::PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u) { if (K_PEM_X509_INFO_read) return (K_PEM_X509_INFO_read)(fp,sk,cb,u); else return 0L; } X509 *KOpenSSLProxy::X509_d2i_fp(FILE *out, X509** buf) { if (K_ASN1_d2i_fp) return reinterpret_cast((K_ASN1_d2i_fp)(reinterpret_cast(K_X509_new), reinterpret_cast(K_d2i_X509), out, reinterpret_cast(buf))); else return 0L; } int KOpenSSLProxy::SSL_peek(SSL *ssl,void *buf,int num) { if (K_SSL_peek) return (K_SSL_peek)(ssl,buf,num); else return -1; } const char *KOpenSSLProxy::RAND_file_name(char *buf, size_t num) { if (K_RAND_file_name) return (K_RAND_file_name)(buf, num); else return 0L; } int KOpenSSLProxy::RAND_load_file(const char *filename, long max_bytes) { if (K_RAND_load_file) return (K_RAND_load_file)(filename, max_bytes); else return -1; } int KOpenSSLProxy::RAND_write_file(const char *filename) { if (K_RAND_write_file) return (K_RAND_write_file)(filename); else return -1; } int KOpenSSLProxy::X509_PURPOSE_get_count() { if (K_X509_PURPOSE_get_count) return (K_X509_PURPOSE_get_count)(); else return -1; } int KOpenSSLProxy::X509_PURPOSE_get_id(X509_PURPOSE *p) { if (K_X509_PURPOSE_get_id) return (K_X509_PURPOSE_get_id)(p); else return -1; } int KOpenSSLProxy::X509_check_purpose(X509 *x, int id, int ca) { if (K_X509_check_purpose) return (K_X509_check_purpose)(x, id, ca); else return -1; } X509_PURPOSE *KOpenSSLProxy::X509_PURPOSE_get0(int idx) { if (K_X509_PURPOSE_get0) return (K_X509_PURPOSE_get0)(idx); else return 0L; } int KOpenSSLProxy::EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key) { if (K_EVP_PKEY_assign) return (K_EVP_PKEY_assign)(pkey, type, key); else return -1; } + +int KOpenSSLProxy::EVP_PKEY_base_id(EVP_PKEY *pkey) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->type; +#else + if (K_EVP_PKEY_base_id) return (K_EVP_PKEY_base_id)(pkey); + else return 0; +#endif +} + + +RSA *KOpenSSLProxy::EVP_PKEY_get0_RSA(EVP_PKEY *pkey) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->pkey.rsa; +#else + if (K_EVP_PKEY_get0_RSA) return (K_EVP_PKEY_get0_RSA)(pkey); + else return 0L; +#endif +} + + +void KOpenSSLProxy::RSA_get0_key(RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (n) *n = rsa->n; + if (e) *e = rsa->e; + if (d) *d = rsa->d; +#else + if (K_RSA_get0_key) (K_RSA_get0_key)(rsa, n, e, d); +#endif +} + + +DSA *KOpenSSLProxy::EVP_PKEY_get0_DSA(EVP_PKEY *pkey) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + return pkey->pkey.dsa; +#else + if (K_EVP_PKEY_get0_DSA) return (K_EVP_PKEY_get0_DSA)(pkey); + else return 0L; +#endif +} + + +void KOpenSSLProxy::DSA_get0_pqg(DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (p) *p = dsa->p; + if (q) *q = dsa->q; + if (g) *g = dsa->g; +#else + if (K_DSA_get0_pqg) (K_DSA_get0_pqg)(dsa, p, q, g); +#endif +} + + +void KOpenSSLProxy::DSA_get0_key(DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (pub_key) *pub_key = dsa->pub_key; + if (priv_key) *priv_key = dsa->priv_key; +#else + if (K_DSA_get0_key) (K_DSA_get0_key)(dsa, pub_key, priv_key); +#endif +} + int KOpenSSLProxy::X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey) { if (K_X509_REQ_set_pubkey) return (K_X509_REQ_set_pubkey)(x, pkey); else return -1; } RSA* KOpenSSLProxy::RSA_generate_key(int bits, unsigned long e, void (*callback)(int,int,void *), void *cb_arg) { if (K_RSA_generate_key) return (K_RSA_generate_key)(bits, e, callback, cb_arg); else return 0L; } STACK *KOpenSSLProxy::X509_get1_email(X509 *x) { if (K_X509_get1_email) return (K_X509_get1_email)(x); else return 0L; } void KOpenSSLProxy::X509_email_free(STACK *sk) { if (K_X509_email_free) (K_X509_email_free)(sk); } EVP_CIPHER *KOpenSSLProxy::EVP_des_ede3_cbc() { if (K_EVP_des_ede3_cbc) return (K_EVP_des_ede3_cbc)(); else return 0L; } EVP_CIPHER *KOpenSSLProxy::EVP_des_cbc() { if (K_EVP_des_cbc) return (K_EVP_des_cbc)(); else return 0L; } EVP_CIPHER *KOpenSSLProxy::EVP_rc2_cbc() { if (K_EVP_rc2_cbc) return (K_EVP_rc2_cbc)(); else return 0L; } EVP_CIPHER *KOpenSSLProxy::EVP_rc2_64_cbc() { if (K_EVP_rc2_64_cbc) return (K_EVP_rc2_64_cbc)(); else return 0L; } EVP_CIPHER *KOpenSSLProxy::EVP_rc2_40_cbc() { if (K_EVP_rc2_40_cbc) return (K_EVP_rc2_40_cbc)(); else return 0L; } int KOpenSSLProxy::i2d_X509_REQ_fp(FILE *fp, X509_REQ *x) { if (K_i2d_X509_REQ_fp) return (K_i2d_X509_REQ_fp)(fp,x); else return -1; } void KOpenSSLProxy::ERR_clear_error() { if (K_ERR_clear_error) (K_ERR_clear_error)(); } unsigned long KOpenSSLProxy::ERR_get_error() { if (K_ERR_get_error) return (K_ERR_get_error)(); else return 0xffffffff; } void KOpenSSLProxy::ERR_print_errors_fp(FILE* fp) { if (K_ERR_print_errors_fp) (K_ERR_print_errors_fp)(fp); } SSL_SESSION *KOpenSSLProxy::SSL_get1_session(SSL *ssl) { if (K_SSL_get1_session) return (K_SSL_get1_session)(ssl); else return 0L; } void KOpenSSLProxy::SSL_SESSION_free(SSL_SESSION *session) { if (K_SSL_SESSION_free) (K_SSL_SESSION_free)(session); } int KOpenSSLProxy::SSL_set_session(SSL *ssl, SSL_SESSION *session) { if (K_SSL_set_session) return (K_SSL_set_session)(ssl, session); else return -1; } SSL_SESSION *KOpenSSLProxy::d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, long length) { if (K_d2i_SSL_SESSION) return (K_d2i_SSL_SESSION)(a, pp, length); else return 0L; } int KOpenSSLProxy::i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp) { if (K_i2d_SSL_SESSION) return (K_i2d_SSL_SESSION)(in, pp); else return -1; } int KOpenSSLProxy::i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *p) { if (K_i2d_PrivateKey_fp) return (K_i2d_PrivateKey_fp)(fp, p); else return -1; } int KOpenSSLProxy::i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *p, const EVP_CIPHER *c, char *k, int klen, pem_password_cb *cb, void *u) { if (K_i2d_PKCS8PrivateKey_fp) return (K_i2d_PKCS8PrivateKey_fp)(fp, p, c, k, klen, cb, u); else return -1; } void KOpenSSLProxy::RSA_free(RSA *rsa) { if (K_RSA_free) (K_RSA_free)(rsa); } EVP_CIPHER *KOpenSSLProxy::EVP_bf_cbc() { if (K_EVP_bf_cbc) return (K_EVP_bf_cbc)(); return 0L; } int KOpenSSLProxy::X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md) { if (K_X509_REQ_sign) return (K_X509_REQ_sign)(x, pkey, md); return -1; } int KOpenSSLProxy::X509_NAME_add_entry_by_txt(X509_NAME *name, char *field, int type, unsigned char *bytes, int len, int loc, int set) { if (K_X509_NAME_add_entry_by_txt) return (K_X509_NAME_add_entry_by_txt)(name, field, type, bytes, len, loc, set); return -1; } X509_NAME *KOpenSSLProxy::X509_NAME_new() { if (K_X509_NAME_new) return (K_X509_NAME_new)(); return 0L; } int KOpenSSLProxy::X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name) { if (K_X509_REQ_set_subject_name) return (K_X509_REQ_set_subject_name)(req, name); return -1; } unsigned char *KOpenSSLProxy::ASN1_STRING_data(ASN1_STRING *x) { if (K_ASN1_STRING_data) return (K_ASN1_STRING_data)(x); return 0L; } int KOpenSSLProxy::ASN1_STRING_length(ASN1_STRING *x) { if (K_ASN1_STRING_length) return (K_ASN1_STRING_length)(x); return 0L; } STACK_OF(SSL_CIPHER) *KOpenSSLProxy::SSL_get_ciphers(const SSL* ssl) { if (K_SSL_get_ciphers) return (K_SSL_get_ciphers)(ssl); return 0L; } #endif diff --git a/kio/kssl/kopenssl.h b/kio/kssl/kopenssl.h index ab05486336..ae3398fbef 100644 --- a/kio/kssl/kopenssl.h +++ b/kio/kssl/kopenssl.h @@ -1,894 +1,954 @@ /* This file is part of the KDE libraries Copyright (C) 2001-2003 George Staikos This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // IF YOU ARE USING THIS CLASS, YOU ARE MAKING A MISTAKE. #ifndef __KOPENSSLPROXY_H #define __KOPENSSLPROXY_H #define KOSSL KOpenSSLProxy class KOpenSSLProxyPrivate; #include #include #ifdef KSSL_HAVE_SSL #define crypt _openssl_crypt #include #include #include #include #include #include #include #include #include #include #include #include #undef crypt #if OPENSSL_VERSION_NUMBER >= 0x10000000L #define STACK _STACK #define OSSL_SKVALUE_RTYPE void #define OSSL_MORECONST const #else #define OSSL_SKVALUE_RTYPE char #define OSSL_MORECONST #endif #endif /** * Dynamically load and wrap OpenSSL. * * @author George Staikos * @see KSSL * @short KDE OpenSSL Wrapper * @internal */ class KOpenSSLProxy { public: /** * Return an instance of class KOpenSSLProxy * * You cannot delete this object. It is a singleton class. */ static KOpenSSLProxy *self(); /** * Return true of libcrypto was found and loaded */ bool hasLibCrypto() const; /** * Return true of libssl was found and loaded */ bool hasLibSSL() const; /** * Destroy the class and start over - don't use this unless you know * what you are doing. */ void destroy(); // Here are the symbols that we need. #ifdef KSSL_HAVE_SSL /* * SSL_connect - initiate the TLS/SSL handshake with an TLS/SSL server */ int SSL_connect(SSL *ssl); /* * SSL_accept - initiate the TLS/SSL handshake with an TLS/SSL server */ int SSL_accept(SSL *ssl); /* * SSL_get_error - get the error code */ int SSL_get_error(SSL *ssl, int rc); /* * SSL_read - read bytes from a TLS/SSL connection. */ int SSL_read(SSL *ssl, void *buf, int num); /* * SSL_write - write bytes to a TLS/SSL connection. */ int SSL_write(SSL *ssl, const void *buf, int num); /* * SSL_new - create a new SSL structure for a connection */ SSL *SSL_new(SSL_CTX *ctx); /* * SSL_free - free an allocated SSL structure */ void SSL_free(SSL *ssl); /* * SSL_shutdown - shutdown an allocated SSL connection */ int SSL_shutdown(SSL *ssl); /* * SSL_CTX_new - create a new SSL_CTX object as framework for TLS/SSL enabled functions */ SSL_CTX *SSL_CTX_new(SSL_METHOD *method); /* * SSL_CTX_free - free an allocated SSL_CTX object */ void SSL_CTX_free(SSL_CTX *ctx); /* * SSL_set_fd - connect the SSL object with a file descriptor */ int SSL_set_fd(SSL *ssl, int fd); /* * SSL_pending - obtain number of readable bytes buffered in an SSL object */ int SSL_pending(SSL *ssl); /* * SSL_peek - obtain bytes buffered in an SSL object */ int SSL_peek(SSL *ssl, void *buf, int num); /* * SSL_CTX_set_cipher_list - choose list of available SSL_CIPHERs */ int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str); /* * SSL_CTX_set_verify - set peer certificate verification parameters */ void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, int (*verify_callback)(int, X509_STORE_CTX *)); /* * SSL_use_certificate - load certificate */ int SSL_use_certificate(SSL *ssl, X509 *x); /* * SSL_get_current_cipher - get SSL_CIPHER of a connection */ SSL_CIPHER *SSL_get_current_cipher(SSL *ssl); /* * SSL_set_options - manipulate SSL engine options * Note: These are all mapped to SSL_ctrl so call them as the comment * specifies but know that they use SSL_ctrl. They are #define * so they will map to the one in this class if called as a * member function of this class. */ /* long SSL_set_options(SSL *ssl, long options); */ /* Returns 0 if not reused, 1 if session id is reused */ /* int SSL_session_reused(SSL *ssl); */ long SSL_ctrl(SSL *ssl,int cmd, long larg, char *parg); /* * RAND_egd - set the path to the EGD */ int RAND_egd(const char *path); /* * RAND_file_name */ const char *RAND_file_name(char *buf, size_t num); /* * RAND_load_file */ int RAND_load_file(const char *filename, long max_bytes); /* * RAND_write_file */ int RAND_write_file(const char *filename); /* * TLSv1_client_method - return a TLSv1 client method object */ SSL_METHOD *TLSv1_client_method(); /* * SSLv23_client_method - return a SSLv23 client method object */ SSL_METHOD *SSLv23_client_method(); /* * SSL_get_peer_certificate - return the peer's certificate */ X509 *SSL_get_peer_certificate(SSL *s); /* * SSL_get_peer_cert_chain - get the peer's certificate chain */ STACK_OF(X509) *SSL_get_peer_cert_chain(SSL *s); /* * SSL_CIPHER_get_bits - get the number of bits in this cipher */ int SSL_CIPHER_get_bits(SSL_CIPHER *c,int *alg_bits); /* * SSL_CIPHER_get_version - get the version of this cipher */ char *SSL_CIPHER_get_version(SSL_CIPHER *c); /* * SSL_CIPHER_get_name - get the name of this cipher */ const char *SSL_CIPHER_get_name(SSL_CIPHER *c); /* * SSL_CIPHER_description - get the description of this cipher */ char *SSL_CIPHER_description(SSL_CIPHER *,char *buf,int size); /* * SSL_CTX_use_PrivateKey - set the private key for the session. * - for use with client certificates */ int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey); /* * SSL_CTX_use_certificate - set the client certificate for the session. */ int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x); /* * d2i_X509 - Convert a text representation of X509 to an X509 object */ X509 * d2i_X509(X509 **a,unsigned char **pp,long length); /* * i2d_X509 - Convert an X509 object into a text representation */ int i2d_X509(X509 *a,unsigned char **pp); /* * X509_cmp - compare two X509 objects */ int X509_cmp(X509 *a, X509 *b); /* * X509_dup - duplicate an X509 object */ X509 *X509_dup(X509 *x509); + /* + * X509_getm_notBefore - get validity start + */ + ASN1_TIME *X509_getm_notBefore(const X509 *x); + + + /* + * X509_getm_notAfter - get validity end + */ + ASN1_TIME *X509_getm_notAfter(const X509 *x); + + /* * X509_STORE_CTX_new - create an X509 store context */ X509_STORE_CTX *X509_STORE_CTX_new(void); /* * X509_STORE_CTX_free - free up an X509 store context */ void X509_STORE_CTX_free(X509_STORE_CTX *v); /* * X509_STORE_CTX_set_chain - set the certificate chain */ void X509_STORE_CTX_set_chain(X509_STORE_CTX *v, STACK_OF(X509)* x); + /* * X509_STORE_CTX_set_purpose - set the purpose of the certificate */ void X509_STORE_CTX_set_purpose(X509_STORE_CTX *v, int purpose); + + /* + * X509_STORE_CTX_get_current_cert - get the current certificate + */ + X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *v); + + + /* + * X509_STORE_CTX_set_error - set certificate error + */ + void X509_STORE_CTX_set_error(X509_STORE_CTX *v, int error); + + + /* + * X509_STORE_CTX_get_error - get certificate error + */ + int X509_STORE_CTX_get_error(X509_STORE_CTX *v); + + /* * X509_verify_cert - verify the certificate */ int X509_verify_cert(X509_STORE_CTX *v); /* * X509_STORE_new - create an X509 store */ X509_STORE *X509_STORE_new(void); /* * X509_STORE_free - free up an X509 store */ void X509_STORE_free(X509_STORE *v); + /* + * X509_STORE_set_verify_cb - set verify callback + */ + void X509_STORE_set_verify_cb(X509_STORE *v, int (*verify_cb)(int, X509_STORE_CTX *)); + + /* * X509_free - free up an X509 */ void X509_free(X509 *v); /* * X509_NAME_oneline - return the X509 data in a string */ char *X509_NAME_oneline(X509_NAME *a, char *buf, int size); /* * X509_get_subject_name - return the X509_NAME for the subject field */ X509_NAME *X509_get_subject_name(X509 *a); /* * X509_get_issuer_name - return the X509_NAME for the issuer field */ X509_NAME *X509_get_issuer_name(X509 *a); + /* + * X509_get0_signature - return X509 signature and signature algorithm + */ + void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg, const X509 *x); + + /* * X509_STORE_add_lookup - add a lookup file/method to an X509 store */ X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m); /* * X509_LOOKUP_file - Definition of the LOOKUP_file method */ X509_LOOKUP_METHOD *X509_LOOKUP_file(void); /* * X509_LOOKUP_free - Free an X509_LOOKUP */ void X509_LOOKUP_free(X509_LOOKUP *x); /* * X509_LOOKUP_ctrl - This is not normally called directly (use macros) */ int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl, char **ret); /* * X509_STORE_CTX_init - initialize an X509 STORE context */ void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain); /* * CRYPTO_free - free up an internally allocated object */ +#if OPENSSL_VERSION_NUMBER < 0x10100000L void CRYPTO_free(void *x); +#else + void CRYPTO_free(void *x, const char *file, int line); +#endif /* * BIO_new - create new BIO */ BIO *BIO_new(BIO_METHOD *type); /* * BIO methods - only one defined here yet */ BIO_METHOD *BIO_s_mem(void); /* * BIO_new_fp - nastiness called BIO - used to create BIO* from FILE* */ BIO *BIO_new_fp(FILE *stream, int close_flag); /* * BIO_new_mem_buf - read only BIO from memory region */ BIO *BIO_new_mem_buf(void *buf, int len); /* * BIO_free - nastiness called BIO - used to destroy BIO* */ int BIO_free(BIO *a); /* * BIO_ctrl - BIO control method */ long BIO_ctrl(BIO *bp,int cmd,long larg,void *parg); /* * BIO_write - equivalent to ::write for BIO */ int BIO_write(BIO *b, const void *data, int len); /* * PEM_write_bio_X509 - write a PEM encoded cert to a BIO* */ int PEM_write_bio_X509(BIO *bp, X509 *x); /* * ASN1_item_i2d_fp - used for netscape output */ int ASN1_item_i2d_fp(FILE *out, unsigned char *x); /* * ASN1_d2i_fp - read an X509 from a DER encoded file (buf can be NULL) */ X509 *X509_d2i_fp(FILE *out, X509** buf); /* * X509_print - print the text form of an X509 */ int X509_print(FILE *fp, X509 *x); /* * Read a PKCS#12 cert from fp */ PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12); /* * Change the password on a PKCS#12 cert */ int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass); /* * Write a PKCS#12 to mem */ int i2d_PKCS12(PKCS12 *p12, unsigned char **p); /* * Write a PKCS#12 to FILE* */ int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); /* * Create a new PKCS#12 object */ PKCS12 *PKCS12_new(void); /* * Destroy that PKCS#12 that you created! */ void PKCS12_free(PKCS12 *a); /* * Parse the PKCS#12 */ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca); /* * Free the Private Key */ void EVP_PKEY_free(EVP_PKEY *x); /* * Pop off the stack */ - char *sk_pop(STACK *s); + char *OPENSSL_sk_pop(STACK *s); /* * Free the stack */ - void sk_free(STACK *s); + void OPENSSL_sk_free(STACK *s); #if OPENSSL_VERSION_NUMBER >= 0x10000000L - void sk_free(void *s) { return sk_free(reinterpret_cast(s)); } + void OPENSSL_sk_free(void *s) { return OPENSSL_sk_free(reinterpret_cast(s)); } #endif /* * Number of elements in the stack */ - int sk_num(STACK *s); + int OPENSSL_sk_num(STACK *s); /* * Value of element n in the stack */ - char *sk_value(STACK *s, int n); + char *OPENSSL_sk_value(STACK *s, int n); #if OPENSSL_VERSION_NUMBER >= 0x10000000L - char *sk_value(void *s, int n) { return sk_value(reinterpret_cast(s), n); } + char *OPENSSL_sk_value(void *s, int n) { return OPENSSL_sk_value(reinterpret_cast(s), n); } #endif /* * Create a new stack */ - STACK *sk_new(int (*cmp)()); + STACK *OPENSSL_sk_new(int (*cmp)()); /* * Add an element to the stack */ - int sk_push(STACK *s, char *d); + int OPENSSL_sk_push(STACK *s, char *d); #if OPENSSL_VERSION_NUMBER >= 0x10000000L - int sk_push(void *s, void *d) { return sk_push(reinterpret_cast(s), reinterpret_cast(d)); } + int OPENSSL_sk_push(void *s, void *d) { return OPENSSL_sk_push(reinterpret_cast(s), reinterpret_cast(d)); } #endif /* * Duplicate the stack */ - STACK *sk_dup(STACK *s); + STACK *OPENSSL_sk_dup(STACK *s); /* * Convert an ASN1_INTEGER to its text form */ char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, ASN1_INTEGER *aint); /* * Get the certificate's serial number */ ASN1_INTEGER *X509_get_serialNumber(X509 *x); /* * Get the certificate's public key */ EVP_PKEY *X509_get_pubkey(X509 *x); /* * Convert the public key to a decimal form */ int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp); /* * Check the private key of a PKCS bundle against the X509 */ int X509_check_private_key(X509 *x, EVP_PKEY *p); /* * Convert a BIGNUM to a hex string */ char *BN_bn2hex(const BIGNUM *a); /* * Compute the digest of an X.509 */ int X509_digest(const X509 *x,const EVP_MD *t, unsigned char *md, unsigned int *len); /* * EVP_md5 */ EVP_MD *EVP_md5(); /* * ASN1_INTEGER free */ void ASN1_INTEGER_free(ASN1_INTEGER *x); /* * ASN1_STRING_data */ unsigned char *ASN1_STRING_data(ASN1_STRING *x); /* * ASN1_STRING_length */ int ASN1_STRING_length(ASN1_STRING *x); /* * */ int OBJ_obj2nid(ASN1_OBJECT *o); /* * */ const char * OBJ_nid2ln(int n); /* * get the number of extensions */ int X509_get_ext_count(X509 *x); /* * */ int X509_get_ext_by_NID(X509 *x, int nid, int lastpos); /* * */ int X509_get_ext_by_OBJ(X509 *x,ASN1_OBJECT *obj,int lastpos); /* * */ X509_EXTENSION *X509_get_ext(X509 *x, int loc); /* * */ X509_EXTENSION *X509_delete_ext(X509 *x, int loc); /* * */ int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); /* * */ void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx); /* * */ char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *ia5); /* * */ int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n); /* * */ PKCS7 *PKCS7_new(void); /* * */ void PKCS7_free(PKCS7 *a); /* * */ void PKCS7_content_free(PKCS7 *a); /* * */ int i2d_PKCS7(PKCS7 *a, unsigned char **pp); /* * */ PKCS7 *d2i_PKCS7(PKCS7 **a, unsigned char **pp,long length); /* * */ int i2d_PKCS7_fp(FILE *fp,PKCS7 *p7); /* * */ PKCS7 *d2i_PKCS7_fp(FILE *fp,PKCS7 **p7); /* * */ int i2d_PKCS7_bio(BIO *bp,PKCS7 *p7); /* * */ PKCS7 *d2i_PKCS7_bio(BIO *bp,PKCS7 **p7); /* * */ PKCS7 *PKCS7_dup(PKCS7 *p7); /* * Create a PKCS7 signature / signed message */ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, int flags); /* * Verify a PKCS7 signature. */ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, BIO *indata, BIO *out, int flags); /* * Get signers of a verified PKCS7 signature */ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags); /* * PKCS7 encrypt message */ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher, int flags); /* * decrypt PKCS7 message */ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags); /* * Load a CA list file. */ STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file); /* * Load a file of PEM encoded objects. */ STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u); /* * Get the number of purposes available */ int X509_PURPOSE_get_count(); /* * Get the ID of a purpose */ int X509_PURPOSE_get_id(X509_PURPOSE *); /* * Check the existence of purpose id "id" in x. for CA, set ca = 1, else 0 */ int X509_check_purpose(X509 *x, int id, int ca); /* * Get the purpose with index #idx */ X509_PURPOSE * X509_PURPOSE_get0(int idx); /* * Create a new Private KEY */ EVP_PKEY* EVP_PKEY_new(); /* * Assign a private key */ int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key); + /* + * Get key type + */ + int EVP_PKEY_base_id(EVP_PKEY *pkey); + + RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); + void RSA_get0_key(RSA *rsa, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); + DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey); + void DSA_get0_pqg(DSA *dsa, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); + void DSA_get0_key(DSA *dsa, const BIGNUM **pub_key, const BIGNUM **priv_key); + + /* * Generate a RSA key */ RSA *RSA_generate_key(int bits, unsigned long e, void (*callback)(int,int,void *), void *cb_arg); /* * Create/destroy a certificate request */ X509_REQ *X509_REQ_new(); void X509_REQ_free(X509_REQ *a); /* * Set the public key in the REQ object */ int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey); /* for testing */ int i2d_X509_REQ_fp(FILE *fp, X509_REQ *x); /* SMime support */ STACK *X509_get1_email(X509 *x); void X509_email_free(STACK *sk); /* Ciphers needed for SMime */ EVP_CIPHER *EVP_des_ede3_cbc(); EVP_CIPHER *EVP_des_cbc(); EVP_CIPHER *EVP_rc2_cbc(); EVP_CIPHER *EVP_rc2_64_cbc(); EVP_CIPHER *EVP_rc2_40_cbc(); /* clear the current error - use this often*/ void ERR_clear_error(); /* retrieve the latest error */ unsigned long ERR_get_error(); /* Print the errors to this stream */ void ERR_print_errors_fp(FILE *fp); /* Get a pointer to the SSL session id (reference counted) */ SSL_SESSION *SSL_get1_session(SSL *ssl); /* Frees a pointer to the SSL session id (reference decremented if needed) */ void SSL_SESSION_free(SSL_SESSION *session); /* Set the SSL session to reuse. */ int SSL_set_session(SSL *ssl, SSL_SESSION *session); /* Decode ASN.1 to SSL_SESSION */ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, unsigned char **pp, long length); /* Encode SSL_SESSION to ASN.1 */ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); /* Write privatekey to FILE stream */ int i2d_PrivateKey_fp(FILE*, EVP_PKEY*); /* Write PKCS#8privatekey to FILE stream */ int i2d_PKCS8PrivateKey_fp(FILE*, EVP_PKEY*, const EVP_CIPHER*, char*, int, pem_password_cb*, void*); /* Free RSA structure */ void RSA_free(RSA*); /* Get a blowfish CBC pointer */ EVP_CIPHER *EVP_bf_cbc(); /* Sign a CSR */ int X509_REQ_sign(X509_REQ*, EVP_PKEY*, const EVP_MD*); /* add a name entry */ int X509_NAME_add_entry_by_txt(X509_NAME*, char*, int, unsigned char*, int, int, int); /* Create a name */ X509_NAME *X509_NAME_new(); /* Set the subject */ int X509_REQ_set_subject_name(X509_REQ*,X509_NAME*); /* get list of available SSL_CIPHER's sorted by preference */ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL* ssl); #endif private: friend class KOpenSSLProxyPrivate; KOpenSSLProxy(); ~KOpenSSLProxy(); KOpenSSLProxyPrivate * const d; }; #endif diff --git a/kio/kssl/kssl.cpp b/kio/kssl/kssl.cpp index c36db55a42..faba1bb5ab 100644 --- a/kio/kssl/kssl.cpp +++ b/kio/kssl/kssl.cpp @@ -1,216 +1,212 @@ /* This file is part of the KDE project * * Copyright (C) 2000-2003 George Staikos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kssl.h" #include #include // this hack provided by Malte Starostik to avoid glibc/openssl bug // on some systems #ifdef KSSL_HAVE_SSL #include #include #include #define crypt _openssl_crypt #include #include #include #include #include #undef crypt #endif #include #include #include #include #include #include #include #include #include #ifdef __GNUC__ #warning "kssl.cc contains temporary functions! Clean up" #warning "kssl.cc needs to be ported to QSslSocket" #endif -#define sk_dup d->kossl->sk_dup - class KSSLPrivate { public: KSSLPrivate() { kossl = KOpenSSLProxy::self(); } ~KSSLPrivate() {} KSSLCertificate::KSSLValidation m_cert_vfy_res; #ifdef KSSL_HAVE_SSL SSL *m_ssl; SSL_CTX *m_ctx; SSL_METHOD *m_meth; #endif KOSSL *kossl; }; KSSL::KSSL(bool init) { d = new KSSLPrivate; m_bInit = false; m_bAutoReconfig = true; m_cfg = new KSSLSettings(); #ifdef KSSL_HAVE_SSL d->m_ssl = 0L; #endif if (init) initialize(); } KSSL::~KSSL() { close(); delete m_cfg; delete d; } int KSSL::seedWithEGD() { int rc = 0; #ifdef KSSL_HAVE_SSL if (m_cfg->useEGD() && !m_cfg->getEGDPath().isEmpty()) { rc = d->kossl->RAND_egd(m_cfg->getEGDPath().toLatin1().constData()); if (rc < 0) kDebug(7029) << "KSSL: Error seeding PRNG with the EGD."; else kDebug(7029) << "KSSL: PRNG was seeded with " << rc << " bytes from the EGD." << endl; } else if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { rc = d->kossl->RAND_load_file(m_cfg->getEGDPath().toLatin1().constData(), -1); if (rc < 0) kDebug(7029) << "KSSL: Error seeding PRNG with the entropy file."; else kDebug(7029) << "KSSL: PRNG was seeded with " << rc << " bytes from the entropy file." << endl; } #endif return rc; } bool KSSL::initialize() { #ifdef KSSL_HAVE_SSL kDebug(7029) << "KSSL initialize"; if (m_bInit) return false; if (m_bAutoReconfig) m_cfg->load(); seedWithEGD(); d->m_meth = d->kossl->SSLv23_client_method(); d->m_ctx = d->kossl->SSL_CTX_new(d->m_meth); if (d->m_ctx == 0L) { return false; } // set cipher list QString clist = m_cfg->getCipherList(); kDebug(7029) << "Cipher list: " << clist; if (!clist.isEmpty()) d->kossl->SSL_CTX_set_cipher_list(d->m_ctx, const_cast(clist.toLatin1().constData())); m_bInit = true; return true; #else return false; #endif } void KSSL::close() { #ifdef KSSL_HAVE_SSL //kDebug(7029) << "KSSL close"; if (!m_bInit) return; if (d->m_ssl) { d->kossl->SSL_shutdown(d->m_ssl); d->kossl->SSL_free(d->m_ssl); d->m_ssl = 0L; } d->kossl->SSL_CTX_free(d->m_ctx); if (m_cfg->useEFile() && !m_cfg->getEGDPath().isEmpty()) { d->kossl->RAND_write_file(m_cfg->getEGDPath().toLatin1().constData()); } m_bInit = false; #endif } bool KSSL::reInitialize() { close(); return initialize(); } // get the callback file - it's hidden away in here //#include "ksslcallback.c" bool KSSL::reconfig() { return reInitialize(); } void KSSL::setAutoReconfig(bool ar) { m_bAutoReconfig = ar; } bool KSSL::setSettings(KSSLSettings *settings) { delete m_cfg; m_cfg = settings; return reconfig(); } KSSLSettings * KSSL::settings() { return m_cfg; } #ifdef KSSL_HAVE_SSL bool KSSL::m_bSSLWorks = true; #else bool KSSL::m_bSSLWorks = false; #endif bool KSSL::doesSSLWork() { return m_bSSLWorks; } -#undef sk_dup - diff --git a/kio/kssl/ksslcallback.c b/kio/kssl/ksslcallback.c index 516b916337..38e94356e8 100644 --- a/kio/kssl/ksslcallback.c +++ b/kio/kssl/ksslcallback.c @@ -1,89 +1,89 @@ /* This file is part of the KDE project * * Copyright (C) 2000 George Staikos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef KSSL_HAVE_SSL #ifndef _kde_ksslcallback_c #define _kde_ksslcallback_c X509 *KSSL_X509CallBack_ca; bool KSSL_X509CallBack_ca_found; extern "C" { static int X509Callback(int ok, X509_STORE_CTX *ctx) { - kDebug(7029) << "X509Callback: ok = " << ok << " error = " << ctx->error << " depth = " << ctx->error_depth; + //kDebug(7029) << "X509Callback: ok = " << ok << " error = " << ctx->error << " depth = " << ctx->error_depth; // Here is how this works. We put "ok = 1;" in any case that we // don't consider to be an error. In that case, it will return OK // for the certificate check as long as there are no other critical // errors. Don't forget that there can be multiple errors. // // Of course we can also put other code in here but any data returned // back will not be threadsafe ofcourse. if (KSSL_X509CallBack_ca) { - if (KOSSL::self()->X509_cmp(ctx->current_cert, KSSL_X509CallBack_ca) != 0) + if (KOSSL::self()->X509_cmp(KOSSL::self()->X509_STORE_CTX_get_current_cert(ctx), KSSL_X509CallBack_ca) != 0) return 1; // Ignore errors for this certificate KSSL_X509CallBack_ca_found = true; } if (!ok) { - switch (ctx->error) { + switch (KOSSL::self()->X509_STORE_CTX_get_error(ctx)) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: case X509_V_ERR_UNABLE_TO_GET_CRL: case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: case X509_V_ERR_CERT_SIGNATURE_FAILURE: case X509_V_ERR_CRL_SIGNATURE_FAILURE: case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_CRL_NOT_YET_VALID: case X509_V_ERR_CRL_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: case X509_V_ERR_OUT_OF_MEM: case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: case X509_V_ERR_CERT_CHAIN_TOO_LONG: case X509_V_ERR_CERT_REVOKED: case X509_V_ERR_INVALID_CA: case X509_V_ERR_PATH_LENGTH_EXCEEDED: case X509_V_ERR_INVALID_PURPOSE: case X509_V_ERR_CERT_UNTRUSTED: case X509_V_ERR_CERT_REJECTED: case X509_V_ERR_APPLICATION_VERIFICATION: default: break; } } return(ok); } } #endif #endif diff --git a/kio/kssl/ksslcertchain.cpp b/kio/kssl/ksslcertchain.cpp index 2be7995bf8..cdfab2b5ae 100644 --- a/kio/kssl/ksslcertchain.cpp +++ b/kio/kssl/ksslcertchain.cpp @@ -1,215 +1,194 @@ /* This file is part of the KDE project * * Copyright (C) 2001 George Staikos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ksslcertchain.h" #include #include #include "kssldefs.h" #include "ksslcertificate.h" // this hack provided by Malte Starostik to avoid glibc/openssl bug // on some systems #ifdef KSSL_HAVE_SSL #define crypt _openssl_crypt #include #include #include #include #include #include #include #undef crypt #endif #include #include #include -#ifdef KSSL_HAVE_SSL -#define sk_new d->kossl->sk_new -#define sk_push d->kossl->sk_push -#define sk_free d->kossl->sk_free -#define sk_value d->kossl->sk_value -#define sk_num d->kossl->sk_num -#define sk_dup d->kossl->sk_dup -#define sk_pop d->kossl->sk_pop -#endif - class KSSLCertChainPrivate { public: KSSLCertChainPrivate() { kossl = KOSSL::self(); } ~KSSLCertChainPrivate() { } KOSSL *kossl; }; KSSLCertChain::KSSLCertChain() :d(new KSSLCertChainPrivate) { _chain = NULL; } KSSLCertChain::~KSSLCertChain() { #ifdef KSSL_HAVE_SSL if (_chain) { STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; for (;;) { - X509* x5 = sk_X509_pop(x); + X509 *x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(reinterpret_cast(x))); if (!x5) break; d->kossl->X509_free(x5); } - sk_X509_free(x); + d->kossl->OPENSSL_sk_free(reinterpret_cast(x)); } #endif delete d; } bool KSSLCertChain::isValid() { return (_chain && depth() > 0); } KSSLCertChain *KSSLCertChain::replicate() { KSSLCertChain *x = new KSSLCertChain; QList ch = getChain(); x->setChain(ch); // this will do a deep copy for us qDeleteAll(ch); return x; } int KSSLCertChain::depth() { #ifdef KSSL_HAVE_SSL - return sk_X509_num((STACK_OF(X509)*)_chain); + return d->kossl->OPENSSL_sk_num(static_cast(_chain)); #endif return 0; } void *KSSLCertChain::rawChain() { return _chain; } QList KSSLCertChain::getChain() const { QList cl; if (!_chain) return cl; #ifdef KSSL_HAVE_SSL STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; - for (int i = 0; i < sk_X509_num(x); i++) { - X509* x5 = sk_X509_value(x, i); + for (int i = 0; i < d->kossl->OPENSSL_sk_num(reinterpret_cast(x)); i++) { + X509 *x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(reinterpret_cast(x), i)); if (!x5) continue; KSSLCertificate *nc = new KSSLCertificate; nc->setCert(d->kossl->X509_dup(x5)); cl.append(nc); } #endif return cl; } void KSSLCertChain::setChain(const QList& chain) { #ifdef KSSL_HAVE_SSL if (_chain) { STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; for (;;) { - X509* x5 = sk_X509_pop(x); + X509 *x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(reinterpret_cast(x))); if (!x5) break; d->kossl->X509_free(x5); } - sk_X509_free(x); - _chain = NULL; + d->kossl->OPENSSL_sk_free(reinterpret_cast(x)); + _chain = NULL; } if (chain.isEmpty()) return; - _chain = (void *)sk_new(NULL); + _chain = (void *)d->kossl->OPENSSL_sk_new(NULL); foreach (KSSLCertificate *x, chain) { - sk_X509_push((STACK_OF(X509)*)_chain, d->kossl->X509_dup(x->getCert())); + d->kossl->OPENSSL_sk_push(static_cast(_chain), d->kossl->X509_dup(x->getCert())); } #endif } void KSSLCertChain::setChain(void *stack_of_x509) { #ifdef KSSL_HAVE_SSL if (_chain) { STACK_OF(X509) *x = (STACK_OF(X509) *)_chain; for (;;) { - X509* x5 = sk_X509_pop(x); + X509 *x5 = reinterpret_cast(d->kossl->OPENSSL_sk_pop(reinterpret_cast(x))); if (!x5) break; d->kossl->X509_free(x5); } - sk_X509_free(x); + d->kossl->OPENSSL_sk_free(reinterpret_cast(x)); _chain = NULL; } if (!stack_of_x509) return; -_chain = (void *)sk_new(NULL); +_chain = (void *)d->kossl->OPENSSL_sk_new(NULL); STACK_OF(X509) *x = (STACK_OF(X509) *)stack_of_x509; - for (int i = 0; i < sk_X509_num(x); i++) { - X509* x5 = sk_X509_value(x, i); + for (int i = 0; i < d->kossl->OPENSSL_sk_num(reinterpret_cast(x)); i++) { + X509 *x5 = reinterpret_cast(d->kossl->OPENSSL_sk_value(reinterpret_cast(x), i)); if (!x5) continue; - sk_X509_push((STACK_OF(X509)*)_chain,d->kossl->X509_dup(x5)); + d->kossl->OPENSSL_sk_push(reinterpret_cast(_chain), d->kossl->X509_dup(x5)); } #else _chain = NULL; #endif } void KSSLCertChain::setCertChain(const QStringList& chain) { QList cl; for (QStringList::ConstIterator s = chain.begin(); s != chain.end(); ++s) { KSSLCertificate *c = KSSLCertificate::fromString((*s).toLocal8Bit()); if (c) { cl.append(c); } } setChain(cl); } - -#ifdef KSSL_HAVE_SSL -#undef sk_new -#undef sk_push -#undef sk_free -#undef sk_value -#undef sk_num -#undef sk_dup -#undef sk_pop -#endif - diff --git a/kio/kssl/ksslcertificate.cpp b/kio/kssl/ksslcertificate.cpp index 0d4fbd9cdc..c93d5c5b22 100644 --- a/kio/kssl/ksslcertificate.cpp +++ b/kio/kssl/ksslcertificate.cpp @@ -1,1346 +1,1358 @@ /* This file is part of the KDE project * * Copyright (C) 2000-2003 George Staikos * 2008 Richard Hartmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "ksslcertificate.h" #include #include #include #include #include #include #include "kssldefs.h" #include "ksslcertchain.h" #include "ksslutils.h" #include #include #include #include #include #include #include #ifdef HAVE_SYS_STAT_H #include #endif // this hack provided by Malte Starostik to avoid glibc/openssl bug // on some systems #ifdef KSSL_HAVE_SSL #define crypt _openssl_crypt #include #include #include #include #include #undef crypt #endif #include #include #include "ksslx509v3.h" static char hv[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; class KSSLCertificatePrivate { public: KSSLCertificatePrivate() { kossl = KOSSL::self(); _lastPurpose = KSSLCertificate::None; } ~KSSLCertificatePrivate() { } KSSLCertificate::KSSLValidation m_stateCache; bool m_stateCached; #ifdef KSSL_HAVE_SSL X509 *m_cert; #endif KOSSL *kossl; KSSLCertChain _chain; KSSLX509V3 _extensions; KSSLCertificate::KSSLPurpose _lastPurpose; }; KSSLCertificate::KSSLCertificate() { d = new KSSLCertificatePrivate; d->m_stateCached = false; KGlobal::dirs()->addResourceType("kssl", "data", "kssl"); #ifdef KSSL_HAVE_SSL d->m_cert = NULL; #endif } KSSLCertificate::KSSLCertificate(const KSSLCertificate& x) { d = new KSSLCertificatePrivate; d->m_stateCached = false; KGlobal::dirs()->addResourceType("kssl", "data", "kssl"); #ifdef KSSL_HAVE_SSL d->m_cert = NULL; setCert(KOSSL::self()->X509_dup(const_cast(x).getCert())); KSSLCertChain *c = x.d->_chain.replicate(); setChain(c->rawChain()); delete c; #endif } KSSLCertificate::~KSSLCertificate() { #ifdef KSSL_HAVE_SSL if (d->m_cert) { d->kossl->X509_free(d->m_cert); } #endif delete d; } KSSLCertChain& KSSLCertificate::chain() { return d->_chain; } KSSLCertificate *KSSLCertificate::fromX509(X509 *x5) { KSSLCertificate *n = NULL; #ifdef KSSL_HAVE_SSL if (x5) { n = new KSSLCertificate; n->setCert(KOSSL::self()->X509_dup(x5)); } #endif return n; } KSSLCertificate *KSSLCertificate::fromString(const QByteArray &cert) { KSSLCertificate *n = NULL; #ifdef KSSL_HAVE_SSL if (cert.isEmpty()) { return NULL; } QByteArray qba = QByteArray::fromBase64(cert); unsigned char *qbap = reinterpret_cast(qba.data()); X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); if (!x5c) { return NULL; } n = new KSSLCertificate; n->setCert(x5c); #endif return n; } QString KSSLCertificate::getSubject() const { QString rc = ""; #ifdef KSSL_HAVE_SSL char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_subject_name(d->m_cert), 0, 0); if (!t) { return rc; } rc = t; d->kossl->OPENSSL_free(t); #endif return rc; } QString KSSLCertificate::getSerialNumber() const { QString rc = ""; #ifdef KSSL_HAVE_SSL ASN1_INTEGER *aint = d->kossl->X509_get_serialNumber(d->m_cert); if (aint) { rc = ASN1_INTEGER_QString(aint); // d->kossl->ASN1_INTEGER_free(aint); this makes the sig test fail } #endif return rc; } QString KSSLCertificate::getSignatureText() const { QString rc = ""; #ifdef KSSL_HAVE_SSL char *s; int n, i; - i = d->kossl->OBJ_obj2nid(d->m_cert->sig_alg->algorithm); + const X509_ALGOR *algor; + const ASN1_BIT_STRING *sig; + d->kossl->X509_get0_signature(&sig, &algor, d->m_cert); + i = d->kossl->OBJ_obj2nid(algor->algorithm); rc = i18n("Signature Algorithm: "); rc += (i == NID_undef)?i18n("Unknown"):QString(d->kossl->OBJ_nid2ln(i)); rc += '\n'; rc += i18n("Signature Contents:"); - n = d->m_cert->signature->length; - s = (char *)d->m_cert->signature->data; + n = sig->length; + s = (char *)sig->data; for (i = 0; i < n; ++i) { if (i%20 != 0) { rc += ':'; } else { rc += '\n'; } rc.append(QChar(hv[(s[i]&0xf0)>>4])); rc.append(QChar(hv[s[i]&0x0f])); } #endif return rc; } void KSSLCertificate::getEmails(QStringList &to) const { to.clear(); #ifdef KSSL_HAVE_SSL if (!d->m_cert) { return; } STACK *s = d->kossl->X509_get1_email(d->m_cert); + const int size = d->kossl->OPENSSL_sk_num(s); if (s) { - for(int n=0; n < s->num; n++) { - to.append(d->kossl->sk_value(s,n)); + for(int n=0; n < size; n++) { + to.append(d->kossl->OPENSSL_sk_value(s,n)); } d->kossl->X509_email_free(s); } #endif } QString KSSLCertificate::getKDEKey() const { return getSubject() + " (" + getMD5DigestText() + ')'; } QString KSSLCertificate::getMD5DigestFromKDEKey(const QString &k) { QString rc; int pos = k.lastIndexOf('('); if (pos != -1) { unsigned int len = k.length(); if (k.at(len-1) == ')') { rc = k.mid(pos+1, len-pos-2); } } return rc; } QString KSSLCertificate::getMD5DigestText() const { QString rc = ""; #ifdef KSSL_HAVE_SSL unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { return rc; } for (unsigned int j = 0; j < n; j++) { if (j > 0) { rc += ':'; } rc.append(QChar(hv[(md[j]&0xf0)>>4])); rc.append(QChar(hv[md[j]&0x0f])); } #endif return rc; } QString KSSLCertificate::getMD5Digest() const { QString rc = ""; #ifdef KSSL_HAVE_SSL unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; if (!d->kossl->X509_digest(d->m_cert, d->kossl->EVP_md5(), md, &n)) { return rc; } for (unsigned int j = 0; j < n; j++) { rc.append(QLatin1Char(hv[(md[j]&0xf0)>>4])); rc.append(QLatin1Char(hv[md[j]&0x0f])); } #endif return rc; } QString KSSLCertificate::getKeyType() const { QString rc = ""; #ifdef KSSL_HAVE_SSL EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); if (pkey) { #ifndef NO_RSA - if (pkey->type == EVP_PKEY_RSA) { + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { rc = "RSA"; } else #endif #ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) { + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { rc = "DSA"; } else #endif rc = "Unknown"; d->kossl->EVP_PKEY_free(pkey); } #endif return rc; } QString KSSLCertificate::getPublicKeyText() const { QString rc = ""; char *x = NULL; #ifdef KSSL_HAVE_SSL EVP_PKEY *pkey = d->kossl->X509_get_pubkey(d->m_cert); if (pkey) { rc = i18nc("Unknown", "Unknown key algorithm"); #ifndef NO_RSA - if (pkey->type == EVP_PKEY_RSA) { - x = d->kossl->BN_bn2hex(pkey->pkey.rsa->n); + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_RSA) { + const BIGNUM *n, *e; + d->kossl->RSA_get0_key(d->kossl->EVP_PKEY_get0_RSA(pkey), &n, &e, NULL); + x = d->kossl->BN_bn2hex(n); rc = i18n("Key type: RSA (%1 bit)", strlen(x)*4) + '\n'; rc += i18n("Modulus: "); for (unsigned int i = 0; i < strlen(x); i++) { if (i%40 != 0 && i%2 == 0) { rc += ':'; } else if (i%40 == 0) { rc += '\n'; } rc += x[i]; } rc += '\n'; d->kossl->OPENSSL_free(x); - x = d->kossl->BN_bn2hex(pkey->pkey.rsa->e); + x = d->kossl->BN_bn2hex(e); rc += i18n("Exponent: 0x") + QLatin1String(x) + QLatin1String("\n"); d->kossl->OPENSSL_free(x); } #endif #ifndef NO_DSA - if (pkey->type == EVP_PKEY_DSA) { - x = d->kossl->BN_bn2hex(pkey->pkey.dsa->p); + if (d->kossl->EVP_PKEY_base_id(pkey) == EVP_PKEY_DSA) { + DSA *dsa = d->kossl->EVP_PKEY_get0_DSA(pkey); + const BIGNUM *p, *q, *g; + d->kossl->DSA_get0_pqg(dsa, &p, &q, &g); + x = d->kossl->BN_bn2hex(p); // hack - this may not be always accurate rc = i18n("Key type: DSA (%1 bit)", strlen(x)*4) + '\n'; rc += i18n("Prime: "); for (unsigned int i = 0; i < strlen(x); i++) { if (i%40 != 0 && i%2 == 0) { rc += ':'; } else if (i%40 == 0) { rc += '\n'; } rc += x[i]; } rc += '\n'; d->kossl->OPENSSL_free(x); - x = d->kossl->BN_bn2hex(pkey->pkey.dsa->q); + x = d->kossl->BN_bn2hex(q); rc += i18n("160 bit prime factor: "); for (unsigned int i = 0; i < strlen(x); i++) { if (i%40 != 0 && i%2 == 0) { rc += ':'; } else if (i%40 == 0) { rc += '\n'; } rc += x[i]; } rc += '\n'; d->kossl->OPENSSL_free(x); - x = d->kossl->BN_bn2hex(pkey->pkey.dsa->g); + x = d->kossl->BN_bn2hex(g); rc += QString("g: "); for (unsigned int i = 0; i < strlen(x); i++) { if (i%40 != 0 && i%2 == 0) { rc += ':'; } else if (i%40 == 0) { rc += '\n'; } rc += x[i]; } rc += '\n'; d->kossl->OPENSSL_free(x); - x = d->kossl->BN_bn2hex(pkey->pkey.dsa->pub_key); + const BIGNUM *pub_key; + d->kossl->DSA_get0_key(dsa, &pub_key, NULL); + x = d->kossl->BN_bn2hex(pub_key); rc += i18n("Public key: "); for (unsigned int i = 0; i < strlen(x); i++) { if (i%40 != 0 && i%2 == 0) { rc += ':'; } else if (i%40 == 0) { rc += '\n'; } rc += x[i]; } rc += '\n'; d->kossl->OPENSSL_free(x); } #endif d->kossl->EVP_PKEY_free(pkey); } #endif return rc; } QString KSSLCertificate::getIssuer() const { QString rc = ""; #ifdef KSSL_HAVE_SSL char *t = d->kossl->X509_NAME_oneline(d->kossl->X509_get_issuer_name(d->m_cert), 0, 0); if (!t) { return rc; } rc = t; d->kossl->OPENSSL_free(t); #endif return rc; } void KSSLCertificate::setChain(void *c) { #ifdef KSSL_HAVE_SSL d->_chain.setChain(c); #endif d->m_stateCached = false; d->m_stateCache = KSSLCertificate::Unknown; } void KSSLCertificate::setCert(X509 *c) { #ifdef KSSL_HAVE_SSL d->m_cert = c; if (c) { d->_extensions.flags = 0; d->kossl->X509_check_purpose(c, -1, 0); // setup the fields (!!) #if 0 kDebug(7029) << "---------------- Certificate ------------------" << endl; kDebug(7029) << getSubject(); #endif for (int j = 0; j < d->kossl->X509_PURPOSE_get_count(); j++) { X509_PURPOSE *ptmp = d->kossl->X509_PURPOSE_get0(j); int id = d->kossl->X509_PURPOSE_get_id(ptmp); for (int ca = 0; ca < 2; ca++) { int idret = d->kossl->X509_check_purpose(c, id, ca); if (idret == 1 || idret == 2) { // have it // kDebug() << "PURPOSE: " << id << (ca?" CA":""); if (!ca) { d->_extensions.flags |= (1L <<(id-1)); } else d->_extensions.flags |= (1L <<(16+id-1)); } else { if (!ca) { d->_extensions.flags &= ~(1L <<(id-1)); } else d->_extensions.flags &= ~(1L <<(16+id-1)); } } } #if 0 kDebug(7029) << "flags: " << QString::number(c->ex_flags, 2) << "\nkeyusage: " << QString::number(c->ex_kusage, 2) << "\nxkeyusage: " << QString::number(c->ex_xkusage, 2) << "\nnscert: " << QString::number(c->ex_nscert, 2) << endl; if (c->ex_flags & EXFLAG_KUSAGE) kDebug(7029) << " --- Key Usage extensions found"; else kDebug(7029) << " --- Key Usage extensions NOT found"; if (c->ex_flags & EXFLAG_XKUSAGE) kDebug(7029) << " --- Extended key usage extensions found"; else kDebug(7029) << " --- Extended key usage extensions NOT found"; if (c->ex_flags & EXFLAG_NSCERT) kDebug(7029) << " --- NS extensions found"; else kDebug(7029) << " --- NS extensions NOT found"; if (d->_extensions.certTypeSSLCA()) kDebug(7029) << "NOTE: this is an SSL CA file."; else kDebug(7029) << "NOTE: this is NOT an SSL CA file."; if (d->_extensions.certTypeEmailCA()) kDebug(7029) << "NOTE: this is an EMAIL CA file."; else kDebug(7029) << "NOTE: this is NOT an EMAIL CA file."; if (d->_extensions.certTypeCodeCA()) kDebug(7029) << "NOTE: this is a CODE CA file."; else kDebug(7029) << "NOTE: this is NOT a CODE CA file."; if (d->_extensions.certTypeSSLClient()) kDebug(7029) << "NOTE: this is an SSL client."; else kDebug(7029) << "NOTE: this is NOT an SSL client."; if (d->_extensions.certTypeSSLServer()) kDebug(7029) << "NOTE: this is an SSL server."; else kDebug(7029) << "NOTE: this is NOT an SSL server."; if (d->_extensions.certTypeNSSSLServer()) kDebug(7029) << "NOTE: this is a NETSCAPE SSL server."; else kDebug(7029) << "NOTE: this is NOT a NETSCAPE SSL server."; if (d->_extensions.certTypeSMIME()) kDebug(7029) << "NOTE: this is an SMIME certificate."; else kDebug(7029) << "NOTE: this is NOT an SMIME certificate."; if (d->_extensions.certTypeSMIMEEncrypt()) kDebug(7029) << "NOTE: this is an SMIME encrypt cert."; else kDebug(7029) << "NOTE: this is NOT an SMIME encrypt cert."; if (d->_extensions.certTypeSMIMESign()) kDebug(7029) << "NOTE: this is an SMIME sign cert."; else kDebug(7029) << "NOTE: this is NOT an SMIME sign cert."; if (d->_extensions.certTypeCRLSign()) kDebug(7029) << "NOTE: this is a CRL signer."; else kDebug(7029) << "NOTE: this is NOT a CRL signer."; kDebug(7029) << "-----------------------------------------------" << endl; #endif } #endif d->m_stateCached = false; d->m_stateCache = KSSLCertificate::Unknown; } X509 *KSSLCertificate::getCert() { #ifdef KSSL_HAVE_SSL return d->m_cert; #endif return 0; } // pull in the callback. It's common across multiple files but we want // it to be hidden. #include "ksslcallback.c" bool KSSLCertificate::isValid(KSSLCertificate::KSSLPurpose p) { return (validate(p) == KSSLCertificate::Ok); } bool KSSLCertificate::isValid() { return isValid(KSSLCertificate::SSLServer); } int KSSLCertificate::purposeToOpenSSL(KSSLCertificate::KSSLPurpose p) const { int rc = 0; #ifdef KSSL_HAVE_SSL if (p == KSSLCertificate::SSLServer) { rc = X509_PURPOSE_SSL_SERVER; } else if (p == KSSLCertificate::SSLClient) { rc = X509_PURPOSE_SSL_CLIENT; } else if (p == KSSLCertificate::SMIMEEncrypt) { rc = X509_PURPOSE_SMIME_ENCRYPT; } else if (p == KSSLCertificate::SMIMESign) { rc = X509_PURPOSE_SMIME_SIGN; } else if (p == KSSLCertificate::Any) { rc = X509_PURPOSE_ANY; } #endif return rc; } // For backward compatibility KSSLCertificate::KSSLValidation KSSLCertificate::validate() { return validate(KSSLCertificate::SSLServer); } KSSLCertificate::KSSLValidation KSSLCertificate::validate(KSSLCertificate::KSSLPurpose purpose) { KSSLValidationList result = validateVerbose(purpose); if (result.isEmpty()) { return KSSLCertificate::Ok; } else return result.first(); } // // See apps/verify.c in OpenSSL for the source of most of this logic. // // CRL files? we don't do that yet KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose) { return validateVerbose(purpose, 0); } KSSLCertificate::KSSLValidationList KSSLCertificate::validateVerbose(KSSLCertificate::KSSLPurpose purpose, KSSLCertificate *ca) { KSSLValidationList errors; if (ca || (d->_lastPurpose != purpose)) { d->m_stateCached = false; } if (!d->m_stateCached) { d->_lastPurpose = purpose; } #ifdef KSSL_HAVE_SSL X509_STORE *certStore; X509_LOOKUP *certLookup; X509_STORE_CTX *certStoreCTX; int rc = 0; if (!d->m_cert) { errors << KSSLCertificate::Unknown; return errors; } if (d->m_stateCached) { errors << d->m_stateCache; return errors; } const QStringList qsl = KGlobal::dirs()->resourceDirs("kssl"); if (qsl.isEmpty()) { errors << KSSLCertificate::NoCARoot; return errors; } KSSLCertificate::KSSLValidation ksslv = Unknown; for (QStringList::ConstIterator j = qsl.begin(); j != qsl.end(); ++j) { KDE_struct_stat sb; QString _j = (*j) + "ca-bundle.crt"; if (-1 == KDE_stat(_j.toLatin1().constData(), &sb)) { continue; } certStore = d->kossl->X509_STORE_new(); if (!certStore) { errors << KSSLCertificate::Unknown; return errors; } - X509_STORE_set_verify_cb_func(certStore, X509Callback); + d->kossl->X509_STORE_set_verify_cb(certStore, X509Callback); certLookup = d->kossl->X509_STORE_add_lookup(certStore, d->kossl->X509_LOOKUP_file()); if (!certLookup) { ksslv = KSSLCertificate::Unknown; d->kossl->X509_STORE_free(certStore); continue; } if (!d->kossl->X509_LOOKUP_load_file(certLookup, _j.toLatin1().constData(), X509_FILETYPE_PEM)) { // error accessing directory and loading pems kDebug(7029) << "KSSL couldn't read CA root: " << _j << endl; ksslv = KSSLCertificate::ErrorReadingRoot; d->kossl->X509_STORE_free(certStore); continue; } // This is the checking code certStoreCTX = d->kossl->X509_STORE_CTX_new(); // this is a bad error - could mean no free memory. // This may be the wrong thing to do here if (!certStoreCTX) { kDebug(7029) << "KSSL couldn't create an X509 store context."; d->kossl->X509_STORE_free(certStore); continue; } d->kossl->X509_STORE_CTX_init(certStoreCTX, certStore, d->m_cert, NULL); if (d->_chain.isValid()) { d->kossl->X509_STORE_CTX_set_chain(certStoreCTX, (STACK_OF(X509)*)d->_chain.rawChain()); } //kDebug(7029) << "KSSL setting CRL.............."; // int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x); d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, purposeToOpenSSL(purpose)); KSSL_X509CallBack_ca = ca ? ca->d->m_cert : 0; KSSL_X509CallBack_ca_found = false; - certStoreCTX->error = X509_V_OK; + d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); rc = d->kossl->X509_verify_cert(certStoreCTX); - int errcode = certStoreCTX->error; + int errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); if (ca && !KSSL_X509CallBack_ca_found) { ksslv = KSSLCertificate::Irrelevant; } else { ksslv = processError(errcode); } // For servers, we can try NS_SSL_SERVER too if ((ksslv != KSSLCertificate::Ok) && (ksslv != KSSLCertificate::Irrelevant) && purpose == KSSLCertificate::SSLServer) { d->kossl->X509_STORE_CTX_set_purpose(certStoreCTX, X509_PURPOSE_NS_SSL_SERVER); - certStoreCTX->error = X509_V_OK; + d->kossl->X509_STORE_CTX_set_error(certStoreCTX, X509_V_OK); rc = d->kossl->X509_verify_cert(certStoreCTX); - errcode = certStoreCTX->error; + errcode = d->kossl->X509_STORE_CTX_get_error(certStoreCTX); ksslv = processError(errcode); } d->kossl->X509_STORE_CTX_free(certStoreCTX); d->kossl->X509_STORE_free(certStore); // end of checking code // //kDebug(7029) << "KSSL Validation procedure RC: " // << rc << endl; //kDebug(7029) << "KSSL Validation procedure errcode: " // << errcode << endl; //kDebug(7029) << "KSSL Validation procedure RESULTS: " // << ksslv << endl; if (ksslv != NoCARoot && ksslv != InvalidCA && ksslv != GetIssuerCertFailed && ksslv != DecodeIssuerPublicKeyFailed && ksslv != GetIssuerCertLocallyFailed ) { d->m_stateCached = true; d->m_stateCache = ksslv; } break; } if (ksslv != KSSLCertificate::Ok) { errors << ksslv; } #else errors << KSSLCertificate::NoSSL; #endif return errors; } KSSLCertificate::KSSLValidation KSSLCertificate::revalidate() { return revalidate(KSSLCertificate::SSLServer); } KSSLCertificate::KSSLValidation KSSLCertificate::revalidate(KSSLCertificate::KSSLPurpose p) { d->m_stateCached = false; return validate(p); } KSSLCertificate::KSSLValidation KSSLCertificate::processError(int ec) { KSSLCertificate::KSSLValidation rc; rc = KSSLCertificate::Unknown; #ifdef KSSL_HAVE_SSL switch (ec) { // see man 1 verify for a detailed listing of all error codes // error 0 case X509_V_OK: rc = KSSLCertificate::Ok; break; // error 2 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: rc = KSSLCertificate::GetIssuerCertFailed; break; // error 3 case X509_V_ERR_UNABLE_TO_GET_CRL: rc = KSSLCertificate::GetCRLFailed; break; // error 4 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: rc = KSSLCertificate::DecryptCertificateSignatureFailed; break; // error 5 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: rc = KSSLCertificate::DecryptCRLSignatureFailed; break; // error 6 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: rc = KSSLCertificate::DecodeIssuerPublicKeyFailed; break; // error 7 case X509_V_ERR_CERT_SIGNATURE_FAILURE: rc = KSSLCertificate::CertificateSignatureFailed; break; // error 8 case X509_V_ERR_CRL_SIGNATURE_FAILURE: rc = KSSLCertificate::CRLSignatureFailed; break; // error 9 case X509_V_ERR_CERT_NOT_YET_VALID: rc = KSSLCertificate::CertificateNotYetValid; break; // error 10 case X509_V_ERR_CERT_HAS_EXPIRED: rc = KSSLCertificate::CertificateHasExpired; kDebug(7029) << "KSSL apparently this is expired. Not after: " << getNotAfter() << endl; break; // error 11 case X509_V_ERR_CRL_NOT_YET_VALID: rc = KSSLCertificate::CRLNotYetValid; break; // error 12 case X509_V_ERR_CRL_HAS_EXPIRED: rc = KSSLCertificate::CRLHasExpired; break; // error 13 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: rc = KSSLCertificate::CertificateFieldNotBeforeErroneous; break; // error 14 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: rc = KSSLCertificate::CertificateFieldNotAfterErroneous; break; // error 15 - unused as of OpenSSL 0.9.8g case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: rc = KSSLCertificate::CRLFieldLastUpdateErroneous; break; // error 16 - unused as of OpenSSL 0.9.8g case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: rc = KSSLCertificate::CRLFieldNextUpdateErroneous; break; // error 17 case X509_V_ERR_OUT_OF_MEM: rc = KSSLCertificate::OutOfMemory; break; // error 18 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: rc = KSSLCertificate::SelfSigned; break; // error 19 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: rc = KSSLCertificate::SelfSignedInChain; break; // error 20 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: rc = KSSLCertificate::GetIssuerCertLocallyFailed; break; // error 21 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: rc = KSSLCertificate::VerifyLeafSignatureFailed; break; // error 22 - unused as of OpenSSL 0.9.8g case X509_V_ERR_CERT_CHAIN_TOO_LONG: rc = KSSLCertificate::CertificateChainTooLong; break; // error 23 - unused as of OpenSSL 0.9.8g case X509_V_ERR_CERT_REVOKED: rc = KSSLCertificate::CertificateRevoked; break; // error 24 case X509_V_ERR_INVALID_CA: rc = KSSLCertificate::InvalidCA; break; // error 25 case X509_V_ERR_PATH_LENGTH_EXCEEDED: rc = KSSLCertificate::PathLengthExceeded; break; // error 26 case X509_V_ERR_INVALID_PURPOSE: rc = KSSLCertificate::InvalidPurpose; break; // error 27 case X509_V_ERR_CERT_UNTRUSTED: rc = KSSLCertificate::CertificateUntrusted; break; // error 28 case X509_V_ERR_CERT_REJECTED: rc = KSSLCertificate::CertificateRejected; break; // error 29 - only used with -issuer_checks case X509_V_ERR_SUBJECT_ISSUER_MISMATCH: rc = KSSLCertificate::IssuerSubjectMismatched; break; // error 30 - only used with -issuer_checks case X509_V_ERR_AKID_SKID_MISMATCH: rc = KSSLCertificate::AuthAndSubjectKeyIDMismatched; break; // error 31 - only used with -issuer_checks case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH: rc = KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched; break; // error 32 case X509_V_ERR_KEYUSAGE_NO_CERTSIGN: rc = KSSLCertificate::KeyMayNotSignCertificate; break; // error 50 - unused as of OpenSSL 0.9.8g case X509_V_ERR_APPLICATION_VERIFICATION: rc = KSSLCertificate::ApplicationVerificationFailed; break; default: rc = KSSLCertificate::Unknown; break; } d->m_stateCache = rc; d->m_stateCached = true; #endif return rc; } QString KSSLCertificate::getNotBefore() const { #ifdef KSSL_HAVE_SSL - return ASN1_UTCTIME_QString(X509_get_notBefore(d->m_cert)); + return ASN1_UTCTIME_QString(d->kossl->X509_getm_notBefore(d->m_cert)); #else return QString(); #endif } QString KSSLCertificate::getNotAfter() const { #ifdef KSSL_HAVE_SSL - return ASN1_UTCTIME_QString(X509_get_notAfter(d->m_cert)); + return ASN1_UTCTIME_QString(d->kossl->X509_getm_notAfter(d->m_cert)); #else return QString(); #endif } QDateTime KSSLCertificate::getQDTNotBefore() const { #ifdef KSSL_HAVE_SSL - return ASN1_UTCTIME_QDateTime(X509_get_notBefore(d->m_cert), NULL); + return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notBefore(d->m_cert), NULL); #else return QDateTime::currentDateTime(); #endif } QDateTime KSSLCertificate::getQDTNotAfter() const { #ifdef KSSL_HAVE_SSL - return ASN1_UTCTIME_QDateTime(X509_get_notAfter(d->m_cert), NULL); + return ASN1_UTCTIME_QDateTime(d->kossl->X509_getm_notAfter(d->m_cert), NULL); #else return QDateTime::currentDateTime(); #endif } int operator==(KSSLCertificate &x, KSSLCertificate &y) { #ifndef KSSL_HAVE_SSL return 1; #else if (!KOSSL::self()->X509_cmp(x.getCert(), y.getCert())) { return 1; } return 0; #endif } KSSLCertificate *KSSLCertificate::replicate() { // The new certificate doesn't have the cached value. It's probably // better this way. We can't anticipate every reason for doing this. KSSLCertificate *newOne = new KSSLCertificate(); #ifdef KSSL_HAVE_SSL newOne->setCert(d->kossl->X509_dup(getCert())); KSSLCertChain *c = d->_chain.replicate(); newOne->setChain(c->rawChain()); delete c; #endif return newOne; } QString KSSLCertificate::toString() { return toDer().toBase64(); } QString KSSLCertificate::verifyText(KSSLValidation x) { switch (x) { // messages for errors defined in verify(1) case KSSLCertificate::Ok: return i18n("The certificate is valid."); case KSSLCertificate::GetIssuerCertFailed: return i18n("Retrieval of the issuer certificate failed. This means the CA's (Certificate Authority) certificate can not be found."); case KSSLCertificate::GetCRLFailed: return i18n("Retrieval of the CRL (Certificate Revocation List) failed. This means the CA's (Certificate Authority) CRL can not be found."); case KSSLCertificate::DecryptCertificateSignatureFailed: return i18n("The decryption of the certificate's signature failed. This means it could not even be calculated as opposed to just not matching the expected result."); case KSSLCertificate::DecryptCRLSignatureFailed: return i18n("The decryption of the CRL's (Certificate Revocation List) signature failed. This means it could not even be calculated as opposed to just not matching the expected result."); case KSSLCertificate::DecodeIssuerPublicKeyFailed: return i18n("The decoding of the public key of the issuer failed. This means that the CA's (Certificate Authority) certificate can not be used to verify the certificate you wanted to use."); case KSSLCertificate::CertificateSignatureFailed: return i18n("The certificate's signature is invalid. This means that the certificate can not be verified."); case KSSLCertificate::CRLSignatureFailed: return i18n("The CRL's (Certificate Revocation List) signature is invalid. This means that the CRL can not be verified."); case KSSLCertificate::CertificateNotYetValid: return i18n("The certificate is not valid, yet."); case KSSLCertificate::CertificateHasExpired: return i18n("The certificate is not valid, any more."); case KSSLCertificate::CRLNotYetValid: return i18n("The CRL (Certificate Revocation List) is not valid, yet."); case KSSLCertificate::CRLHasExpired: return i18n("The CRL (Certificate Revocation List) is not valid, yet."); case KSSLCertificate::CertificateFieldNotBeforeErroneous: return i18n("The time format of the certificate's 'notBefore' field is invalid."); case KSSLCertificate::CertificateFieldNotAfterErroneous: return i18n("The time format of the certificate's 'notAfter' field is invalid."); case KSSLCertificate::CRLFieldLastUpdateErroneous: return i18n("The time format of the CRL's (Certificate Revocation List) 'lastUpdate' field is invalid."); case KSSLCertificate::CRLFieldNextUpdateErroneous: return i18n("The time format of the CRL's (Certificate Revocation List) 'nextUpdate' field is invalid."); case KSSLCertificate::OutOfMemory: return i18n("The OpenSSL process ran out of memory."); case KSSLCertificate::SelfSigned: return i18n("The certificate is self-signed and not in the list of trusted certificates. If you want to accept this certificate, import it into the list of trusted certificates."); case KSSLCertificate::SelfSignedChain: // this is obsolete and kept around for backwards compatibility, only case KSSLCertificate::SelfSignedInChain: return i18n("The certificate is self-signed. While the trust chain could be built up, the root CA's (Certificate Authority) certificate can not be found."); case KSSLCertificate::GetIssuerCertLocallyFailed: return i18n("The CA's (Certificate Authority) certificate can not be found. Most likely, your trust chain is broken."); case KSSLCertificate::VerifyLeafSignatureFailed: return i18n("The certificate can not be verified as it is the only certificate in the trust chain and not self-signed. If you self-sign the certificate, make sure to import it into the list of trusted certificates."); case KSSLCertificate::CertificateChainTooLong: return i18n("The certificate chain is longer than the maximum depth specified."); case KSSLCertificate::Revoked: // this is obsolete and kept around for backwards compatibility, only case KSSLCertificate::CertificateRevoked: return i18n("The certificate has been revoked."); case KSSLCertificate::InvalidCA: return i18n("The certificate's CA (Certificate Authority) is invalid."); case KSSLCertificate::PathLengthExceeded: return i18n("The length of the trust chain exceeded one of the CA's (Certificate Authority) 'pathlength' parameters, making all subsequent signatures invalid."); case KSSLCertificate::InvalidPurpose: return i18n("The certificate has not been signed for the purpose you tried to use it for. This means the CA (Certificate Authority) does not allow this usage."); case KSSLCertificate::Untrusted: // this is obsolete and kept around for backwards compatibility, only case KSSLCertificate::CertificateUntrusted: return i18n("The root CA (Certificate Authority) is not trusted for the purpose you tried to use this certificate for."); case KSSLCertificate::Rejected: // this is obsolete and kept around for backwards compatibility, only // this is obsolete and kept around for backwards compatibility, onle case KSSLCertificate::CertificateRejected: return i18n("The root CA (Certificate Authority) has been marked to be rejected for the purpose you tried to use it for."); case KSSLCertificate::IssuerSubjectMismatched: return i18n("The certificate's CA (Certificate Authority) does not match the CA name of the certificate."); case KSSLCertificate::AuthAndSubjectKeyIDMismatched: return i18n("The CA (Certificate Authority) certificate's key ID does not match the key ID in the 'Issuer' section of the certificate you are trying to use."); case KSSLCertificate::AuthAndSubjectKeyIDAndNameMismatched: return i18n("The CA (Certificate Authority) certificate's key ID and name do not match the key ID and name in the 'Issuer' section of the certificate you are trying to use."); case KSSLCertificate::KeyMayNotSignCertificate: return i18n("The certificate's CA (Certificate Authority) is not allowed to sign certificates."); case KSSLCertificate::ApplicationVerificationFailed: return i18n("OpenSSL could not be verified."); // this is obsolete and kept around for backwards compatibility, only case KSSLCertificate::SignatureFailed: return i18n("The signature test for this certificate failed. This could mean that the signature of this certificate or any in its trust path are invalid, could not be decoded or that the CRL (Certificate Revocation List) could not be verified. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages."); case KSSLCertificate::Expired: return i18n("This certificate, any in its trust path or its CA's (Certificate Authority) CRL (Certificate Revocation List) is not valid. Any of them could not be valid yet or not valid any more. If you see this message, please let the author of the software you are using know that he or she should use the new, more specific error messages."); // continue 'useful' messages // other error messages case KSSLCertificate::ErrorReadingRoot: case KSSLCertificate::NoCARoot: return i18n("Certificate signing authority root files could not be found so the certificate is not verified."); case KSSLCertificate::NoSSL: return i18n("SSL support was not found."); case KSSLCertificate::PrivateKeyFailed: return i18n("Private key test failed."); case KSSLCertificate::InvalidHost: return i18n("The certificate has not been issued for this host."); case KSSLCertificate::Irrelevant: return i18n("This certificate is not relevant."); default: break; } return i18n("The certificate is invalid."); } QByteArray KSSLCertificate::toDer() { QByteArray qba; #ifdef KSSL_HAVE_SSL int certlen = d->kossl->i2d_X509(getCert(), NULL); if (certlen >= 0) { // These should technically be unsigned char * but it doesn't matter // for our purposes char *cert = new char[certlen]; unsigned char *p = (unsigned char *)cert; // FIXME: return code! d->kossl->i2d_X509(getCert(), &p); // encode it into a QString qba = QByteArray(cert, certlen); delete[] cert; } #endif return qba; } QByteArray KSSLCertificate::toPem() { QByteArray qba; QString thecert = toString(); const char *header = "-----BEGIN CERTIFICATE-----\n"; const char *footer = "-----END CERTIFICATE-----\n"; // We just do base64 on the ASN1 // 64 character lines (unpadded) unsigned int xx = thecert.length() - 1; for (unsigned int i = 0; i < xx/64; i++) { thecert.insert(64*(i+1)+i, '\n'); } thecert.prepend(header); if (thecert[thecert.length()-1] != '\n') { thecert += '\n'; } thecert.append(footer); qba = thecert.toLocal8Bit(); return qba; } #define NETSCAPE_CERT_HDR "certificate" #ifdef KSSL_HAVE_SSL #if OPENSSL_VERSION_NUMBER < 0x00909000L typedef struct NETSCAPE_X509_st { ASN1_OCTET_STRING *header; X509 *cert; } NETSCAPE_X509; #endif #endif // what a piece of crap this is QByteArray KSSLCertificate::toNetscape() { QByteArray qba; -#ifdef KSSL_HAVE_SSL + // no equivalent in OpenSSL 1.1.0 (?), so behave as if we had no OpenSSL at all +#if KSSL_HAVE_SSL && OPENSSL_VERSION_NUMBER < 0x10100000L NETSCAPE_X509 nx; ASN1_OCTET_STRING hdr; KTemporaryFile ktf; ktf.open(); FILE *ktf_fs = fopen(ktf.fileName().toLatin1(), "r+"); hdr.data = (unsigned char *)NETSCAPE_CERT_HDR; hdr.length = strlen(NETSCAPE_CERT_HDR); nx.header = &hdr; nx.cert = getCert(); d->kossl->ASN1_item_i2d_fp(ktf_fs,(unsigned char *)&nx); fclose(ktf_fs); QFile qf(ktf.fileName()); if (qf.open(QIODevice::ReadOnly)) { qba = qf.readAll(); } #endif return qba; } QString KSSLCertificate::toText() { QString text; #ifdef KSSL_HAVE_SSL KTemporaryFile ktf; ktf.open(); FILE *ktf_fs = fopen(ktf.fileName().toLatin1(), "r+"); d->kossl->X509_print(ktf_fs, getCert()); fclose(ktf_fs); QFile qf(ktf.fileName()); if (!qf.open(QIODevice::ReadOnly) ) return text; char *buf = new char[qf.size()+1]; qf.read(buf, qf.size()); buf[qf.size()] = 0; text = buf; delete[] buf; qf.close(); #endif return text; } bool KSSLCertificate::setCert(const QString& cert) { #ifdef KSSL_HAVE_SSL QByteArray qba, qbb = cert.toLocal8Bit(); qba = QByteArray::fromBase64(qbb); unsigned char *qbap = reinterpret_cast(qba.data()); X509 *x5c = KOSSL::self()->d2i_X509(NULL, &qbap, qba.size()); if (x5c) { setCert(x5c); return true; } #endif return false; } KSSLX509V3& KSSLCertificate::x509V3Extensions() { return d->_extensions; } bool KSSLCertificate::isSigner() { return d->_extensions.certTypeCA(); } QStringList KSSLCertificate::subjAltNames() const { QStringList rc; #ifdef KSSL_HAVE_SSL STACK_OF(GENERAL_NAME) *names; names = (STACK_OF(GENERAL_NAME)*)d->kossl->X509_get_ext_d2i(d->m_cert, NID_subject_alt_name, 0, 0); if (!names) { return rc; } - int cnt = d->kossl->sk_GENERAL_NAME_num(names); + int cnt = d->kossl->OPENSSL_sk_num((STACK *)names); for (int i = 0; i < cnt; i++) { - const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->sk_value(names, i); + const GENERAL_NAME *val = (const GENERAL_NAME *)d->kossl->OPENSSL_sk_value(names, i); if (val->type != GEN_DNS) { continue; } QString s = (const char *)d->kossl->ASN1_STRING_data(val->d.ia5); if (!s.isEmpty() && /* skip subjectAltNames with embedded NULs */ s.length() == d->kossl->ASN1_STRING_length(val->d.ia5)) { rc += s; } } - d->kossl->sk_free(names); + d->kossl->OPENSSL_sk_free(names); #endif return rc; } QDataStream& operator<<(QDataStream& s, const KSSLCertificate& r) { QStringList qsl; QList cl = const_cast(r).chain().getChain(); foreach(KSSLCertificate *c, cl) { qsl << c->toString(); } qDeleteAll(cl); s << const_cast(r).toString() << qsl; return s; } QDataStream& operator>>(QDataStream& s, KSSLCertificate& r) { QStringList qsl; QString cert; s >> cert >> qsl; if (r.setCert(cert) && !qsl.isEmpty()) { r.chain().setCertChain(qsl); } return s; }