tcpslavebase.cpp
来自「konqueror3 embedded版本, KDE环境下的当家浏览器的嵌入式版」· C++ 代码 · 共 1,342 行 · 第 1/3 页
CPP
1,342 行
}int TCPSlaveBase::startTLS(){ if (d->usingTLS || d->useSSLTunneling || m_bIsSSL || !KSSL::doesSSLWork()) return false; d->kssl = new KSSL(false); if (!d->kssl->TLSInit()) { delete d->kssl; return -1; } if ( !d->realHost.isEmpty() ) { kdDebug(7029) << "Setting real hostname: " << d->realHost << endl; d->kssl->setPeerHost(d->realHost); } else { kdDebug(7029) << "Setting real hostname: " << d->host << endl; d->kssl->setPeerHost(d->host); } if (hasMetaData("ssl_session_id")) { KSSLSession *s = KSSLSession::fromString(metaData("ssl_session_id")); if (s) { d->kssl->setSession(s); delete s; } } certificatePrompt(); int rc = d->kssl->connect(m_iSock); if (rc < 0) { delete d->kssl; return -2; } setMetaData("ssl_session_id", d->kssl->session()->toString()); d->usingTLS = true; setMetaData("ssl_in_use", "TRUE"); if (!d->kssl->reusingSession()) { rc = verifyCertificate(); if (rc != 1) { setMetaData("ssl_in_use", "FALSE"); d->usingTLS = false; delete d->kssl; return -3; } } d->savedMetaData = mOutgoingMetaData; return (d->usingTLS ? 1 : 0);}void TCPSlaveBase::stopTLS(){ if (d->usingTLS) { delete d->kssl; d->usingTLS = false; setMetaData("ssl_in_use", "FALSE"); }}void TCPSlaveBase::setSSLMetaData() { if (!(d->usingTLS || d->useSSLTunneling || m_bIsSSL)) return; mOutgoingMetaData = d->savedMetaData;}bool TCPSlaveBase::canUseTLS(){ if (m_bIsSSL || d->needSSLHandShake || !KSSL::doesSSLWork()) return false; KSSLSettings kss; return kss.tlsv1();}void TCPSlaveBase::certificatePrompt(){QString certname; // the cert to use this sessionbool send = false, prompt = false, save = false, forcePrompt = false;KSSLCertificateHome::KSSLAuthAction aa; setMetaData("ssl_using_client_cert", "FALSE"); // we change this if needed if (metaData("ssl_no_client_cert") == "TRUE") return; forcePrompt = (metaData("ssl_force_cert_prompt") == "TRUE"); // Delete the old cert since we're certainly done with it now if (d->pkcs) { delete d->pkcs; d->pkcs = NULL; } if (!d->kssl) return; // Look for a general certificate if (!forcePrompt) { certname = KSSLCertificateHome::getDefaultCertificateName(&aa); switch(aa) { case KSSLCertificateHome::AuthSend: send = true; prompt = false; break; case KSSLCertificateHome::AuthDont: send = false; prompt = false; certname = QString::null; break; case KSSLCertificateHome::AuthPrompt: send = false; prompt = true; break; default: break; } } QString ourHost; if (!d->realHost.isEmpty()) { ourHost = d->realHost; } else { ourHost = d->host; } // Look for a certificate on a per-host basis as an override QString tmpcn = KSSLCertificateHome::getDefaultCertificateName(ourHost, &aa); if (aa != KSSLCertificateHome::AuthNone) { // we must override switch (aa) { case KSSLCertificateHome::AuthSend: send = true; prompt = false; certname = tmpcn; break; case KSSLCertificateHome::AuthDont: send = false; prompt = false; certname = QString::null; break; case KSSLCertificateHome::AuthPrompt: send = false; prompt = true; certname = tmpcn; break; default: break; } } // Finally, we allow the application to override anything. if (hasMetaData("ssl_demand_certificate")) { certname = metaData("ssl_demand_certificate"); if (!certname.isEmpty()) { forcePrompt = false; prompt = false; send = true; } } if (certname.isEmpty() && !prompt && !forcePrompt) return; // Ok, we're supposed to prompt the user.... if (prompt || forcePrompt) { QStringList certs = KSSLCertificateHome::getCertificateList(); for (QStringList::Iterator it = certs.begin(); it != certs.end(); ++it) { KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(*it); if (pkcs && (!pkcs->getCertificate() || !pkcs->getCertificate()->x509V3Extensions().certTypeSSLClient())) { certs.remove(*it); } } if (certs.isEmpty()) return; // we had nothing else, and prompt failed if (!d->dcc) { d->dcc = new DCOPClient; d->dcc->attach(); if (!d->dcc->isApplicationRegistered("kio_uiserver")) { KApplication::startServiceByDesktopPath("kio_uiserver.desktop", QStringList() ); } } QByteArray data, retval; QCString rettype; QDataStream arg(data, IO_WriteOnly); arg << ourHost; arg << certs; arg << metaData("window-id").toInt(); bool rc = d->dcc->call("kio_uiserver", "UIServer", "showSSLCertDialog(QString, QStringList,int)", data, rettype, retval); if (rc && rettype == "KSSLCertDlgRet") { QDataStream retStream(retval, IO_ReadOnly); KSSLCertDlgRet drc; retStream >> drc; if (drc.ok) { send = drc.send; save = drc.save; certname = drc.choice; } } } // The user may have said to not send the certificate, // but to save the choice if (!send) { if (save) { KSSLCertificateHome::setDefaultCertificate(certname, ourHost, false, false); } return; } // We're almost committed. If we can read the cert, we'll send it now. KSSLPKCS12 *pkcs = KSSLCertificateHome::getCertificateByName(certname); if (!pkcs && KSSLCertificateHome::hasCertificateByName(certname)) { // We need the password KIO::AuthInfo ai; bool first = true; do { ai.prompt = i18n("Enter the certificate password:"); ai.caption = i18n("SSL Certificate Password"); ai.url.setProtocol("kssl"); ai.url.setHost(certname); ai.username = certname; ai.keepPassword = true; bool showprompt; if (first) showprompt = !checkCachedAuthentication(ai); else showprompt = true; if (showprompt) { if (!openPassDlg(ai, first ? QString::null : i18n("Unable to open the certificate. Try a new password?"))) break; } first = false; pkcs = KSSLCertificateHome::getCertificateByName(certname, ai.password); } while (!pkcs); } // If we could open the certificate, let's send it if (pkcs) { if (!d->kssl->setClientCertificate(pkcs)) { messageBox(Information, i18n("The procedure to set the " "client certificate for the session " "failed."), i18n("SSL")); delete pkcs; // we don't need this anymore pkcs = 0L; } else { kdDebug(7029) << "Client SSL certificate is being used." << endl; setMetaData("ssl_using_client_cert", "TRUE"); if (save) { KSSLCertificateHome::setDefaultCertificate(certname, ourHost, true, false); } } d->pkcs = pkcs; }}bool TCPSlaveBase::usingTLS() const{ return d->usingTLS;}// ### remove this for KDE4 (misses const):bool TCPSlaveBase::usingTLS(){ return d->usingTLS;}// Returns 0 for failed verification, -1 for rejected cert and 1 for okint TCPSlaveBase::verifyCertificate(){ int rc = 0; bool permacache = false; bool isChild = false; bool _IPmatchesCN = false; int result; bool doAddHost = false; QString ourHost; if (!d->realHost.isEmpty()) ourHost = d->realHost; else ourHost = d->host; QString theurl = QString(m_sServiceName)+"://"+ourHost+":"+QString::number(m_iPort); if (!hasMetaData("ssl_militant") || metaData("ssl_militant") == "FALSE") d->militantSSL = false; else if (metaData("ssl_militant") == "TRUE") d->militantSSL = true; if (!d->cc) d->cc = new KSSLCertificateCache; KSSLCertificate& pc = d->kssl->peerInfo().getPeerCertificate(); KSSLCertificate::KSSLValidationList ksvl = pc.validateVerbose(KSSLCertificate::SSLServer); _IPmatchesCN = d->kssl->peerInfo().certMatchesAddress(); if (!_IPmatchesCN) {#ifndef Q_WS_WIN //temporary KNetwork::KResolverResults res = KNetwork::KResolver::resolve(d->kssl->peerInfo().peerHost(), "80", KNetwork::KResolver::CanonName); if (!res.isEmpty()) { QString old = d->kssl->peerInfo().peerHost(); d->kssl->peerInfo().setPeerHost(res[0].canonicalName()); _IPmatchesCN = d->kssl->peerInfo().certMatchesAddress(); if (!_IPmatchesCN) { d->kssl->peerInfo().setPeerHost(old); } }#endif if (!_IPmatchesCN && !d->militantSSL) { // force this if the user wants it if (d->cc->getHostList(pc).contains(ourHost)) { _IPmatchesCN = true; } } } if (!_IPmatchesCN) { ksvl << KSSLCertificate::InvalidHost; } KSSLCertificate::KSSLValidation ksv = KSSLCertificate::Ok; if (!ksvl.isEmpty()) ksv = ksvl.first(); /* Setting the various bits of meta-info that will be needed. */ setMetaData("ssl_cipher", d->kssl->connectionInfo().getCipher()); setMetaData("ssl_cipher_desc", d->kssl->connectionInfo().getCipherDescription()); setMetaData("ssl_cipher_version", d->kssl->connectionInfo().getCipherVersion()); setMetaData("ssl_cipher_used_bits", QString::number(d->kssl->connectionInfo().getCipherUsedBits())); setMetaData("ssl_cipher_bits", QString::number(d->kssl->connectionInfo().getCipherBits())); setMetaData("ssl_peer_ip", d->ip); if (!d->realHost.isEmpty()) { setMetaData("ssl_proxied", "true"); } QString errorStr; for(KSSLCertificate::KSSLValidationList::ConstIterator it = ksvl.begin(); it != ksvl.end(); ++it) { errorStr += QString::number(*it)+":"; } setMetaData("ssl_cert_errors", errorStr); setMetaData("ssl_peer_certificate", pc.toString()); if (pc.chain().isValid() && pc.chain().depth() > 1) { QString theChain; QPtrList<KSSLCertificate> chain = pc.chain().getChain(); for (KSSLCertificate *c = chain.first(); c; c = chain.next()) { theChain += c->toString(); theChain += "\n"; } setMetaData("ssl_peer_chain", theChain); } else setMetaData("ssl_peer_chain", ""); setMetaData("ssl_cert_state", QString::number(ksv)); if (ksv == KSSLCertificate::Ok) { rc = 1; setMetaData("ssl_action", "accept"); } kdDebug(7029) << "SSL HTTP frame the parent? " << metaData("main_frame_request") << endl; if (!hasMetaData("main_frame_request") || metaData("main_frame_request") == "TRUE") { // Since we're the parent, we need to teach the child. setMetaData("ssl_parent_ip", d->ip); setMetaData("ssl_parent_cert", pc.toString()); // - Read from cache and see if there is a policy for this KSSLCertificateCache::KSSLCertificatePolicy cp = d->cc->getPolicyByCertificate(pc); // - validation code if (ksv != KSSLCertificate::Ok) { if (d->militantSSL) { return -1; } if (cp == KSSLCertificateCache::Unknown || cp == KSSLCertificateCache::Ambiguous) { cp = KSSLCertificateCache::Prompt; } else { // A policy was already set so let's honor that. permacache = d->cc->isPermanent(pc); } if (!_IPmatchesCN && cp == KSSLCertificateCache::Accept) { cp = KSSLCertificateCache::Prompt;// ksv = KSSLCertificate::Ok; } // Precondition: cp is one of Reject, Accept or Prompt switch (cp) { case KSSLCertificateCache::Accept: rc = 1; setMetaData("ssl_action", "accept"); break; case KSSLCertificateCache::Reject: rc = -1; setMetaData("ssl_action", "reject"); break; case KSSLCertificateCache::Prompt: { do { if (ksv == KSSLCertificate::InvalidHost) { QString msg = i18n("The IP address of the host %1 " "does not match the one the " "certificate was issued to."); result = messageBox( WarningYesNoCancel, msg.arg(ourHost), i18n("Server Authentication"), i18n("&Details"), i18n("Co&ntinue") ); } else { QString msg = i18n("The server certificate failed the " "authenticity test (%1)."); result = messageBox( WarningYesNoCancel, msg.arg(ourHost), i18n("Server Authentication"), i18n("&Details"), i18n("Co&ntinue") ); } if (result == KMessageBox::Yes) { if (!d->dcc) { d->dcc = new DCOPClient; d->dcc->attach(); if (!d->dcc->isApplicationRegistered("kio_uiserver")) { KApplication::startServiceByDesktopPath("kio_uiserver.desktop",
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?