Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: pu
Hello, [ Disclaimer: I've already asked security team about this upload and they told me to do it via s-p-u ] This upload would fix 2 security issues. Change-by-change details are below while full diff is attached. * Blacklist a set of fraudulent ssl certificates; to perform this blacklisting we need these patches: - blacklist_fraudulent_comodo_certificates.diff - ssl_certificate_large_sn.diff http://git.debian.org/?p=pkg-kde/qt/qt4-x11.git;a=commit;h=f8f083cf53ff * Fix CVE-2010-3170 (browser wildcard cerficate validation weakness) with cve_2010_3170_ssl_certificates_wildcard.diff. This problem affects the Arora web browser. http://git.debian.org/?p=pkg-kde/qt/qt4-x11.git;a=commit;h=ca7ca43a374c -- System Information: Debian Release: wheezy/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing'), (110, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 2.6.38-2-amd64 (SMP w/4 CPU cores) Locale: LANG=lt_LT.UTF-8, LC_CTYPE=lt_LT.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash
diff --git a/debian/changelog b/debian/changelog index bbd8811..363ab2e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +qt4-x11 (4:4.6.3-4+squeeze1) UNRELEASED; urgency=low + + * Blacklist a set of fraudulent ssl certificates; to perform this + blacklisting we need these patches: + - blacklist_fraudulent_comodo_certificates.diff + - ssl_certificate_large_sn.diff + * Fix CVE-2010-3170 (browser wildcard cerficate validation weakness) with + cve_2010_3170_ssl_certificates_wildcard.diff. This problem affects the Arora + web browser. + + -- José Manuel SantamarÃa Lema <panfa...@gmail.com> Fri, 15 Apr 2011 19:13:13 +0200 + qt4-x11 (4:4.6.3-4) unstable; urgency=high [ Pino Toscano ] diff --git a/debian/patches/blacklist_fraudulent_comodo_certificates.diff b/debian/patches/blacklist_fraudulent_comodo_certificates.diff new file mode 100644 index 0000000..0142822 --- /dev/null +++ b/debian/patches/blacklist_fraudulent_comodo_certificates.diff @@ -0,0 +1,85 @@ +Origin: http://labs.qt.nokia.com/2011/03/29/security-advisory-fraudulent-certificates/ +Description: This patch blacklists a set of fraudulent ssl certificates. +--- a/src/network/ssl/qsslcertificate.cpp ++++ b/src/network/ssl/qsslcertificate.cpp +@@ -219,17 +219,19 @@ + Returns true if this certificate is valid; otherwise returns + false. + +- Note: Currently, this function only checks that the current ++ Note: Currently, this function checks that the current + data-time is within the date-time range during which the +- certificate is considered valid. No other checks are +- currently performed. ++ certificate is considered valid, and checks that the ++ certificate is not in a blacklist of fraudulent certificates. + + \sa isNull() + */ + bool QSslCertificate::isValid() const + { + const QDateTime currentTime = QDateTime::currentDateTime(); +- return currentTime >= d->notValidBefore && currentTime <= d->notValidAfter; ++ return currentTime >= d->notValidBefore && ++ currentTime <= d->notValidAfter && ++ ! QSslCertificatePrivate::isBlacklisted(*this); + } + + /*! +@@ -778,6 +780,30 @@ + return certificates; + } + ++// 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", ++ 0 ++}; ++ ++bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) ++{ ++ for (int a = 0; certificate_blacklist[a] != 0; a++) { ++ if (certificate.serialNumber() == certificate_blacklist[a]) ++ return true; ++ } ++ return false; ++} ++ + #ifndef QT_NO_DEBUG_STREAM + QDebug operator<<(QDebug debug, const QSslCertificate &certificate) + { +--- a/src/network/ssl/qsslcertificate_p.h ++++ b/src/network/ssl/qsslcertificate_p.h +@@ -96,6 +96,7 @@ + static QSslCertificate QSslCertificate_from_X509(X509 *x509); + static QList<QSslCertificate> certificatesFromPem(const QByteArray &pem, int count = -1); + static QList<QSslCertificate> certificatesFromDer(const QByteArray &der, int count = -1); ++ static bool isBlacklisted(const QSslCertificate &certificate); + + friend class QSslSocketBackendPrivate; + +--- a/src/network/ssl/qsslsocket_openssl.cpp ++++ b/src/network/ssl/qsslsocket_openssl.cpp +@@ -810,6 +810,13 @@ + X509 *x509 = q_SSL_get_peer_certificate(ssl); + configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509); + q_X509_free(x509); ++ if (QSslCertificatePrivate::isBlacklisted(configuration.peerCertificate)) { ++ q->setErrorString(QSslSocket::tr("The peer certificate is blacklisted")); ++ q->setSocketError(QAbstractSocket::SslHandshakeFailedError); ++ emit q->error(QAbstractSocket::SslHandshakeFailedError); ++ plainSocket->disconnectFromHost(); ++ return false; ++ } + + // Start translating errors. + QList<QSslError> errors; diff --git a/debian/patches/cve_2010_3170_ssl_certificates_wildcard.diff b/debian/patches/cve_2010_3170_ssl_certificates_wildcard.diff new file mode 100644 index 0000000..e738d4b --- /dev/null +++ b/debian/patches/cve_2010_3170_ssl_certificates_wildcard.diff @@ -0,0 +1,81 @@ +Origin: http://qt.gitorious.org/qt/qt/commit/5f601856 + http://qt.gitorious.org/qt/qt/commit/87c62128 +Description: Fix handling of SSL certificates with wildcards +--- a/src/network/ssl/qsslsocket_openssl.cpp ++++ b/src/network/ssl/qsslsocket_openssl.cpp +@@ -834,17 +834,16 @@ + QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName); + QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName); + +- QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard); +- if (!regexp.exactMatch(peerName)) { ++ if (!isMatchingHostname(commonName.lower(), peerName.lower())) { + bool matched = false; + foreach (const QString &altName, configuration.peerCertificate + .alternateSubjectNames().values(QSsl::DnsEntry)) { +- regexp.setPattern(altName); +- if (regexp.exactMatch(peerName)) { ++ if (isMatchingHostname(altName.lower(), peerName.lower())) { + matched = true; + break; + } + } ++ + if (!matched) { + // No matches in common names or alternate names. + QSslError error(QSslError::HostNameMismatch, configuration.peerCertificate); +@@ -969,4 +968,44 @@ + return certificates; + } + ++bool QSslSocketBackendPrivate::isMatchingHostname(const QString &cn, const QString &hostname) ++{ ++ int wildcard = cn.indexOf(QLatin1Char('*')); ++ ++ // Check this is a wildcard cert, if not then just compare the strings ++ if (wildcard < 0) ++ return cn == hostname; ++ ++ int firstCnDot = cn.indexOf(QLatin1Char('.')); ++ int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1); ++ ++ // Check at least 3 components ++ if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length())) ++ return false; ++ ++ // Check * is last character of 1st component (ie. there's a following .) ++ if (wildcard+1 != firstCnDot) ++ return false; ++ ++ // Check only one star ++ if (cn.lastIndexOf(QLatin1Char('*')) != wildcard) ++ return false; ++ ++ // Check characters preceding * (if any) match ++ if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard))) ++ return false; ++ ++ // Check characters following first . match ++ if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot)) ++ return false; ++ ++ // Check if the hostname is an IP address, if so then wildcards are not allowed ++ QHostAddress addr(hostname); ++ if (!addr.isNull()) ++ return false; ++ ++ // Ok, I guess this was a wildcard CN and the hostname matches. ++ return true; ++} ++ + QT_END_NAMESPACE +--- a/src/network/ssl/qsslsocket_openssl_p.h ++++ b/src/network/ssl/qsslsocket_openssl_p.h +@@ -115,6 +115,7 @@ + + static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher); + static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); ++ Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname); + }; + + QT_END_NAMESPACE diff --git a/debian/patches/series b/debian/patches/series index 2c90b91..b355cb1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -3,6 +3,9 @@ 0005_fix_detection_of_headers_files.diff 0006_webkit_propriotary_flash_init_gtk_first.diff 0007_qsslsocket_improve_error_handling_CVE-2010-2621.patch +ssl_certificate_large_sn.diff +blacklist_fraudulent_comodo_certificates.diff +cve_2010_3170_ssl_certificates_wildcard.diff # qt-copy patches 0180-window-role.diff diff --git a/debian/patches/ssl_certificate_large_sn.diff b/debian/patches/ssl_certificate_large_sn.diff new file mode 100644 index 0000000..2d406ac --- /dev/null +++ b/debian/patches/ssl_certificate_large_sn.diff @@ -0,0 +1,54 @@ +From 0f16c7ce8dcd6f4905d14875088c55148e41366a Mon Sep 17 00:00:00 2001 +From: Peter Hartmann <peter.hartm...@nokia.com> +Date: Tue, 1 Jun 2010 16:50:55 +0200 +Subject: [PATCH] QSslCertificate: support large serial numbers + +We were calling an OpenSSL function that returned a long for the serial +number; sometimes serial numbers are too big to fit into a long (up to +20 octets). In that case, do not convert the serial number to decimal, +but just output the hexadecimal value. + +Reviewed-by: Zeno Albisser +Task-number: QTBUG-9973 +--- + src/network/ssl/qsslcertificate.cpp | 23 ++++++++++++++++--- + .../more-certificates/cert-large-serial-number.pem | 14 ++++++++++++ + tests/auto/qsslcertificate/tst_qsslcertificate.cpp | 13 +++++++++++ + 3 files changed, 46 insertions(+), 4 deletions(-) + create mode 100644 tests/auto/qsslcertificate/more-certificates/cert-large-serial-number.pem + +--- a/src/network/ssl/qsslcertificate.cpp ++++ b/src/network/ssl/qsslcertificate.cpp +@@ -259,13 +259,28 @@ + + /*! + Returns the certificate's serial number string in decimal format. ++ In case the serial number cannot be converted to decimal format ++ (i.e. if it is bigger than 4294967295, which means it does not fit into 4 bytes), ++ its hexadecimal version is returned. + */ + QByteArray QSslCertificate::serialNumber() const + { +- if (d->serialNumberString.isEmpty() && d->x509) +- d->serialNumberString = +- QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber))); +- ++ if (d->serialNumberString.isEmpty() && d->x509) { ++ ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber; ++ // if we cannot convert to a long, just output the hexadecimal number ++ if (serialNumber->length > 4) { ++ QByteArray hexString; ++ hexString.reserve(serialNumber->length * 3); ++ for (int a = 0; a < serialNumber->length; ++a) { ++ hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0'); ++ hexString += ':'; ++ } ++ hexString.chop(1); ++ d->serialNumberString = hexString; ++ } else { ++ d->serialNumberString = QByteArray::number(qlonglong(q_ASN1_INTEGER_get(serialNumber))); ++ } ++ } + return d->serialNumberString; + } +