[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    branches/KDE/4.2/kdelibs/kio/kio
From:       Roland Harnau <truthandprogress () googlemail ! com>
Date:       2009-02-26 13:44:48
Message-ID: 1235655888.959334.5577.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 932373 by rharnau:

Make Konqueror show correct information about whether a SSL certificate is
trusted in its SSL Information dialog. For this the matching of host name and
certificate has do be done before the meta data is sent.

BUG: 182805

 M  +80 -79    tcpslavebase.cpp  


--- branches/KDE/4.2/kdelibs/kio/kio/tcpslavebase.cpp #932372:932373
@@ -103,6 +103,8 @@
 class TCPSlaveBase::TcpSlaveBasePrivate
 {
 public:
+    TcpSlaveBasePrivate(TCPSlaveBase* qq) : q(qq) {}
+
     QList<KSslError> nonIgnorableErrors(const QList<KSslError> &/*e*/) const
     {
         QList<KSslError> ret;
@@ -110,6 +112,55 @@
         return ret;
     }
 
+    void prepareSslRelatedMetaData()
+    {
+        KSslCipher cipher = socket.sessionCipher();
+        q->setMetaData("ssl_protocol_version", socket.negotiatedSslVersionName());
+        QString sslCipher = cipher.encryptionMethod() + '\n';
+        sslCipher += cipher.authenticationMethod() + '\n';
+        sslCipher += cipher.keyExchangeMethod() + '\n';
+        sslCipher += cipher.digestMethod();
+        q->setMetaData("ssl_cipher", sslCipher);
+        q->setMetaData("ssl_cipher_used_bits", QString::number(cipher.usedBits()));
+        q->setMetaData("ssl_cipher_bits", QString::number(cipher.supportedBits()));
+        q->setMetaData("ssl_peer_ip", ip);
+
+        // try to fill in the blanks, i.e. missing certificates, and just assume \
that +        // those belong to the peer (==website or similar) certificate.
+        for (int i = 0; i < sslErrors.count(); i++) {
+            if (sslErrors[i].certificate().isNull()) {
+                sslErrors[i] = KSslError(sslErrors[i].error(),
+                                        socket.peerCertificateChain()[0]);
+            }
+        }
+
+        QString errorStr;
+        // encode the two-dimensional numeric error list using '\n' and '\t' as \
outer and inner separators +        foreach (const QSslCertificate &cert, \
socket.peerCertificateChain()) { +            foreach (const KSslError &error, \
sslErrors) { +                if (error.certificate() == cert) {
+                    errorStr += QString::number(static_cast<int>(error.error())) + \
'\t'; +                }
+            }
+            if (errorStr.endsWith('\t')) {
+                errorStr.chop(1);
+            }
+            errorStr += '\n';
+        }
+        errorStr.chop(1);
+        q->setMetaData("ssl_cert_errors", errorStr);
+
+        QString peerCertChain;
+        foreach (const QSslCertificate &cert, socket.peerCertificateChain()) {
+            peerCertChain.append(cert.toPem());
+            peerCertChain.append('\x01');
+        }
+        peerCertChain.chop(1);
+        q->setMetaData("ssl_peer_chain", peerCertChain);
+    }
+
+    TCPSlaveBase* q;
+
     int timeout;
     bool isBlocking;
 
@@ -125,6 +176,7 @@
     bool autoSSL;
     bool sslNoUi; // If true, we just drop the connection silently
                   // if SSL certificate check fails in some way.
+    QList<KSslError> sslErrors;
 };
 
 
@@ -140,7 +192,7 @@
                            const QByteArray &appSocket,
                            bool autoSSL)
  : SlaveBase(protocol, poolSocket, appSocket),
