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 #ifdef HAVE_CONFIG_H
00027 #include <config.h>
00028 #endif
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 <ksocks.h>
00043 #include <kdebug.h>
00044 #include <ksslall.h>
00045 #include <ksslcertdlg.h>
00046 #include <tdemessagebox.h>
00047 #ifndef Q_WS_WIN //temporary
00048 #include <kresolver.h>
00049 #endif
00050
00051 #include <tdelocale.h>
00052 #include <dcopclient.h>
00053 #include <tqcstring.h>
00054 #include <tqdatastream.h>
00055
00056 #include <tdeapplication.h>
00057
00058 #include <tdeprotocolmanager.h>
00059 #include <kde_file.h>
00060
00061 #include "tdeio/tcpslavebase.h"
00062
00063 using namespace TDEIO;
00064
00065 class TCPSlaveBase::TcpSlaveBasePrivate
00066 {
00067 public:
00068
00069 TcpSlaveBasePrivate() : rblockSz(256), militantSSL(false), userAborted(false) {}
00070 ~TcpSlaveBasePrivate() {}
00071
00072 KSSL *kssl;
00073 bool usingTLS;
00074 KSSLCertificateCache *cc;
00075 TQString host;
00076 TQString realHost;
00077 TQString ip;
00078 DCOPClient *dcc;
00079 KSSLPKCS12 *pkcs;
00080
00081 int status;
00082 int timeout;
00083 int rblockSz;
00084 bool block;
00085 bool useSSLTunneling;
00086 bool needSSLHandShake;
00087 bool militantSSL;
00088
00089 bool userAborted;
00090 MetaData savedMetaData;
00091 };
00092
00093
00094 TCPSlaveBase::TCPSlaveBase(unsigned short int defaultPort,
00095 const TQCString &protocol,
00096 const TQCString &poolSocket,
00097 const TQCString &appSocket)
00098 :SlaveBase (protocol, poolSocket, appSocket),
00099 m_iSock(-1),
00100 m_iDefaultPort(defaultPort),
00101 m_sServiceName(protocol),
00102 fp(0)
00103 {
00104
00105
00106 doConstructorStuff();
00107 m_bIsSSL = false;
00108 }
00109
00110 TCPSlaveBase::TCPSlaveBase(unsigned short int defaultPort,
00111 const TQCString &protocol,
00112 const TQCString &poolSocket,
00113 const TQCString &appSocket,
00114 bool useSSL)
00115 :SlaveBase (protocol, poolSocket, appSocket),
00116 m_iSock(-1),
00117 m_bIsSSL(useSSL),
00118 m_iDefaultPort(defaultPort),
00119 m_sServiceName(protocol),
00120 fp(0)
00121 {
00122 doConstructorStuff();
00123 if (useSSL)
00124 m_bIsSSL = initializeSSL();
00125 }
00126
00127
00128 void TCPSlaveBase::doConstructorStuff()
00129 {
00130 d = new TcpSlaveBasePrivate;
00131 d->kssl = 0L;
00132 d->ip = "";
00133 d->cc = 0L;
00134 d->usingTLS = false;
00135 d->dcc = 0L;
00136 d->pkcs = 0L;
00137 d->status = -1;
00138 d->timeout = KProtocolManager::connectTimeout();
00139 d->block = false;
00140 d->useSSLTunneling = false;
00141 }
00142
00143 TCPSlaveBase::~TCPSlaveBase()
00144 {
00145 cleanSSL();
00146 if (d->usingTLS) delete d->kssl;
00147 if (d->dcc) delete d->dcc;
00148 if (d->pkcs) delete d->pkcs;
00149 delete d;
00150 }
00151
00152 ssize_t TCPSlaveBase::write(const void *data, ssize_t len)
00153 {
00154 #ifdef Q_OS_UNIX
00155 if ( (m_bIsSSL || d->usingTLS) && !d->useSSLTunneling )
00156 {
00157 if ( d->needSSLHandShake )
00158 (void) doSSLHandShake( true );
00159 return d->kssl->write(data, len);
00160 }
00161 return KSocks::self()->write(m_iSock, data, len);
00162 #else
00163 return 0;
00164 #endif
00165 }
00166
00167 ssize_t TCPSlaveBase::read(void *data, ssize_t len)
00168 {
00169 #ifdef Q_OS_UNIX
00170 if ( (m_bIsSSL || d->usingTLS) && !d->useSSLTunneling )
00171 {
00172 if ( d->needSSLHandShake )
00173 (void) doSSLHandShake( true );
00174 return d->kssl->read(data, len);
00175 }
00176 return KSocks::self()->read(m_iSock, data, len);
00177 #else
00178 return 0;
00179 #endif
00180 }
00181
00182
00183 void TCPSlaveBase::setBlockSize(int sz)
00184 {
00185 if (sz <= 0)
00186 sz = 1;
00187
00188 d->rblockSz = sz;
00189 }
00190
00191
00192 ssize_t TCPSlaveBase::readLine(char *data, ssize_t len)
00193 {
00194
00195
00196
00197
00198
00199
00200 if (!data)
00201 return -1;
00202
00203 char tmpbuf[1024];
00204 *data = 0;
00205 ssize_t clen = 0;
00206 char *buf = data;
00207 int rc = 0;
00208
00209 if ((m_bIsSSL || d->usingTLS) && !d->useSSLTunneling) {
00210 if ( d->needSSLHandShake )
00211 (void) doSSLHandShake( true );
00212
00213 while (clen < len-1) {
00214 rc = d->kssl->pending();
00215 if (rc > 0) {
00216 int bytes = rc;
00217 if (bytes > d->rblockSz)
00218 bytes = d->rblockSz;
00219
00220 rc = d->kssl->peek(tmpbuf, bytes);
00221 if (rc <= 0) {
00222
00223 return -1;
00224 }
00225
00226 bytes = rc;
00227 for (int i = 0; i < rc; i++) {
00228 if (tmpbuf[i] == '\n') {
00229 bytes = i+1;
00230 break;
00231 }
00232 }
00233
00234 if (bytes+clen >= len)
00235 bytes = len - clen - 1;
00236
00237 rc = d->kssl->read(buf, bytes);
00238 if (rc > 0) {
00239 clen += rc;
00240 buf += (rc-1);
00241 if (*buf++ == '\n')
00242 break;
00243 } else {
00244
00245 return -1;
00246 }
00247 } else {
00248 rc = d->kssl->read(buf, 1);
00249 if (rc <= 0) {
00250 return -1;
00251
00252
00253
00254 } else {
00255 clen++;
00256 if (*buf++ == '\n')
00257 break;
00258 }
00259 }
00260 }
00261 } else {
00262 while (clen < len-1) {
00263 #ifdef Q_OS_UNIX
00264 rc = KSocks::self()->read(m_iSock, buf, 1);
00265 #else
00266 rc = 0;
00267 #endif
00268 if (rc <= 0) {
00269
00270 return -1;
00271 } else {
00272 clen++;
00273 if (*buf++ == '\n')
00274 break;
00275 }
00276 }
00277 }
00278
00279
00280 *buf = 0;
00281 return clen;
00282 }
00283
00284 unsigned short int TCPSlaveBase::port(unsigned short int _p)
00285 {
00286 unsigned short int p = _p;
00287
00288 if (_p <= 0)
00289 {
00290 p = m_iDefaultPort;
00291 }
00292
00293 return p;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 bool TCPSlaveBase::connectToHost( const TQString &host,
00303 unsigned int _port,
00304 bool sendError )
00305 {
00306 #ifdef Q_OS_UNIX
00307 unsigned short int p;
00308 KExtendedSocket ks;
00309
00310 d->userAborted = false;
00311
00312
00313 if (metaData("main_frame_request") == "TRUE" &&
00314 metaData("ssl_activate_warnings") == "TRUE" &&
00315 metaData("ssl_was_in_use") == "TRUE" &&
00316 !m_bIsSSL) {
00317 KSSLSettings kss;
00318 if (kss.warnOnLeave()) {
00319 int result = messageBox( i18n("You are about to leave secure "
00320 "mode. Transmissions will no "
00321 "longer be encrypted.\nThis "
00322 "means that a third party could "
00323 "observe your data in transit."),
00324 WarningContinueCancel,
00325 i18n("Security Information"),
00326 i18n("C&ontinue Loading"), TQString::null,
00327 "WarnOnLeaveSSLMode" );
00328
00329
00330 TDEConfig *config = new TDEConfig("tdeioslaverc");
00331 config->setGroup("Notification Messages");
00332
00333 if (!config->readBoolEntry("WarnOnLeaveSSLMode", true)) {
00334 config->deleteEntry("WarnOnLeaveSSLMode");
00335 config->sync();
00336 kss.setWarnOnLeave(false);
00337 kss.save();
00338 }
00339 delete config;
00340
00341 if ( result == KMessageBox::Cancel ) {
00342 d->userAborted = true;
00343 return false;
00344 }
00345 }
00346 }
00347
00348 d->status = -1;
00349 d->host = host;
00350 d->needSSLHandShake = m_bIsSSL;
00351 p = port(_port);
00352 ks.setAddress(host, p);
00353 if ( d->timeout > -1 )
00354 ks.setTimeout( d->timeout );
00355
00356 if (ks.connect() < 0)
00357 {
00358 d->status = ks.status();
00359 if ( sendError )
00360 {
00361 if (d->status == IO_LookupError)
00362 error( ERR_UNKNOWN_HOST, host);
00363 else if ( d->status != -1 )
00364 error( ERR_COULD_NOT_CONNECT, host);
00365 }
00366 return false;
00367 }
00368
00369 m_iSock = ks.fd();
00370
00371
00372 const TDESocketAddress *sa = ks.peerAddress();
00373 if (sa)
00374 d->ip = sa->nodeName();
00375 else
00376 d->ip = "";
00377
00378 ks.release();
00379
00380 if ( d->block != ks.blockingMode() )
00381 ks.setBlockingMode( d->block );
00382
00383 m_iPort=p;
00384
00385 if (m_bIsSSL && !d->useSSLTunneling) {
00386 if ( !doSSLHandShake( sendError ) )
00387 return false;
00388 }
00389 else
00390 setMetaData("ssl_in_use", "FALSE");
00391
00392
00393
00394
00395 if ((fp = KDE_fdopen(m_iSock, "w+")) == 0) {
00396 closeDescriptor();
00397 return false;
00398 }
00399
00400 return true;
00401 #else //!Q_OS_UNIX
00402 return false;
00403 #endif //Q_OS_UNIX
00404 }
00405
00406 void TCPSlaveBase::closeDescriptor()
00407 {
00408 stopTLS();
00409 if (fp) {
00410 fclose(fp);
00411 fp=0;
00412 m_iSock=-1;
00413 if (m_bIsSSL)
00414 d->kssl->close();
00415 }
00416 if (m_iSock != -1) {
00417 close(m_iSock);
00418 m_iSock=-1;
00419 }
00420 d->ip = "";
00421 d->host = "";
00422 }
00423
00424 bool TCPSlaveBase::initializeSSL()
00425 {
00426 if (m_bIsSSL) {
00427 if (KSSL::doesSSLWork()) {
00428 d->kssl = new KSSL;
00429 return true;
00430 }
00431 }
00432 return false;
00433 }
00434
00435 void TCPSlaveBase::cleanSSL()
00436 {
00437 delete d->cc;
00438
00439 if (m_bIsSSL) {
00440 delete d->kssl;
00441 d->kssl = 0;
00442 }
00443 d->militantSSL = false;
00444 }
00445
00446 bool TCPSlaveBase::atEnd()
00447 {
00448 return feof(fp);
00449 }
00450
00451 int TCPSlaveBase::startTLS()
00452 {
00453 if (d->usingTLS || d->useSSLTunneling || m_bIsSSL || !KSSL::doesSSLWork())
00454 return false;
00455
00456 d->kssl = new KSSL(false);
00457 if (!d->kssl->TLSInit()) {
00458 delete d->kssl;
00459 return -1;
00460 }
00461
00462 if ( !d->realHost.isEmpty() )
00463 {
00464 kdDebug(7029) << "Setting real hostname: " << d->realHost << endl;
00465 d->kssl->setPeerHost(d->realHost);
00466 } else {
00467 kdDebug(7029) << "Setting real hostname: " << d->host << endl;
00468 d->kssl->setPeerHost(d->host);
00469 }
00470
00471 if (hasMetaData("ssl_session_id")) {
00472 KSSLSession *s = KSSLSession::fromString(metaData("ssl_session_id"));
00473 if (s) {
00474 d->kssl->takeSession(s);
00475 delete s;
00476 }
00477 }
00478 certificatePrompt();
00479
00480 int rc = d->kssl->connect(m_iSock);
00481 if (rc < 0) {
00482 delete d->kssl;
00483 return -2;
00484 }
00485
00486 setMetaData("ssl_session_id", d->kssl->session()->toString());
00487
00488 d->usingTLS = true;
00489 setMetaData("ssl_in_use", "TRUE");
00490
00491 if (!d->kssl->reusingSession()) {
00492 rc = verifyCertificate();
00493 if (rc != 1) {
00494 setMetaData("ssl_in_use", "FALSE");
00495 d->usingTLS = false;
00496 delete d->kssl;
00497 return -3;
00498 }
00499 }
00500
00501 d->savedMetaData = mOutgoingMetaData;
00502 return (d->usingTLS ? 1 : 0);
00503 }
00504
00505
00506 void TCPSlaveBase::stopTLS()
00507 {
00508 if (d->usingTLS) {
00509 delete d->kssl;
00510 d->usingTLS = false;
00511 setMetaData("ssl_in_use", "FALSE");
00512 }
00513 }
00514
00515
00516 void TCPSlaveBase::setSSLMetaData() {
00517 if (!(d->usingTLS || d->useSSLTunneling || m_bIsSSL))
00518 return;
00519
00520 mOutgoingMetaData = d->savedMetaData;
00521 }
00522
00523
00524 bool TCPSlaveBase::canUseTLS()
00525 {
00526 if (m_bIsSSL || d->needSSLHandShake || !KSSL::doesSSLWork())
00527 return false;
00528
00529 KSSLSettings kss;
00530 return kss.tlsv1();
00531 }
00532
00533
00534 void TCPSlaveBase::certificatePrompt()
00535 {
00536 TQString certname;
00537 bool send = false, prompt = false, save = false, forcePrompt = false;
00538 KSSLCertificateHome::KSSLAuthAction aa;
00539
00540 setMetaData("ssl_using_client_cert", "FALSE");
00541
00542 if (metaData("ssl_no_client_cert") == "TRUE") return;
00543 forcePrompt = (metaData("ssl_force_cert_prompt") == "TRUE");
00544
00545
00546 if (d->pkcs) {
00547 delete d->pkcs;
00548 d->pkcs = NULL;
00549 }
00550
00551 if (!d->kssl) return;
00552
00553
00554 if (!forcePrompt) {
00555 certname = KSSLCertificateHome::getDefaultCertificateName(&aa);
00556 switch(aa) {
00557 case KSSLCertificateHome::AuthSend:
00558 send = true; prompt = false;
00559 break;
00560 case KSSLCertificateHome::AuthDont:
00561 send = false; prompt = false;
00562 certname = TQString::null;
00563 break;
00564 case KSSLCertificateHome::AuthPrompt:
00565 send = false; prompt = true;
00566 break;
00567 default:
00568 break;
00569 }
00570 }
00571
00572 TQString ourHost;
00573 if (!d->realHost.isEmpty()) {
00574 ourHost = d->realHost;
00575 } else {
00576 ourHost = d->host;
00577 }
00578
00579
00580 TQString tmpcn = KSSLCertificateHome::getDefaultCertificateName(ourHost, &aa);
00581 if (aa != KSSLCertificateHome::AuthNone) {
00582 switch (aa) {
00583 case KSSLCertificateHome::AuthSend:
00584 send = true;
00585 prompt = false;
00586 certname = tmpcn;
00587 break;
00588 case KSSLCertificateHome::AuthDont:
00589 send = false;
00590 prompt = false;
00591 certname = TQString::null;
00592 break;
00593 case KSSLCertificateHome::AuthPrompt:
00594 send = false;
00595 prompt = true;
00596 certname = tmpcn;
00597 break;
00598 default:
00599 break;
00600 }
00601 }
00602
00603
00604 if (hasMetaData("ssl_demand_certificate")) {
00605 certname = metaData("ssl_demand_certificate");
00606 if (!certname.isEmpty()) {
00607 forcePrompt = false;
00608 prompt = false;
00609 send = true;
00610 }
00611 }
00612
00613 if (certname.isEmpty() && !prompt && !forcePrompt) return;
00614
00615
00616 if (prompt || forcePrompt) {
00617 TQStringList certs = KSSLCertificateHome::getCertificateList();
00618
00619 for (TQStringList::Iterator it = certs.begin(); it != certs.end(); ++it) {
00620 KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(*it);
00621 if (pkcs && (!pkcs->getCertificate() ||
00622 !pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())) {
00623 certs.remove(*it);
00624 }
00625 delete pkcs;
00626 }
00627
00628 if (certs.isEmpty()) return;
00629
00630 if (!d->dcc) {
00631 d->dcc = new DCOPClient;
00632 d->dcc->attach();
00633 if (!d->dcc->isApplicationRegistered("tdeio_uiserver")) {
00634 TDEApplication::startServiceByDesktopPath("tdeio_uiserver.desktop",
00635 TQStringList() );
00636 }
00637 }
00638
00639 TQByteArray data, retval;
00640 TQCString rettype;
00641 TQDataStream arg(data, IO_WriteOnly);
00642 arg << ourHost;
00643 arg << certs;
00644 arg << metaData("window-id").toInt();
00645 bool rc = d->dcc->call("tdeio_uiserver", "UIServer",
00646 "showSSLCertDialog(TQString, TQStringList,int)",
00647 data, rettype, retval);
00648
00649 if (rc && rettype == "KSSLCertDlgRet") {
00650 TQDataStream retStream(retval, IO_ReadOnly);
00651 KSSLCertDlgRet drc;
00652 retStream >> drc;
00653 if (drc.ok) {
00654 send = drc.send;
00655 save = drc.save;
00656 certname = drc.choice;
00657 }
00658 }
00659 }
00660
00661
00662
00663 if (!send) {
00664 if (save) {
00665 KSSLCertificateHome::setDefaultCertificate(certname, ourHost,
00666 false, false);
00667 }
00668 return;
00669 }
00670
00671
00672 KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(certname);
00673 if (!pkcs && KSSLCertificateHome::hasCertificateByName(certname)) {
00674 TDEIO::AuthInfo ai;
00675 bool first = true;
00676 do {
00677 ai.prompt = i18n("Enter the certificate password:");
00678 ai.caption = i18n("SSL Certificate Password");
00679 ai.url.setProtocol("kssl");
00680 ai.url.setHost(certname);
00681 ai.username = certname;
00682 ai.keepPassword = true;
00683
00684 bool showprompt;
00685 if (first)
00686 showprompt = !checkCachedAuthentication(ai);
00687 else
00688 showprompt = true;
00689 if (showprompt) {
00690 if (!openPassDlg(ai, first ? TQString::null :
00691 i18n("Unable to open the certificate. Try a new password?")))
00692 break;
00693 }
00694
00695 first = false;
00696 pkcs = KSSLCertificateHome::getCertificateByName(certname, ai.password);
00697 } while (!pkcs);
00698
00699 }
00700
00701
00702 if (pkcs) {
00703 if (!d->kssl->setClientCertificate(pkcs)) {
00704 messageBox(Information, i18n("The procedure to set the "
00705 "client certificate for the session "
00706 "failed."), i18n("SSL"));
00707 delete pkcs;
00708 pkcs = 0L;
00709 } else {
00710 kdDebug(7029) << "Client SSL certificate is being used." << endl;
00711 setMetaData("ssl_using_client_cert", "TRUE");
00712 if (save) {
00713 KSSLCertificateHome::setDefaultCertificate(certname, ourHost,
00714 true, false);
00715 }
00716 }
00717 d->pkcs = pkcs;
00718 }
00719 }
00720
00721
00722
00723 bool TCPSlaveBase::usingTLS() const
00724 {
00725 return d->usingTLS;
00726 }
00727
00728
00729 bool TCPSlaveBase::usingTLS()
00730 {
00731 return d->usingTLS;
00732 }
00733
00734
00735
00736 int TCPSlaveBase::verifyCertificate()
00737 {
00738 int rc = 0;
00739 bool permacache = false;
00740 bool isChild = false;
00741 bool _IPmatchesCN = false;
00742 int result;
00743 bool doAddHost = false;
00744 TQString ourHost;
00745
00746 if (!d->realHost.isEmpty())
00747 ourHost = d->realHost;
00748 else ourHost = d->host;
00749
00750 TQString theurl = TQString(m_sServiceName)+"://"+ourHost+":"+TQString::number(m_iPort);
00751
00752 if (!hasMetaData("ssl_militant") || metaData("ssl_militant") == "FALSE")
00753 d->militantSSL = false;
00754 else if (metaData("ssl_militant") == "TRUE")
00755 d->militantSSL = true;
00756
00757 if (!d->cc) d->cc = new KSSLCertificateCache;
00758
00759 KSSLCertificate& pc = d->kssl->peerInfo().getPeerCertificate();
00760
00761 KSSLCertificate::KSSLValidationList ksvl = pc.validateVerbose(KSSLCertificate::SSLServer);
00762
00763 _IPmatchesCN = d->kssl->peerInfo().certMatchesAddress();
00764 if (!_IPmatchesCN) {
00765 #ifndef Q_WS_WIN //temporary
00766 KNetwork::KResolverResults res = KNetwork::KResolver::resolve(d->kssl->peerInfo().peerHost(), "80", KNetwork::KResolver::CanonName);
00767 if (!res.isEmpty()) {
00768 TQString old = d->kssl->peerInfo().peerHost();
00769 d->kssl->peerInfo().setPeerHost(res[0].canonicalName());
00770 _IPmatchesCN = d->kssl->peerInfo().certMatchesAddress();
00771 if (!_IPmatchesCN) {
00772 d->kssl->peerInfo().setPeerHost(old);
00773 }
00774 }
00775 #endif
00776 if (!_IPmatchesCN && !d->militantSSL) {
00777 if (d->cc->getHostList(pc).contains(ourHost)) {
00778 _IPmatchesCN = true;
00779 }
00780 }
00781 }
00782
00783 if (!_IPmatchesCN) {
00784 ksvl << KSSLCertificate::InvalidHost;
00785 }
00786
00787 KSSLCertificate::KSSLValidation ksv = KSSLCertificate::Ok;
00788 if (!ksvl.isEmpty())
00789 ksv = ksvl.first();
00790
00791
00792 setMetaData("ssl_cipher", d->kssl->connectionInfo().getCipher());
00793 setMetaData("ssl_cipher_desc",
00794 d->kssl->connectionInfo().getCipherDescription());
00795 setMetaData("ssl_cipher_version",
00796 d->kssl->connectionInfo().getCipherVersion());
00797 setMetaData("ssl_cipher_used_bits",
00798 TQString::number(d->kssl->connectionInfo().getCipherUsedBits()));
00799 setMetaData("ssl_cipher_bits",
00800 TQString::number(d->kssl->connectionInfo().getCipherBits()));
00801 setMetaData("ssl_peer_ip", d->ip);
00802 if (!d->realHost.isEmpty()) {
00803 setMetaData("ssl_proxied", "true");
00804 }
00805
00806 TQString errorStr;
00807 for(KSSLCertificate::KSSLValidationList::ConstIterator it = ksvl.begin();
00808 it != ksvl.end(); ++it)
00809 {
00810 errorStr += TQString::number(*it)+":";
00811 }
00812 setMetaData("ssl_cert_errors", errorStr);
00813 setMetaData("ssl_peer_certificate", pc.toString());
00814
00815 if (pc.chain().isValid() && pc.chain().depth() > 1) {
00816 TQString theChain;
00817 TQPtrList<KSSLCertificate> chain = pc.chain().getChain();
00818 chain.setAutoDelete(true);
00819 for (KSSLCertificate *c = chain.first(); c; c = chain.next()) {
00820 theChain += c->toString();
00821 theChain += "\n";
00822 }
00823 setMetaData("ssl_peer_chain", theChain);
00824 } else setMetaData("ssl_peer_chain", "");
00825
00826 setMetaData("ssl_cert_state", TQString::number(ksv));
00827
00828 if (ksv == KSSLCertificate::Ok) {
00829 rc = 1;
00830 setMetaData("ssl_action", "accept");
00831 }
00832
00833 kdDebug(7029) << "SSL HTTP frame the parent? " << metaData("main_frame_request") << endl;
00834 if (!hasMetaData("main_frame_request") || metaData("main_frame_request") == "TRUE") {
00835
00836 setMetaData("ssl_parent_ip", d->ip);
00837 setMetaData("ssl_parent_cert", pc.toString());
00838
00839 KSSLCertificateCache::KSSLCertificatePolicy cp =
00840 d->cc->getPolicyByCertificate(pc);
00841
00842
00843 if (ksv != KSSLCertificate::Ok) {
00844 if (d->militantSSL) {
00845 return -1;
00846 }
00847
00848 if (cp == KSSLCertificateCache::Unknown ||
00849 cp == KSSLCertificateCache::Ambiguous) {
00850 cp = KSSLCertificateCache::Prompt;
00851 } else {
00852
00853 permacache = d->cc->isPermanent(pc);
00854 }
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864 switch (cp) {
00865 case KSSLCertificateCache::Accept:
00866 rc = 1;
00867 setMetaData("ssl_action", "accept");
00868 break;
00869 case KSSLCertificateCache::Reject:
00870 rc = -1;
00871 setMetaData("ssl_action", "reject");
00872 break;
00873 case KSSLCertificateCache::Prompt:
00874 {
00875 do {
00876 if (ksv == KSSLCertificate::InvalidHost) {
00877 TQString msg = i18n("The IP address of the host %1 "
00878 "does not match the one the "
00879 "certificate was issued to.");
00880 result = messageBox( WarningYesNoCancel,
00881 msg.arg(ourHost),
00882 i18n("Server Authentication"),
00883 i18n("&Details"),
00884 i18n("Co&ntinue") );
00885 } else {
00886 TQString msg = i18n("The server certificate failed the "
00887 "authenticity test (%1).");
00888 result = messageBox( WarningYesNoCancel,
00889 msg.arg(ourHost),
00890 i18n("Server Authentication"),
00891 i18n("&Details"),
00892 i18n("Co&ntinue") );
00893 }
00894
00895 if (result == KMessageBox::Yes) {
00896 if (!d->dcc) {
00897 d->dcc = new DCOPClient;
00898 d->dcc->attach();
00899 if (!d->dcc->isApplicationRegistered("tdeio_uiserver")) {
00900 TDEApplication::startServiceByDesktopPath("tdeio_uiserver.desktop",
00901 TQStringList() );
00902 }
00903
00904 }
00905 TQByteArray data, ignore;
00906 TQCString ignoretype;
00907 TQDataStream arg(data, IO_WriteOnly);
00908 arg << theurl << mOutgoingMetaData;
00909 arg << metaData("window-id").toInt();
00910 d->dcc->call("tdeio_uiserver", "UIServer",
00911 "showSSLInfoDialog(TQString,TDEIO::MetaData,int)",
00912 data, ignoretype, ignore);
00913 }
00914 } while (result == KMessageBox::Yes);
00915
00916 if (result == KMessageBox::No) {
00917 setMetaData("ssl_action", "accept");
00918 rc = 1;
00919 cp = KSSLCertificateCache::Accept;
00920 doAddHost = true;
00921 result = messageBox( WarningYesNo,
00922 i18n("Would you like to accept this "
00923 "certificate forever without "
00924 "being prompted?"),
00925 i18n("Server Authentication"),
00926 i18n("&Forever"),
00927 i18n("&Current Sessions Only"));
00928 if (result == KMessageBox::Yes)
00929 permacache = true;
00930 else
00931 permacache = false;
00932 } else {
00933 setMetaData("ssl_action", "reject");
00934 rc = -1;
00935 cp = KSSLCertificateCache::Prompt;
00936 }
00937 break;
00938 }
00939 default:
00940 kdDebug(7029) << "TCPSlaveBase/SSL error in cert code."
00941 << "Please report this to kfm-devel@kde.org."
00942 << endl;
00943 break;
00944 }
00945 }
00946
00947
00948
00949 d->cc->addCertificate(pc, cp, permacache);
00950 if (doAddHost) d->cc->addHost(pc, ourHost);
00951 } else {
00952
00953 KSSLCertificateCache::KSSLCertificatePolicy cp =
00954 d->cc->getPolicyByCertificate(pc);
00955 isChild = true;
00956
00957
00958
00959 bool certAndIPTheSame = (d->ip == metaData("ssl_parent_ip") &&
00960 pc.toString() == metaData("ssl_parent_cert"));
00961
00962 if (ksv == KSSLCertificate::Ok) {
00963 if (certAndIPTheSame) {
00964 rc = 1;
00965 setMetaData("ssl_action", "accept");
00966 } else {
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 setMetaData("ssl_action", "accept");
00983 rc = 1;
00984
00985
00986 }
00987 } else {
00988 if (d->militantSSL) {
00989 return -1;
00990 }
00991
00992 if (cp == KSSLCertificateCache::Accept) {
00993 if (certAndIPTheSame) {
00994 rc = 1;
00995 setMetaData("ssl_action", "accept");
00996 } else {
00997 result = messageBox(WarningYesNo,
00998 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?"),
00999 i18n("Server Authentication"));
01000 if (result == KMessageBox::Yes) {
01001 rc = 1;
01002 setMetaData("ssl_action", "accept");
01003 d->cc->addHost(pc, ourHost);
01004 } else {
01005 rc = -1;
01006 setMetaData("ssl_action", "reject");
01007 }
01008 }
01009 } else if (cp == KSSLCertificateCache::Reject) {
01010 messageBox(Information, i18n("SSL certificate is being rejected as requested. You can disable this in the Trinity Control Center."),
01011 i18n("Server Authentication"));
01012 rc = -1;
01013 setMetaData("ssl_action", "reject");
01014 } else {
01015 do {
01016 TQString msg = i18n("The server certificate failed the "
01017 "authenticity test (%1).");
01018 result = messageBox(WarningYesNoCancel,
01019 msg.arg(ourHost),
01020 i18n("Server Authentication"),
01021 i18n("&Details"),
01022 i18n("Co&nnect"));
01023 if (result == KMessageBox::Yes) {
01024 if (!d->dcc) {
01025 d->dcc = new DCOPClient;
01026 d->dcc->attach();
01027 if (!d->dcc->isApplicationRegistered("tdeio_uiserver")) {
01028 TDEApplication::startServiceByDesktopPath("tdeio_uiserver.desktop",
01029 TQStringList() );
01030 }
01031 }
01032 TQByteArray data, ignore;
01033 TQCString ignoretype;
01034 TQDataStream arg(data, IO_WriteOnly);
01035 arg << theurl << mOutgoingMetaData;
01036 arg << metaData("window-id").toInt();
01037 d->dcc->call("tdeio_uiserver", "UIServer",
01038 "showSSLInfoDialog(TQString,TDEIO::MetaData,int)",
01039 data, ignoretype, ignore);
01040 }
01041 } while (result == KMessageBox::Yes);
01042
01043 if (result == KMessageBox::No) {
01044 setMetaData("ssl_action", "accept");
01045 rc = 1;
01046 cp = KSSLCertificateCache::Accept;
01047 result = messageBox(WarningYesNo,
01048 i18n("Would you like to accept this "
01049 "certificate forever without "
01050 "being prompted?"),
01051 i18n("Server Authentication"),
01052 i18n("&Forever"),
01053 i18n("&Current Sessions Only"));
01054 permacache = (result == KMessageBox::Yes);
01055 d->cc->addCertificate(pc, cp, permacache);
01056 d->cc->addHost(pc, ourHost);
01057 } else {
01058 setMetaData("ssl_action", "reject");
01059 rc = -1;
01060 cp = KSSLCertificateCache::Prompt;
01061 d->cc->addCertificate(pc, cp, permacache);
01062 }
01063 }
01064 }
01065 }
01066
01067
01068 if (rc == -1) {
01069 return rc;
01070 }
01071
01072 if (metaData("ssl_activate_warnings") == "TRUE") {
01073
01074 if (!isChild && metaData("ssl_was_in_use") == "FALSE" &&
01075 d->kssl->settings()->warnOnEnter()) {
01076 int result;
01077 do {
01078 result = messageBox( i18n("You are about to "
01079 "enter secure mode. "
01080 "All transmissions "
01081 "will be encrypted "
01082 "unless otherwise "
01083 "noted.\nThis means "
01084 "that no third party "
01085 "will be able to "
01086 "easily observe your "
01087 "data in transit."),
01088 WarningYesNo,
01089 i18n("Security Information"),
01090 i18n("Display SSL "
01091 "&Information"),
01092 i18n("C&onnect"),
01093 "WarnOnEnterSSLMode" );
01094
01095 TDEConfig *config = new TDEConfig("tdeioslaverc");
01096 config->setGroup("Notification Messages");
01097
01098 bool dialogBoxStatus = false;
01099 if( config->hasKey("WarnOnEnterSSLMode") ) {
01100 dialogBoxStatus = true;
01101 }
01102 bool keyStatus = config->readBoolEntry("WarnOnEnterSSLMode", true);
01103 dialogBoxStatus = dialogBoxStatus && keyStatus;
01104 if (!keyStatus) {
01105 config->deleteEntry("WarnOnEnterSSLMode");
01106 config->sync();
01107 d->kssl->settings()->setWarnOnEnter(false);
01108 d->kssl->settings()->save();
01109 }
01110 delete config;
01111
01112 if ( result == KMessageBox::Yes )
01113 {
01114 if (!d->dcc) {
01115 d->dcc = new DCOPClient;
01116 d->dcc->attach();
01117 if (!d->dcc->isApplicationRegistered("tdeio_uiserver")) {
01118 TDEApplication::startServiceByDesktopPath("tdeio_uiserver.desktop",
01119 TQStringList() );
01120 }
01121 }
01122 TQByteArray data, ignore;
01123 TQCString ignoretype;
01124 TQDataStream arg(data, IO_WriteOnly);
01125 arg << theurl << mOutgoingMetaData;
01126 arg << metaData("window-id").toInt();
01127 d->dcc->call("tdeio_uiserver", "UIServer",
01128 "showSSLInfoDialog(TQString,TDEIO::MetaData,int)",
01129 data, ignoretype, ignore);
01130 }
01131
01132 if(dialogBoxStatus) {
01133 break;
01134 }
01135 } while (result != KMessageBox::No);
01136 }
01137
01138 }
01139
01140
01141 kdDebug(7029) << "SSL connection information follows:" << endl
01142 << "+-----------------------------------------------" << endl
01143 << "| Cipher: " << d->kssl->connectionInfo().getCipher() << endl
01144 << "| Description: " << d->kssl->connectionInfo().getCipherDescription() << endl
01145 << "| Version: " << d->kssl->connectionInfo().getCipherVersion() << endl
01146 << "| Strength: " << d->kssl->connectionInfo().getCipherUsedBits()
01147 << " of " << d->kssl->connectionInfo().getCipherBits()
01148 << " bits used." << endl
01149 << "| PEER:" << endl
01150 << "| Subject: " << d->kssl->peerInfo().getPeerCertificate().getSubject() << endl
01151 << "| Issuer: " << d->kssl->peerInfo().getPeerCertificate().getIssuer() << endl
01152 << "| Validation: " << (int)ksv << endl
01153 << "| Certificate matches IP: " << _IPmatchesCN << endl
01154 << "+-----------------------------------------------"
01155 << endl;
01156
01157
01158 return rc;
01159 }
01160
01161
01162 bool TCPSlaveBase::isConnectionValid()
01163 {
01164 if ( m_iSock == -1 )
01165 return false;
01166
01167 fd_set rdfs;
01168 FD_ZERO(&rdfs);
01169 FD_SET(m_iSock , &rdfs);
01170
01171 struct timeval tv;
01172 tv.tv_usec = 0;
01173 tv.tv_sec = 0;
01174 int retval;
01175 #ifdef Q_OS_UNIX
01176 do {
01177 retval = KSocks::self()->select(m_iSock+1, &rdfs, NULL, NULL, &tv);
01178 if (wasKilled())
01179 return false;
01180 } while ((retval == -1) && (errno == EAGAIN));
01181 #else
01182 retval = -1;
01183 #endif
01184
01185
01186
01187
01188
01189
01190 if (retval == -1)
01191 return false;
01192
01193 if (retval == 0)
01194 return true;
01195
01196
01197 char buffer[100];
01198 #ifdef Q_OS_UNIX
01199 do {
01200 retval = KSocks::self()->recv(m_iSock, buffer, 80, MSG_PEEK);
01201
01202 } while ((retval == -1) && (errno == EAGAIN));
01203 #else
01204 retval = -1;
01205 #endif
01206
01207
01208 if (retval <= 0)
01209 return false;
01210
01211 return true;
01212 }
01213
01214
01215 bool TCPSlaveBase::waitForResponse( int t )
01216 {
01217 fd_set rd;
01218 struct timeval timeout;
01219
01220 if ( (m_bIsSSL || d->usingTLS) && !d->useSSLTunneling && d->kssl )
01221 if (d->kssl->pending() > 0)
01222 return true;
01223
01224 FD_ZERO(&rd);
01225 FD_SET(m_iSock, &rd);
01226
01227 timeout.tv_usec = 0;
01228 timeout.tv_sec = t;
01229 time_t startTime;
01230
01231 int rc;
01232 int n = t;
01233
01234 reSelect:
01235 startTime = time(NULL);
01236 #ifdef Q_OS_UNIX
01237 rc = KSocks::self()->select(m_iSock+1, &rd, NULL, NULL, &timeout);
01238 #else
01239 rc = -1;
01240 #endif
01241 if (wasKilled())
01242 return false;
01243
01244 if (rc == -1)
01245 return false;
01246
01247 if (FD_ISSET(m_iSock, &rd))
01248 return true;
01249
01250
01251
01252
01253 int timeDone = time(NULL) - startTime;
01254 if (timeDone < n)
01255 {
01256 n -= timeDone;
01257 timeout.tv_sec = n;
01258 goto reSelect;
01259 }
01260
01261 return false;
01262 }
01263
01264 int TCPSlaveBase::connectResult()
01265 {
01266 return d->status;
01267 }
01268
01269 void TCPSlaveBase::setBlockConnection( bool b )
01270 {
01271 d->block = b;
01272 }
01273
01274 void TCPSlaveBase::setConnectTimeout( int t )
01275 {
01276 d->timeout = t;
01277 }
01278
01279 bool TCPSlaveBase::isSSLTunnelEnabled()
01280 {
01281 return d->useSSLTunneling;
01282 }
01283
01284 void TCPSlaveBase::setEnableSSLTunnel( bool enable )
01285 {
01286 d->useSSLTunneling = enable;
01287 }
01288
01289 void TCPSlaveBase::setRealHost( const TQString& realHost )
01290 {
01291 d->realHost = realHost;
01292 }
01293
01294 bool TCPSlaveBase::doSSLHandShake( bool sendError )
01295 {
01296 kdDebug(7029) << "TCPSlaveBase::doSSLHandShake: " << endl;
01297 TQString msgHost = d->host;
01298
01299 d->kssl->reInitialize();
01300
01301 if (hasMetaData("ssl_session_id")) {
01302 KSSLSession *s = KSSLSession::fromString(metaData("ssl_session_id"));
01303 if (s) {
01304 d->kssl->takeSession(s);
01305 delete s;
01306 }
01307 }
01308 certificatePrompt();
01309
01310 if ( !d->realHost.isEmpty() )
01311 {
01312 msgHost = d->realHost;
01313 }
01314
01315 kdDebug(7029) << "Setting real hostname: " << msgHost << endl;
01316 d->kssl->setPeerHost(msgHost);
01317
01318 d->status = d->kssl->connect(m_iSock);
01319 if (d->status < 0)
01320 {
01321 closeDescriptor();
01322 if ( sendError )
01323 error( ERR_COULD_NOT_CONNECT, msgHost);
01324 return false;
01325 }
01326
01327 setMetaData("ssl_session_id", d->kssl->session()->toString());
01328 setMetaData("ssl_in_use", "TRUE");
01329
01330 if (!d->kssl->reusingSession()) {
01331 int rc = verifyCertificate();
01332 if ( rc != 1 ) {
01333 d->status = -1;
01334 closeDescriptor();
01335 if ( sendError )
01336 error( ERR_COULD_NOT_CONNECT, msgHost);
01337 return false;
01338 }
01339 }
01340
01341 d->needSSLHandShake = false;
01342
01343 d->savedMetaData = mOutgoingMetaData;
01344 return true;
01345 }
01346
01347
01348 bool TCPSlaveBase::userAborted() const
01349 {
01350 return d->userAborted;
01351 }
01352
01353 void TCPSlaveBase::virtual_hook( int id, void* data )
01354 { SlaveBase::virtual_hook( id, data ); }
01355