summaryrefslogtreecommitdiffstats
path: root/meta/recipes-qt/qt4/files/blacklist-fraudulent-comodo-certificates-patch.diff
blob: 00faf75932271fecada999abf8a2f74e1b1de467 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
Security advisory: Fraudulent certificates

Background:

Recently a group of people managed to get fraudulent SSL certificates signed
by a Certificate Authority (CA).

These certificates potentially enable their owners to pretend to be other
entities on the Web; the attackers can present valid certificates for e.g.
mail.google.com, login.yahoo.com and login.live.com, among others.

The patch below solves this problem by blacklisting those fake certificates
and aborting an SSL handshake with entities that present these certificates.
The patch applies to all 4.6 and 4.7 versions, and should be applied to all Qt
4.6.x and 4.7.x versions; upcoming Qt releases will contain a fix for this
problem.

More technical background:

In order to trick a user into establishing an SSL connection to a site using
one of those fake certificates, in addition to controlling the certificate, an
attacker would need to either control the DNS server used by the victim, or
have control over a proxy that the victim uses. That way, the attacker could
trick the victim to connect to the attacker?s site and then present the user
with a valid certificate.

One obvious question now is: Should those certificates not just be revoked,
which would solve the problem?

First, they have been revoked by the affected Certificate Authority (see above
link).

However, the problem in this case, and probably part of the reason why most
browser vendors release new versions blacklisting those certificates, is that
by default browsers do not treat invalid responses from an OCSP server (a
server used for checking the revocation status of a certificate) as fatal, and
will allow the SSL connection to proceed anyway. Qt itself does not support
OCSP yet, which makes blacklisting the certificates the only valid option (now
would be a good moment to vote on the task for implementing OCSP in Qt); since
Qt is relying on the system root certificates since version 4.7, it cannot
control the root certificates that Qt trusts automatically anymore.

http://www.comodo.com/Comodo-Fraud-Incident-2011-03-23.html
http://qt.nokia.com/files/qt-patches/blacklist-fraudulent-comodo-certificates-patch.diff/view

diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 618ac79..a5cdf01 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -219,17 +219,19 @@ bool QSslCertificate::isNull() const
     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);
 }
 
 /*!
@@ -798,6 +800,30 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
     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)
 {
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index cdceb0f..1ce33d3 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -96,6 +96,7 @@ public:
     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;
 
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 0866534..2427193 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1193,6 +1193,13 @@ bool QSslSocketBackendPrivate::startHandshake()
     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;