-   d(new TcpSlaveBasePrivate)
+   d(new TcpSlaveBasePrivate(this))
 {
     d->timeout = KProtocolManager::connectTimeout();
     d->isBlocking = true;
@@ -441,50 +493,31 @@
                  << " supportedBits:" << cipher.supportedBits()
                  << " usedBits:" << cipher.usedBits();
 
-    setMetaData("ssl_protocol_version", d->socket.negotiatedSslVersionName());
-    QString sslCipher = cipher.encryptionMethod() + '\n';
-    sslCipher += cipher.authenticationMethod() + '\n';
-    sslCipher += cipher.keyExchangeMethod() + '\n';
-    sslCipher += cipher.digestMethod();
-    setMetaData("ssl_cipher", sslCipher);
-    setMetaData("ssl_cipher_used_bits", QString::number(cipher.usedBits()));
-    setMetaData("ssl_cipher_bits", QString::number(cipher.supportedBits()));
-    setMetaData("ssl_peer_ip", d->ip);
-
-    // try to fill in the blanks, i.e. missing certificates, and just assume that
-    // those belong to the peer (==website or similar) certificate.
-    QList<KSslError> sslErrors = d->socket.sslErrors();
-    for (int i = 0; i < sslErrors.count(); i++) {
-        if (sslErrors[i].certificate().isNull()) {
-            sslErrors[i] = KSslError(sslErrors[i].error(),
-                                     d->socket.peerCertificateChain()[0]);
+    // Since we connect by IP (cf. KIO::HostInfo) the SSL code will not recognize
+    // that the site certificate belongs to the domain. We therefore do the
+    // domain<->certificate matching here.
+    d->sslErrors = d->socket.sslErrors();
+    QSslCertificate peerCert = d->socket.peerCertificateChain().first();
+    QStringList domainPatterns(peerCert.subjectInfo(QSslCertificate::CommonName));
+    domainPatterns += peerCert.alternateSubjectNames().values(QSsl::DnsEntry);
+    QRegExp domainMatcher(QString(), Qt::CaseInsensitive, QRegExp::Wildcard);
+    QMutableListIterator<KSslError> it(d->sslErrors);
+    while (it.hasNext()) {
+        // As of 4.4.0 Qt does not assign a certificate to the QSslError it emits
+        // *in the case of HostNameMismatch*. A HostNameMismatch, however, will \
always +        // be an error of the peer certificate so we just don't check the \
error's +        // certificate().
+        if (it.next().error() != KSslError::HostNameMismatch) {
+            continue;
         }
-    }
-
-    QString errorStr;
-    // encode the two-dimensional numeric error list using '\n' and '\t' as outer \
                and inner separators
-    foreach (const QSslCertificate &cert, d->socket.peerCertificateChain()) {        \
                
-        foreach (const KSslError &error, sslErrors) {
-            if (error.certificate() == cert) {
-                errorStr += QString::number(static_cast<int>(error.error())) + '\t';
+        foreach (const QString &dp, domainPatterns) {
+            domainMatcher.setPattern(dp);
+            if (domainMatcher.exactMatch(d->host)) {
+                it.remove();
             }
         }
-        if (errorStr.endsWith('\t')) {
-            errorStr.chop(1);
-        }
-        errorStr += '\n';
     }
-    errorStr.chop(1);
-    setMetaData("ssl_cert_errors", errorStr);
 
-    QString peerCertChain;
-    foreach (const QSslCertificate &cert, d->socket.peerCertificateChain()) {
-        peerCertChain.append(cert.toPem());
-        peerCertChain.append('\x01');
-    }
-    peerCertChain.chop(1);
-    setMetaData("ssl_peer_chain", peerCertChain);
-
     // The app side needs the metadata now for the SSL error dialog (if any) but
     // the same metadata will be needed later, too. When "later" arrives the slave
     // may actually be connected to a different application that doesn't know
@@ -493,6 +526,7 @@
     // from here, for example. And Konqi will be the second application to connect
     // to the slave.
     // Therefore we choose to have our metadata and send it, too :)
+    d->prepareSslRelatedMetaData();
     sendAndKeepMetaData();
 
     SslResult rc = verifyServerCertificate();
@@ -529,7 +563,6 @@
     return rc;
 }
 
-
 void TCPSlaveBase::selectClientCertificate()
 {
 #if 0 //hehe
@@ -701,50 +734,19 @@
 #endif
 }
 
-
 TCPSlaveBase::SslResult TCPSlaveBase::verifyServerCertificate()
 {
     d->sslNoUi = hasMetaData("ssl_no_ui") && (metaData("ssl_no_ui") != "FALSE");
 
-    QList<KSslError> se = d->socket.sslErrors();
-    if (se.isEmpty())
+    if (d->sslErrors.isEmpty())
         return ResultOk;
-
-    // Since we connect by IP (cf. KIO::HostInfo) the SSL code will not recognize
-    // that the site certificate belongs to the domain. We therefore do the
-    // domain<->certificate matching here.
-
-    QSslCertificate peerCert = d->socket.peerCertificateChain().first();
-    QStringList domainPatterns(peerCert.subjectInfo(QSslCertificate::CommonName));
-    domainPatterns += peerCert.alternateSubjectNames().values(QSsl::DnsEntry);
-    QRegExp domainMatcher(QString(), Qt::CaseInsensitive, QRegExp::Wildcard);
-    QMutableListIterator<KSslError> it(se);
-    while (it.hasNext()) {
-        // As of 4.4.0 Qt does not assign a certificate to the QSslError it emits
-        // *in the case of HostNameMismatch*. A HostNameMismatch, however, will \
                always
-        // be an error of the peer certificate so we just don't check the error's
-        // certificate().
-        if (it.next().error() != KSslError::HostNameMismatch) {
-            continue;
-        }
-        foreach (const QString &dp, domainPatterns) {
-            domainMatcher.setPattern(dp);
-            if (domainMatcher.exactMatch(d->host)) {
-                it.remove();
-            }
-        }
-    }
-
-    if (se.isEmpty())
-        return ResultOk;
-
     if (d->sslNoUi)
         return ResultFailed;
 
     QString message = i18n("The server failed the authenticity check (%1).\n\n",
                            d->host);
 
-    foreach (const KSslError &err, se) {
+    foreach (const KSslError &err, d->sslErrors) {
         //### use our own wording that is "closer to the user"
         message.append(err.errorString());
         message.append('\n');
@@ -753,7 +755,6 @@
     //### Consider that hostname mismatch and e.g. an expired certificate are very \
                different.
     //    Maybe there should be no option to acceptForever a cert with bad hostname.
 
-
     /* We need a list of ignorable errors. I don't think it makes sense to ignore
        malformed certificates, for example, as other environments probably don't do
        that either. It would be similar to a compiler trying to correct syntax \
errors. @@ -768,15 +769,15 @@
     KSslCertificateRule rule = cm->rule(d->socket.peerCertificateChain().first(), \
d->host);  
     //TODO put nonIgnorableErrors into the cert manager
-    QList<KSslError> fatalErrors = d->nonIgnorableErrors(se);
+    QList<KSslError> fatalErrors = d->nonIgnorableErrors(d->sslErrors);
     if (!fatalErrors.isEmpty()) {
         //TODO message "sorry, fatal error, you can't override it"
         return ResultFailed;
     }
 
     //throw out previously seen errors that are supposed to be ignored.
-    se = rule.filterErrors(se);
-    if (se.isEmpty()) {
+    QList<KSslError> remainingErrors = rule.filterErrors(d->sslErrors);
+    if (remainingErrors.isEmpty()) {
         kDebug(7029) << "Error list empty after removing errors to be ignored. \
Continuing.";  return ResultOk | ResultOverridden;
     }
@@ -820,7 +821,7 @@
     //rule = KSslCertificateRule(d->socket.peerCertificateChain().first(), \
whatever);  
     rule.setExpiryDateTime(ruleExpiry);
-    rule.setIgnoredErrors(se);
+    rule.setIgnoredErrors(remainingErrors);
     cm->setRule(rule);
 
     return ResultOk | ResultOverridden;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic