00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "tcpslavebase.h"
00028
00029 #include <config.h>
00030
00031 #include <sys/types.h>
00032 #include <sys/uio.h>
00033 #include <sys/time.h>
00034 #include <sys/socket.h>
00035
00036 #include <netinet/in.h>
00037
00038 #include <time.h>
00039 #include <netdb.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042
00043 #include <kdebug.h>
00044 #include <ksslcertificatemanager.h>
00045 #include <ksslsettings.h>
00046 #include <kmessagebox.h>
00047 #include <network/ktcpsocket.h>
00048
00049 #include <klocale.h>
00050 #include <QtCore/QDataStream>
00051 #include <QtCore/QTime>
00052 #include <QtNetwork/QTcpSocket>
00053 #include <QtNetwork/QHostInfo>
00054 #include <QtDBus/QtDBus>
00055
00056 #include <kapplication.h>
00057 #include <ktoolinvocation.h>
00058 #include <ksocketfactory.h>
00059 #include <kprotocolmanager.h>
00060
00061 using namespace KIO;
00062
00063
00064 typedef QMap<QString, QString> StringStringMap;
00065 Q_DECLARE_METATYPE(StringStringMap)
00066
00067 namespace KIO {
00068 Q_DECLARE_OPERATORS_FOR_FLAGS(TCPSlaveBase::SslResult)
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00104 class TCPSlaveBase::TcpSlaveBasePrivate
00105 {
00106 public:
00107 TcpSlaveBasePrivate(TCPSlaveBase* qq) : q(qq) {}
00108
00109 void prepareSslRelatedMetaData()
00110 {
00111 KSslCipher cipher = socket.sessionCipher();
00112 q->setMetaData("ssl_protocol_version", socket.negotiatedSslVersionName());
00113 QString sslCipher = cipher.encryptionMethod() + '\n';
00114 sslCipher += cipher.authenticationMethod() + '\n';
00115 sslCipher += cipher.keyExchangeMethod() + '\n';
00116 sslCipher += cipher.digestMethod();
00117 q->setMetaData("ssl_cipher", sslCipher);
00118 q->setMetaData("ssl_cipher_used_bits", QString::number(cipher.usedBits()));
00119 q->setMetaData("ssl_cipher_bits", QString::number(cipher.supportedBits()));
00120 q->setMetaData("ssl_peer_ip", ip);
00121
00122
00123
00124 for (int i = 0; i < sslErrors.count(); i++) {
00125 if (sslErrors[i].certificate().isNull()) {
00126 sslErrors[i] = KSslError(sslErrors[i].error(),
00127 socket.peerCertificateChain()[0]);
00128 }
00129 }
00130
00131 QString errorStr;
00132
00133 foreach (const QSslCertificate &cert, socket.peerCertificateChain()) {
00134 foreach (const KSslError &error, sslErrors) {
00135 if (error.certificate() == cert) {
00136 errorStr += QString::number(static_cast<int>(error.error())) + '\t';
00137 }
00138 }
00139 if (errorStr.endsWith('\t')) {
00140 errorStr.chop(1);
00141 }
00142 errorStr += '\n';
00143 }
00144 errorStr.chop(1);
00145 q->setMetaData("ssl_cert_errors", errorStr);
00146
00147 QString peerCertChain;
00148 foreach (const QSslCertificate &cert, socket.peerCertificateChain()) {
00149 peerCertChain.append(cert.toPem());
00150 peerCertChain.append('\x01');
00151 }
00152 peerCertChain.chop(1);
00153 q->setMetaData("ssl_peer_chain", peerCertChain);
00154 }
00155
00156 TCPSlaveBase* q;
00157
00158 int timeout;
00159 bool isBlocking;
00160
00161 KTcpSocket socket;
00162
00163 QString host;
00164 QString ip;
00165 quint16 port;
00166 QByteArray serviceName;
00167
00168 KSSLSettings sslSettings;
00169 bool usingSSL;
00170 bool autoSSL;
00171 bool sslNoUi;
00172
00173 QList<KSslError> sslErrors;
00174 };
00175
00176
00177
00178 QIODevice *TCPSlaveBase::socket() const
00179 {
00180 return &d->socket;
00181 }
00182
00183
00184 TCPSlaveBase::TCPSlaveBase(const QByteArray &protocol,
00185 const QByteArray &poolSocket,
00186 const QByteArray &appSocket,
00187 bool autoSSL)
00188 : SlaveBase(protocol, poolSocket, appSocket),
00189 d(new TcpSlaveBasePrivate(this))
00190 {
00191 d->timeout = KProtocolManager::connectTimeout();
00192 d->isBlocking = true;
00193 d->port = 0;
00194 d->serviceName = protocol;
00195 d->usingSSL = false;
00196 d->autoSSL = autoSSL;
00197 d->sslNoUi = false;
00198 }
00199
00200
00201 TCPSlaveBase::~TCPSlaveBase()
00202 {
00203 delete d;
00204 }
00205
00206
00207 ssize_t TCPSlaveBase::write(const char *data, ssize_t len)
00208 {
00209 ssize_t written = d->socket.write(data, len);
00210 if (written == -1) {
00211 kDebug(7027) << "d->socket.write() returned -1! Socket error is"
00212 << d->socket.error() << ", Socket state is" << d->socket.state();
00213 }
00214
00215 bool success = false;
00216 if (d->isBlocking) {
00217
00218 success = d->socket.waitForBytesWritten(-1);
00219 } else {
00220
00221
00222
00223 success = d->socket.waitForBytesWritten(0);
00224 }
00225
00226 d->socket.flush();
00227
00228 if (d->socket.state() != KTcpSocket::ConnectedState || !success) {
00229 kDebug(7027) << "Write failed, will return -1! Socket error is"
00230 << d->socket.error() << ", Socket state is" << d->socket.state()
00231 << "Return value of waitForBytesWritten() is" << success;
00232 return -1;
00233 }
00234
00235 return written;
00236 }
00237
00238
00239 ssize_t TCPSlaveBase::read(char* data, ssize_t len)
00240 {
00241 if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) {
00242 setMetaData("ssl_in_use", "FALSE");
00243 kDebug(7029) << "lost SSL connection.";
00244 return -1;
00245 }
00246
00247 if (!d->socket.bytesAvailable()) {
00248 if (d->isBlocking) {
00249 d->socket.waitForReadyRead(-1);
00250 } else {
00251 d->socket.waitForReadyRead(0);
00252 }
00253 } else if (d->socket.encryptionMode() != KTcpSocket::SslClientMode ||
00254 QNetworkProxy::applicationProxy().type() == QNetworkProxy::NoProxy) {
00255
00256
00257 d->socket.waitForReadyRead(0);
00258 }
00259
00260 return d->socket.read(data, len);
00261 }
00262
00263
00264 ssize_t TCPSlaveBase::readLine(char *data, ssize_t len)
00265 {
00266 if (d->usingSSL && (d->socket.encryptionMode() != KTcpSocket::SslClientMode)) {
00267 setMetaData("ssl_in_use", "FALSE");
00268 kDebug(7029) << "lost SSL connection.";
00269 return -1;
00270 }
00271
00272
00273
00274
00275 #ifdef PIGS_CAN_FLY
00276 if (!d->isBlocking) {
00277 d->socket.waitForReadyRead(0);
00278 return d->socket.readLine(data, len);
00279 }
00280 #endif
00281 ssize_t readTotal = 0;
00282 do {
00283 if (!d->socket.bytesAvailable())
00284 d->socket.waitForReadyRead(-1);
00285 ssize_t readStep = d->socket.readLine(&data[readTotal], len-readTotal);
00286 if (readStep == -1 || (readStep == 0 && d->socket.state() != KTcpSocket::ConnectedState)) {
00287 return -1;
00288 }
00289 readTotal += readStep;
00290 } while (readTotal == 0 || data[readTotal-1] != '\n');
00291
00292 return readTotal;
00293 }
00294
00295
00296 bool TCPSlaveBase::connectToHost(const QString &,
00297 const QString &host,
00298 quint16 port)
00299 {
00300 setMetaData("ssl_in_use", "FALSE");
00301
00302
00303
00304
00305 if (metaData("main_frame_request") == "TRUE"
00306 && metaData("ssl_activate_warnings") == "TRUE"
00307 && metaData("ssl_was_in_use") == "TRUE"
00308 && !d->autoSSL) {
00309 KSSLSettings kss;
00310 if (kss.warnOnLeave()) {
00311 int result = messageBox(i18n("You are about to leave secure "
00312 "mode. Transmissions will no "
00313 "longer be encrypted.\nThis "
00314 "means that a third party could "
00315 "observe your data in transit."),
00316 WarningContinueCancel,
00317 i18n("Security Information"),
00318 i18n("C&ontinue Loading"), QString(),
00319 "WarnOnLeaveSSLMode");
00320
00321 if (result == KMessageBox::Cancel) {
00322 error(ERR_USER_CANCELED, host);
00323 return false;
00324 }
00325 }
00326 }
00327
00328 KTcpSocket::SslVersion trySslVersion = KTcpSocket::TlsV1;
00329 while (true) {
00330 disconnectFromHost();
00331 d->host = host;
00332
00333
00334
00335 QList<QHostAddress> addresses;
00336
00337 QHostAddress address;
00338 if (address.setAddress(host)) {
00339 addresses.append(address);
00340 } else {
00341 QHostInfo info;
00342 lookupHost(host);
00343 waitForHostInfo(info);
00344 if (info.error() != QHostInfo::NoError) {
00345 error(ERR_UNKNOWN_HOST, host);
00346 return false;
00347 }
00348 addresses = info.addresses();
00349 }
00350
00351 QListIterator<QHostAddress> it(addresses);
00352 int timeout = d->timeout * 1000;
00353 QTime time;
00354 forever {
00355 time.start();
00356 d->socket.connectToHost(it.next(), port);
00357 if (d->socket.waitForConnected(timeout)) {
00358 break;
00359 }
00360 timeout -= time.elapsed();
00361 if (!it.hasNext() || (timeout < 0)) {
00362 error(ERR_COULD_NOT_CONNECT,
00363 host + QLatin1String(": ") + d->socket.errorString());
00364 return false;
00365 }
00366 }
00367
00368
00369
00370 d->ip = d->socket.peerAddress().toString();
00371 d->port = d->socket.peerPort();
00372
00373 if (d->autoSSL) {
00374 SslResult res = startTLSInternal(trySslVersion);
00375 if ((res & ResultFailed) && (res & ResultFailedEarly)
00376 && (trySslVersion == KTcpSocket::TlsV1)) {
00377 trySslVersion = KTcpSocket::SslV3;
00378 continue;
00379
00380 }
00381 if (res & ResultFailed) {
00382 error(ERR_COULD_NOT_CONNECT,
00383 i18nc("%1 is a host name", "%1: SSL negotiation failed", host));
00384 return false;
00385 }
00386 }
00387 return true;
00388 }
00389 Q_ASSERT(false);
00390 }
00391
00392 void TCPSlaveBase::disconnectFromHost()
00393 {
00394 kDebug(7027);
00395 d->host.clear();
00396 d->ip.clear();
00397 d->usingSSL = false;
00398
00399 if (d->socket.state() == KTcpSocket::UnconnectedState) {
00400
00401
00402 d->socket.close();
00403 return;
00404 }
00405
00406
00407
00408
00409 d->socket.disconnectFromHost();
00410 if (d->socket.state() != KTcpSocket::UnconnectedState)
00411 d->socket.waitForDisconnected(-1);
00412 d->socket.close();
00413 }
00414
00415 bool TCPSlaveBase::isAutoSsl() const
00416 {
00417 return d->autoSSL;
00418 }
00419
00420 bool TCPSlaveBase::isUsingSsl() const
00421 {
00422 return d->usingSSL;
00423 }
00424
00425 quint16 TCPSlaveBase::port() const
00426 {
00427 return d->port;
00428 }
00429
00430 bool TCPSlaveBase::atEnd() const
00431 {
00432 return d->socket.atEnd();
00433 }
00434
00435 bool TCPSlaveBase::startSsl()
00436 {
00437 if (d->usingSSL)
00438 return false;
00439 return startTLSInternal(KTcpSocket::TlsV1) & ResultOk;
00440 }
00441
00442
00443 static bool isMatchingHostname(const QString &cnIn, const QString &hostnameIn)
00444 {
00445 const QString cn = cnIn.toLower();
00446 const QString hostname = hostnameIn.toLower();
00447
00448 const int wildcard = cn.indexOf(QLatin1Char('*'));
00449
00450
00451 if (wildcard < 0)
00452 return cn == hostname;
00453
00454 const int firstCnDot = cn.indexOf(QLatin1Char('.'));
00455 const int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
00456
00457
00458 if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
00459 return false;
00460
00461
00462 if (wildcard+1 != firstCnDot)
00463 return false;
00464
00465
00466 if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
00467 return false;
00468
00469
00470 if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
00471 return false;
00472
00473
00474 if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot))
00475 return false;
00476
00477
00478 QHostAddress addr(hostname);
00479 if (!addr.isNull())
00480 return false;
00481
00482
00483 return true;
00484 }
00485
00486 TCPSlaveBase::SslResult TCPSlaveBase::startTLSInternal(uint v_)
00487 {
00488 KTcpSocket::SslVersion sslVersion = static_cast<KTcpSocket::SslVersion>(v_);
00489 selectClientCertificate();
00490
00491
00492
00493
00494 d->usingSSL = true;
00495 setMetaData("ssl_in_use", "TRUE");
00496
00497 d->socket.setAdvertisedSslVersion(sslVersion);
00498
00499
00500
00501
00502
00503 d->socket.ignoreSslErrors();
00504 d->socket.startClientEncryption();
00505 const bool encryptionStarted = d->socket.waitForEncrypted(-1);
00506
00507
00508 KSslCipher cipher = d->socket.sessionCipher();
00509
00510 if (!encryptionStarted || d->socket.encryptionMode() != KTcpSocket::SslClientMode
00511 || cipher.isNull() || cipher.usedBits() == 0 || d->socket.peerCertificateChain().isEmpty()) {
00512 d->usingSSL = false;
00513 setMetaData("ssl_in_use", "FALSE");
00514 kDebug(7029) << "Initial SSL handshake failed. encryptionStarted is"
00515 << encryptionStarted << ", cipher.isNull() is" << cipher.isNull()
00516 << ", cipher.usedBits() is" << cipher.usedBits()
00517 << ", length of certificate chain is" << d->socket.peerCertificateChain().count()
00518 << ", the socket says:" << d->socket.errorString()
00519 << "and the list of SSL errors contains"
00520 << d->socket.sslErrors().count() << "items.";
00521 return ResultFailed | ResultFailedEarly;
00522 }
00523
00524 kDebug(7029) << "Cipher info - "
00525 << " advertised SSL protocol version" << d->socket.advertisedSslVersion()
00526 << " negotiated SSL protocol version" << d->socket.negotiatedSslVersion()
00527 << " authenticationMethod:" << cipher.authenticationMethod()
00528 << " encryptionMethod:" << cipher.encryptionMethod()
00529 << " keyExchangeMethod:" << cipher.keyExchangeMethod()
00530 << " name:" << cipher.name()
00531 << " supportedBits:" << cipher.supportedBits()
00532 << " usedBits:" << cipher.usedBits();
00533
00534
00535
00536
00537 d->sslErrors = d->socket.sslErrors();
00538 QSslCertificate peerCert = d->socket.peerCertificateChain().first();
00539 QMutableListIterator<KSslError> it(d->sslErrors);
00540 while (it.hasNext()) {
00541
00542
00543
00544
00545
00546
00547 if (it.next().error() == KSslError::HostNameMismatch) {
00548 it.remove();
00549 }
00550 }
00551
00552
00553
00554
00555 QStringList domainPatterns(peerCert.subjectInfo(QSslCertificate::CommonName));
00556 domainPatterns += peerCert.alternateSubjectNames().values(QSsl::DnsEntry);
00557 bool names_match = false;
00558 foreach (const QString &dp, domainPatterns) {
00559 if (isMatchingHostname(dp, d->host)) {
00560 names_match = true;
00561 break;
00562 }
00563 }
00564 if (!names_match) {
00565 d->sslErrors.insert(0, KSslError(KSslError::HostNameMismatch, peerCert));
00566 }
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 d->prepareSslRelatedMetaData();
00578 sendAndKeepMetaData();
00579
00580 SslResult rc = verifyServerCertificate();
00581 if (rc & ResultFailed) {
00582 d->usingSSL = false;
00583 setMetaData("ssl_in_use", "FALSE");
00584 kDebug(7029) << "server certificate verification failed.";
00585 d->socket.disconnectFromHost();
00586 return ResultFailed;
00587 } else if (rc & ResultOverridden) {
00588 kDebug(7029) << "server certificate verification failed but continuing at user's request.";
00589 }
00590
00591
00592 if (metaData("ssl_activate_warnings") == "TRUE"
00593 && metaData("ssl_was_in_use") == "FALSE"
00594 && d->sslSettings.warnOnEnter()) {
00595
00596 int msgResult = messageBox(i18n("You are about to enter secure mode. "
00597 "All transmissions will be encrypted "
00598 "unless otherwise noted.\nThis means "
00599 "that no third party will be able to "
00600 "easily observe your data in transit."),
00601 WarningYesNo,
00602 i18n("Security Information"),
00603 i18n("Display SSL &Information"),
00604 i18n("C&onnect"),
00605 "WarnOnEnterSSLMode");
00606 if (msgResult == KMessageBox::Yes) {
00607 messageBox(SSLMessageBox , d->host);
00608 }
00609 }
00610
00611 return rc;
00612 }
00613
00614 void TCPSlaveBase::selectClientCertificate()
00615 {
00616 #if 0 //hehe
00617 QString certname;
00618 bool send = false, prompt = false, save = false, forcePrompt = false;
00619 KSSLCertificateHome::KSSLAuthAction aa;
00620
00621 setMetaData("ssl_using_client_cert", "FALSE");
00622
00623 if (metaData("ssl_no_client_cert") == "TRUE") return;
00624 forcePrompt = (metaData("ssl_force_cert_prompt") == "TRUE");
00625
00626
00627 if (d->pkcs) {
00628 delete d->pkcs;
00629 d->pkcs = NULL;
00630 }
00631
00632 if (!d->kssl) return;
00633
00634
00635 if (!forcePrompt) {
00636 certname = KSSLCertificateHome::getDefaultCertificateName(&aa);
00637 switch (aa) {
00638 case KSSLCertificateHome::AuthSend:
00639 send = true; prompt = false;
00640 break;
00641 case KSSLCertificateHome::AuthDont:
00642 send = false; prompt = false;
00643 certname.clear();
00644 break;
00645 case KSSLCertificateHome::AuthPrompt:
00646 send = false; prompt = true;
00647 break;
00648 default:
00649 break;
00650 }
00651 }
00652
00653
00654 QString tmpcn = KSSLCertificateHome::getDefaultCertificateName(d->host, &aa);
00655 if (aa != KSSLCertificateHome::AuthNone) {
00656 switch (aa) {
00657 case KSSLCertificateHome::AuthSend:
00658 send = true;
00659 prompt = false;
00660 certname = tmpcn;
00661 break;
00662 case KSSLCertificateHome::AuthDont:
00663 send = false;
00664 prompt = false;
00665 certname.clear();
00666 break;
00667 case KSSLCertificateHome::AuthPrompt:
00668 send = false;
00669 prompt = true;
00670 certname = tmpcn;
00671 break;
00672 default:
00673 break;
00674 }
00675 }
00676
00677
00678 if (hasMetaData("ssl_demand_certificate")) {
00679 certname = metaData("ssl_demand_certificate");
00680 if (!certname.isEmpty()) {
00681 forcePrompt = false;
00682 prompt = false;
00683 send = true;
00684 }
00685 }
00686
00687 if (certname.isEmpty() && !prompt && !forcePrompt) return;
00688
00689
00690 if (prompt || forcePrompt) {
00691 QStringList certs = KSSLCertificateHome::getCertificateList();
00692
00693 QStringList::const_iterator it = certs.begin();
00694 while (it != certs.end()) {
00695 KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(*it);
00696 if (pkcs && (!pkcs->getCertificate() ||
00697 !pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())) {
00698 it = certs.erase(it);
00699 } else {
00700 ++it;
00701 }
00702 delete pkcs;
00703 }
00704
00705 if (certs.isEmpty()) return;
00706
00707 if (!QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kio.uiserver")) {
00708 KToolInvocation::startServiceByDesktopPath("kuiserver.desktop",
00709 QStringList());
00710 }
00711
00712 QDBusInterface uis("org.kde.kio.uiserver", "/UIServer", "org.kde.KIO.UIServer");
00713
00714 QDBusMessage retVal = uis.call("showSSLCertDialog", d->host, certs, metaData("window-id").toLongLong());
00715 if (retVal.type() == QDBusMessage::ReplyMessage) {
00716 if (retVal.arguments().at(0).toBool()) {
00717 send = retVal.arguments().at(1).toBool();
00718 save = retVal.arguments().at(2).toBool();
00719 certname = retVal.arguments().at(3).toString();
00720 }
00721 }
00722 }
00723
00724
00725
00726 if (!send) {
00727 if (save) {
00728 KSSLCertificateHome::setDefaultCertificate(certname, d->host,
00729 false, false);
00730 }
00731 return;
00732 }
00733
00734
00735 KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(certname);
00736 if (!pkcs && KSSLCertificateHome::hasCertificateByName(certname)) {
00737 KIO::AuthInfo ai;
00738 bool first = true;
00739 do {
00740 ai.prompt = i18n("Enter the certificate password:");
00741 ai.caption = i18n("SSL Certificate Password");
00742 ai.url.setProtocol("kssl");
00743 ai.url.setHost(certname);
00744 ai.username = certname;
00745 ai.keepPassword = true;
00746
00747 bool showprompt;
00748 if (first)
00749 showprompt = !checkCachedAuthentication(ai);
00750 else
00751 showprompt = true;
00752 if (showprompt) {
00753 if (!openPasswordDialog(ai, first ? QString() :
00754 i18n("Unable to open the certificate. Try a new password?")))
00755 break;
00756 }
00757
00758 first = false;
00759 pkcs = KSSLCertificateHome::getCertificateByName(certname, ai.password);
00760 } while (!pkcs);
00761
00762 }
00763
00764
00765 if (pkcs) {
00766 if (!d->kssl->setClientCertificate(pkcs)) {
00767 messageBox(Information, i18n("The procedure to set the "
00768 "client certificate for the session "
00769 "failed."), i18n("SSL"));
00770 delete pkcs;
00771 pkcs = 0L;
00772 } else {
00773 kDebug(7029) << "Client SSL certificate is being used.";
00774 setMetaData("ssl_using_client_cert", "TRUE");
00775 if (save) {
00776 KSSLCertificateHome::setDefaultCertificate(certname, d->host,
00777 true, false);
00778 }
00779 }
00780 d->pkcs = pkcs;
00781 }
00782 #endif
00783 }
00784
00785 TCPSlaveBase::SslResult TCPSlaveBase::verifyServerCertificate()
00786 {
00787 d->sslNoUi = hasMetaData("ssl_no_ui") && (metaData("ssl_no_ui") != "FALSE");
00788
00789 if (d->sslErrors.isEmpty()) {
00790 return ResultOk;
00791 } else if (d->sslNoUi) {
00792 return ResultFailed;
00793 }
00794
00795 QList<KSslError> fatalErrors = KSslCertificateManager::nonIgnorableErrors(d->sslErrors);
00796 if (!fatalErrors.isEmpty()) {
00797
00798 return ResultFailed;
00799 }
00800
00801 KSslCertificateManager *const cm = KSslCertificateManager::self();
00802 KSslCertificateRule rule = cm->rule(d->socket.peerCertificateChain().first(), d->host);
00803
00804
00805 QList<KSslError> remainingErrors = rule.filterErrors(d->sslErrors);
00806 if (remainingErrors.isEmpty()) {
00807 kDebug(7029) << "Error list empty after removing errors to be ignored. Continuing.";
00808 return ResultOk | ResultOverridden;
00809 }
00810
00811
00812
00813 QString message = i18n("The server failed the authenticity check (%1).\n\n", d->host);
00814 foreach (const KSslError &err, d->sslErrors) {
00815 message.append(err.errorString());
00816 message.append('\n');
00817 }
00818 message = message.trimmed();
00819
00820 int msgResult;
00821 do {
00822 msgResult = messageBox(WarningYesNoCancel, message,
00823 i18n("Server Authentication"),
00824 i18n("&Details"), i18n("Co&ntinue"));
00825 if (msgResult == KMessageBox::Yes) {
00826
00827 messageBox(SSLMessageBox , d->host);
00828 } else if (msgResult == KMessageBox::Cancel) {
00829 return ResultFailed;
00830 }
00831
00832 } while (msgResult == KMessageBox::Yes);
00833
00834
00835
00836 msgResult = messageBox(WarningYesNo,
00837 i18n("Would you like to accept this "
00838 "certificate forever without "
00839 "being prompted?"),
00840 i18n("Server Authentication"),
00841 i18n("&Forever"),
00842 i18n("&Current Session only"));
00843 QDateTime ruleExpiry = QDateTime::currentDateTime();
00844 if (msgResult == KMessageBox::Yes) {
00845
00846 ruleExpiry = ruleExpiry.addYears(1000);
00847 } else {
00848
00849 ruleExpiry = ruleExpiry.addSecs(30*60);
00850 }
00851
00852
00853
00854
00855 rule.setExpiryDateTime(ruleExpiry);
00856 rule.setIgnoredErrors(d->sslErrors);
00857 cm->setRule(rule);
00858
00859 return ResultOk | ResultOverridden;
00860 #if 0 //### need to to do something like the old code about the main and subframe stuff
00861 kDebug(7029) << "SSL HTTP frame the parent? " << metaData("main_frame_request");
00862 if (!hasMetaData("main_frame_request") || metaData("main_frame_request") == "TRUE") {
00863
00864 setMetaData("ssl_parent_ip", d->ip);
00865 setMetaData("ssl_parent_cert", pc.toString());
00866
00867 KSSLCertificateCache::KSSLCertificatePolicy cp =
00868 d->certCache->getPolicyByCertificate(pc);
00869
00870
00871 if (ksv != KSSLCertificate::Ok) {
00872 if (d->sslNoUi) {
00873 return -1;
00874 }
00875
00876 if (cp == KSSLCertificateCache::Unknown ||
00877 cp == KSSLCertificateCache::Ambiguous) {
00878 cp = KSSLCertificateCache::Prompt;
00879 } else {
00880
00881 permacache = d->certCache->isPermanent(pc);
00882 }
00883
00884 if (!_IPmatchesCN && cp == KSSLCertificateCache::Accept) {
00885 cp = KSSLCertificateCache::Prompt;
00886
00887 }
00888
00890
00891
00892 d->certCache->addCertificate(pc, cp, permacache);
00893 if (doAddHost) d->certCache->addHost(pc, d->host);
00894 } else {
00895
00896 KSSLCertificateCache::KSSLCertificatePolicy cp =
00897 d->certCache->getPolicyByCertificate(pc);
00898 isChild = true;
00899
00900
00901
00902 bool certAndIPTheSame = (d->ip == metaData("ssl_parent_ip") &&
00903 pc.toString() == metaData("ssl_parent_cert"));
00904
00905 if (ksv == KSSLCertificate::Ok) {
00906 if (certAndIPTheSame) {
00907 rc = 1;
00908 setMetaData("ssl_action", "accept");
00909 } else {
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 setMetaData("ssl_action", "accept");
00926 rc = 1;
00927
00928
00929 }
00930 } else {
00931 if (d->sslNoUi) {
00932 return -1;
00933 }
00934
00935 if (cp == KSSLCertificateCache::Accept) {
00936 if (certAndIPTheSame) {
00937 rc = 1;
00938 setMetaData("ssl_action", "accept");
00939 } else {
00940 result = messageBox(WarningYesNo,
00941 i18n("You have indicated that you wish to accept this certificate, but it is not issued to the server who is presenting it. Do you wish to continue loading?"),
00942 i18n("Server Authentication"));
00943 if (result == KMessageBox::Yes) {
00944 rc = 1;
00945 setMetaData("ssl_action", "accept");
00946 d->certCache->addHost(pc, d->host);
00947 } else {
00948 rc = -1;
00949 setMetaData("ssl_action", "reject");
00950 }
00951 }
00952 } else if (cp == KSSLCertificateCache::Reject) {
00953 messageBox(Information, i18n("SSL certificate is being rejected as requested. You can disable this in the KDE Control Center."),
00954 i18n("Server Authentication"));
00955 rc = -1;
00956 setMetaData("ssl_action", "reject");
00957 } else {
00958
00960
00961 return rc;
00962 #endif //#if 0
00963 return ResultOk | ResultOverridden;
00964 }
00965
00966
00967 bool TCPSlaveBase::isConnected() const
00968 {
00969
00970 return d->socket.state() == KTcpSocket::ConnectedState;
00971 }
00972
00973
00974 bool TCPSlaveBase::waitForResponse(int t)
00975 {
00976 if (d->socket.bytesAvailable()) {
00977 return true;
00978 }
00979 return d->socket.waitForReadyRead(t * 1000);
00980 }
00981
00982 void TCPSlaveBase::setBlocking(bool b)
00983 {
00984 if (!b) {
00985 kWarning(7029) << "Caller requested non-blocking mode, but that doesn't work";
00986 return;
00987 }
00988 d->isBlocking = b;
00989 }
00990
00991 void TCPSlaveBase::virtual_hook(int id, void* data)
00992 {
00993 SlaveBase::virtual_hook(id, data);
00994 }
00995
00996