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 + -
显示快捷键?