Bug#626845: pu: package qt4-x11/4:4.6.3-4+squeeze1
Package: release.debian.org
Severity: normal
User: release.debian.org@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 <panfaust@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.hartmann@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;
+ }
+
Reply to: