summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/ssl/qssl.h1
-rw-r--r--src/network/ssl/qsslcertificate.cpp23
-rw-r--r--src/network/ssl/qsslkey.cpp46
-rw-r--r--src/network/ssl/qsslkey.h1
-rw-r--r--src/network/ssl/qsslkey_p.h2
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp42
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h4
7 files changed, 83 insertions, 36 deletions
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 7b76b64b4c..c8af346800 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -63,6 +63,7 @@ namespace QSsl {
};
enum KeyAlgorithm {
+ Opaque,
Rsa,
Dsa
};
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index bbc60f674c..fa97ccb78c 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -892,23 +892,24 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
// These certificates are known to be fraudulent and were created during the comodo
// compromise. See http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
static const char *certificate_blacklist[] = {
- "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e",
- "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06",
- "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3",
- "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29",
- "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71",
- "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47",
- "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43",
- "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0",
- "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0",
- "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56",
+ "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", "mail.google.com", // Comodo
+ "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", "www.google.com", // Comodo
+ "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", "login.yahoo.com", // Comodo
+ "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", "login.yahoo.com", // Comodo
+ "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", "login.yahoo.com", // Comodo
+ "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", "login.skype.com", // Comodo
+ "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", "addons.mozilla.org", // Comodo
+ "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", "login.live.com", // Comodo
+ "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", "global trustee", // Comodo
+ "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", // DigiNotar
0
};
bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
{
for (int a = 0; certificate_blacklist[a] != 0; a++) {
- if (certificate.serialNumber() == certificate_blacklist[a])
+ if (certificate.serialNumber() == certificate_blacklist[a++] &&
+ certificate.subjectInfo(QSslCertificate::CommonName).contains(QString::fromUtf8(certificate_blacklist[a])))
return true;
}
return false;
diff --git a/src/network/ssl/qsslkey.cpp b/src/network/ssl/qsslkey.cpp
index 29cfd0a77d..580b71bca9 100644
--- a/src/network/ssl/qsslkey.cpp
+++ b/src/network/ssl/qsslkey.cpp
@@ -89,6 +89,11 @@ void QSslKeyPrivate::clear(bool deep)
q_DSA_free(dsa);
dsa = 0;
}
+ if (opaque) {
+ if (deep)
+ q_EVP_PKEY_free(opaque);
+ opaque = 0;
+ }
}
/*!
@@ -265,6 +270,23 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding
}
/*!
+ Constructs a QSslKey from a valid native key \a handle.
+ \a type specifies whether the key is public or private.
+
+ QSslKey will take ownership for this key and you must not
+ free the key using the native library. The algorithm used
+ when creating a key from a handle will always be QSsl::Opaque.
+*/
+QSslKey::QSslKey(Qt::HANDLE handle, QSsl::KeyType type)
+ : d(new QSslKeyPrivate)
+{
+ d->opaque = reinterpret_cast<EVP_PKEY *>(handle);
+ d->algorithm = QSsl::Opaque;
+ d->type = type;
+ d->isNull = !d->opaque;
+}
+
+/*!
Constructs an identical copy of \a other.
*/
QSslKey::QSslKey(const QSslKey &other) : d(other.d)
@@ -315,8 +337,9 @@ void QSslKey::clear()
*/
int QSslKey::length() const
{
- if (d->isNull)
+ if (d->isNull || d->algorithm == QSsl::Opaque)
return -1;
+
return (d->algorithm == QSsl::Rsa)
? q_BN_num_bits(d->rsa->n) : q_BN_num_bits(d->dsa->p);
}
@@ -345,8 +368,9 @@ QSsl::KeyAlgorithm QSslKey::algorithm() const
// ### autotest failure for non-empty passPhrase and private key
QByteArray QSslKey::toDer(const QByteArray &passPhrase) const
{
- if (d->isNull)
+ if (d->isNull || d->algorithm == QSsl::Opaque)
return QByteArray();
+
return d->derFromPem(toPem(passPhrase));
}
@@ -357,7 +381,7 @@ QByteArray QSslKey::toDer(const QByteArray &passPhrase) const
*/
QByteArray QSslKey::toPem(const QByteArray &passPhrase) const
{
- if (!QSslSocket::supportsSsl() || d->isNull)
+ if (!QSslSocket::supportsSsl() || d->isNull || d->algorithm == QSsl::Opaque)
return QByteArray();
BIO *bio = q_BIO_new(q_BIO_s_mem());
@@ -417,7 +441,16 @@ QByteArray QSslKey::toPem(const QByteArray &passPhrase) const
*/
Qt::HANDLE QSslKey::handle() const
{
- return (d->algorithm == QSsl::Rsa) ? Qt::HANDLE(d->rsa) : Qt::HANDLE(d->dsa);
+ switch (d->algorithm) {
+ case QSsl::Opaque:
+ return Qt::HANDLE(d->opaque);
+ case QSsl::Rsa:
+ return Qt::HANDLE(d->rsa);
+ case QSsl::Dsa:
+ return Qt::HANDLE(d->dsa);
+ default:
+ return Qt::HANDLE(NULL);
+ }
}
/*!
@@ -435,6 +468,8 @@ bool QSslKey::operator==(const QSslKey &other) const
return false;
if (length() != other.length())
return false;
+ if (algorithm() == QSsl::Opaque)
+ return handle() == other.handle();
return toDer() == other.toDer();
}
@@ -450,7 +485,8 @@ QDebug operator<<(QDebug debug, const QSslKey &key)
{
debug << "QSslKey("
<< (key.type() == QSsl::PublicKey ? "PublicKey" : "PrivateKey")
- << ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA")
+ << ", " << (key.algorithm() == QSsl::Opaque ? "OPAQUE" :
+ (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA"))
<< ", " << key.length()
<< ')';
return debug;
diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h
index 5ee1b4ad2f..7064d22eb4 100644
--- a/src/network/ssl/qsslkey.h
+++ b/src/network/ssl/qsslkey.h
@@ -73,6 +73,7 @@ public:
QSsl::EncodingFormat format = QSsl::Pem,
QSsl::KeyType type = QSsl::PrivateKey,
const QByteArray &passPhrase = QByteArray());
+ explicit QSslKey(Qt::HANDLE handle, QSsl::KeyType type = QSsl::PrivateKey);
QSslKey(const QSslKey &other);
~QSslKey();
QSslKey &operator=(const QSslKey &other);
diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h
index f4a77b3c3f..14075ecad0 100644
--- a/src/network/ssl/qsslkey_p.h
+++ b/src/network/ssl/qsslkey_p.h
@@ -67,6 +67,7 @@ public:
inline QSslKeyPrivate()
: rsa(0)
, dsa(0)
+ , opaque(0)
{
clear();
}
@@ -88,6 +89,7 @@ public:
QSsl::KeyAlgorithm algorithm;
RSA *rsa;
DSA *dsa;
+ EVP_PKEY *opaque;
QAtomicInt ref;
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 300a5c84d5..0ff17910f3 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -322,7 +322,7 @@ init_context:
if (! caCertificate.isValid()) {
expiredCerts.append(caCertificate);
} else {
- q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
+ q_X509_STORE_add_cert(ctx->cert_store, reinterpret_cast<X509 *>(caCertificate.handle()));
}
}
@@ -335,7 +335,7 @@ init_context:
// now add the expired certs
if (addExpiredCerts) {
foreach (const QSslCertificate &caCertificate, expiredCerts) {
- q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
+ q_X509_STORE_add_cert(ctx->cert_store, reinterpret_cast<X509 *>(caCertificate.handle()));
}
}
@@ -358,26 +358,33 @@ init_context:
}
// Load certificate
- if (!q_SSL_CTX_use_certificate(ctx, (X509 *)configuration.localCertificate.handle())) {
+ if (!q_SSL_CTX_use_certificate(ctx, reinterpret_cast<X509 *>(configuration.localCertificate.handle()))) {
q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(getErrorsFromOpenSsl()));
emit q->error(QAbstractSocket::UnknownSocketError);
return false;
}
- // Load private key
- pkey = q_EVP_PKEY_new();
- // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
- // this lead to a memory leak. Now we use the *_set1_* functions which do not
- // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
- if (configuration.privateKey.algorithm() == QSsl::Rsa)
- q_EVP_PKEY_set1_RSA(pkey, (RSA *)configuration.privateKey.handle());
- else
- q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle());
+ if (configuration.privateKey.algorithm() == QSsl::Opaque) {
+ pkey = reinterpret_cast<EVP_PKEY *>(configuration.privateKey.handle());
+ } else {
+ // Load private key
+ pkey = q_EVP_PKEY_new();
+ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
+ // this lead to a memory leak. Now we use the *_set1_* functions which do not
+ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
+ if (configuration.privateKey.algorithm() == QSsl::Rsa)
+ q_EVP_PKEY_set1_RSA(pkey, reinterpret_cast<RSA *>(configuration.privateKey.handle()));
+ else
+ q_EVP_PKEY_set1_DSA(pkey, reinterpret_cast<DSA *>(configuration.privateKey.handle()));
+ }
+
if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) {
q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl()));
emit q->error(QAbstractSocket::UnknownSocketError);
return false;
}
+ if (configuration.privateKey.algorithm() == QSsl::Opaque)
+ pkey = 0; // Don't free the private key, it belongs to QSslKey
// Check if the certificate matches the private key.
if (!q_SSL_CTX_check_private_key(ctx)) {
@@ -1383,7 +1390,6 @@ void QSslSocketBackendPrivate::disconnected()
q_EVP_PKEY_free(pkey);
pkey = 0;
}
-
}
QSslCipher QSslSocketBackendPrivate::sessionCipher() const
@@ -1508,7 +1514,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi
if (!caCertificate.isValid()) {
expiredCerts.append(caCertificate);
} else {
- q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());
+ q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle()));
}
}
@@ -1521,7 +1527,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi
// now add the expired certs
if (addExpiredCerts) {
foreach (const QSslCertificate &caCertificate, expiredCerts) {
- q_X509_STORE_add_cert(certStore, (X509 *)caCertificate.handle());
+ q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle()));
}
}
@@ -1548,9 +1554,9 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi
continue;
}
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_push( (_STACK *)intermediates, (X509 *)cert.handle());
+ q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#else
- q_sk_push( (STACK *)intermediates, (X509 *)cert.handle());
+ q_sk_push( (STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
#endif
}
}
@@ -1562,7 +1568,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(QList<QSslCertificate> certifi
return errors;
}
- if (!q_X509_STORE_CTX_init(storeContext, certStore, (X509 *)certificateChain[0].handle(), intermediates)) {
+ if (!q_X509_STORE_CTX_init(storeContext, certStore, reinterpret_cast<X509 *>(certificateChain[0].handle()), intermediates)) {
q_X509_STORE_CTX_free(storeContext);
q_X509_STORE_free(certStore);
errors << QSslError(QSslError::UnspecifiedError);
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index a1db6d9320..d1705b3680 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -228,13 +228,13 @@ char *q_ERR_error_string(unsigned long a, char *b);
unsigned long q_ERR_get_error();
const EVP_CIPHER *q_EVP_des_ede3_cbc();
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
-int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
+Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
void q_EVP_PKEY_free(EVP_PKEY *a);
RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a);
DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a);
int q_EVP_PKEY_type(int a);
-EVP_PKEY *q_EVP_PKEY_new();
+Q_AUTOTEST_EXPORT EVP_PKEY *q_EVP_PKEY_new();
int q_i2d_X509(X509 *a, unsigned char **b);
const char *q_OBJ_nid2sn(int a);
const char *q_OBJ_nid2ln(int a);