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