From: Manuel Nickschas Date: Thu, 8 Oct 2015 21:31:59 +0000 (+0200) Subject: Merge pull request #132 from mamarley/md5corecertfix X-Git-Tag: travis-deploy-test~560 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=b106c6bd31960a4f70ceb696e9d9dc06a621b9f7;hp=9bb9b31f5175541c9230c20edc37fe0fd9491aa4 Merge pull request #132 from mamarley/md5corecertfix Use SHA2-512 to store the core certificate digest in the client --- diff --git a/src/client/clientauthhandler.cpp b/src/client/clientauthhandler.cpp index 7ed231c2..eeca2cff 100644 --- a/src/client/clientauthhandler.cpp +++ b/src/client/clientauthhandler.cpp @@ -34,6 +34,10 @@ #include "clientsettings.h" #include "peerfactory.h" +#if QT_VERSION < 0x050000 +# include "../../3rdparty/sha512/sha512.h" +#endif + using namespace Protocol; ClientAuthHandler::ClientAuthHandler(CoreAccount account, QObject *parent) @@ -423,6 +427,7 @@ void ClientAuthHandler::checkAndEnableSsl(bool coreSupportsSsl) } s.setAccountValue("ShowNoCoreSslWarning", false); s.setAccountValue("SslCert", QString()); + s.setAccountValue("SslCertDigestVersion", QVariant(QVariant::Int)); } if (_legacy) onConnectionReady(); @@ -444,6 +449,7 @@ void ClientAuthHandler::onSslSocketEncrypted() // That way, a warning will appear in case it becomes invalid at some point CoreAccountSettings s; s.setAccountValue("SSLCert", QString()); + s.setAccountValue("SslCertDigestVersion", QVariant(QVariant::Int)); } emit encrypted(true); @@ -462,8 +468,27 @@ void ClientAuthHandler::onSslErrors() CoreAccountSettings s; QByteArray knownDigest = s.accountValue("SslCert").toByteArray(); + ClientAuthHandler::DigestVersion knownDigestVersion = static_cast(s.accountValue("SslCertDigestVersion").toInt()); + + QByteArray calculatedDigest; + switch (knownDigestVersion) { + case ClientAuthHandler::DigestVersion::Md5: + calculatedDigest = socket->peerCertificate().digest(QCryptographicHash::Md5); + break; - if (knownDigest != socket->peerCertificate().digest()) { + case ClientAuthHandler::DigestVersion::Sha2_512: +#if QT_VERSION >= 0x050000 + calculatedDigest = socket->peerCertificate().digest(QCryptographicHash::Sha512); +#else + calculatedDigest = sha2_512(socket->peerCertificate().toDer()); +#endif + break; + + default: + qWarning() << "Certificate digest version" << QString(knownDigestVersion) << "is not supported"; + } + + if (knownDigest != calculatedDigest) { bool accepted = false; bool permanently = false; emit handleSslErrors(socket, &accepted, &permanently); @@ -473,13 +498,42 @@ void ClientAuthHandler::onSslErrors() return; } - if (permanently) - s.setAccountValue("SslCert", socket->peerCertificate().digest()); - else + if (permanently) { +#if QT_VERSION >= 0x050000 + s.setAccountValue("SslCert", socket->peerCertificate().digest(QCryptographicHash::Sha512)); +#else + s.setAccountValue("SslCert", sha2_512(socket->peerCertificate().toDer())); +#endif + s.setAccountValue("SslCertDigestVersion", ClientAuthHandler::DigestVersion::Latest); + } + else { s.setAccountValue("SslCert", QString()); + s.setAccountValue("SslCertDigestVersion", QVariant(QVariant::Int)); + } + } + else if (knownDigestVersion != ClientAuthHandler::DigestVersion::Latest) { +#if QT_VERSION >= 0x050000 + s.setAccountValue("SslCert", socket->peerCertificate().digest(QCryptographicHash::Sha512)); +#else + s.setAccountValue("SslCert", sha2_512(socket->peerCertificate().toDer())); +#endif + s.setAccountValue("SslCertDigestVersion", ClientAuthHandler::DigestVersion::Latest); } socket->ignoreSslErrors(); } +#if QT_VERSION < 0x050000 +QByteArray ClientAuthHandler::sha2_512(const QByteArray &input) { + unsigned char output[64]; + sha512((unsigned char*) input.constData(), input.size(), output, false); + // QByteArray::fromRawData() cannot be used here because that constructor + // does not copy "output" and the data is clobbered when the variable goes + // out of scope. + QByteArray result; + result.append((char*) output, 64); + return result; +} +#endif + #endif /* HAVE_SSL */ diff --git a/src/client/clientauthhandler.h b/src/client/clientauthhandler.h index 7d6c9357..00c2986e 100644 --- a/src/client/clientauthhandler.h +++ b/src/client/clientauthhandler.h @@ -36,6 +36,12 @@ class ClientAuthHandler : public AuthHandler public: ClientAuthHandler(CoreAccount account, QObject *parent = 0); + enum DigestVersion { + Md5, + Sha2_512, + Latest=Sha2_512 + }; + public slots: void connectToCore(); @@ -83,6 +89,10 @@ private: void checkAndEnableSsl(bool coreSupportsSsl); void startRegistration(); +#if QT_VERSION < 0x050000 + QByteArray sha2_512(const QByteArray &input); +#endif + private slots: void onSocketConnected(); void onSocketStateChanged(QAbstractSocket::SocketState state);