bool FvUpdater::checkSslFingerPrint(QUrl urltoCheck) { if(urltoCheck.scheme()!="https") { qWarning()<<tr("SSL fingerprint check: The url %1 is not a ssl connection!").arg(urltoCheck.toString()); return false; } QSslSocket *socket = new QSslSocket(this); socket->connectToHostEncrypted(urltoCheck.host(), 443); if( !socket->waitForEncrypted(1000)) // waits until ssl emits encrypted(), max 1000msecs { qWarning()<<"SSL fingerprint check: Unable to connect SSL server: "<<socket->sslErrors(); return false; } QSslCertificate cert = socket->peerCertificate(); if(cert.isNull()) { qWarning()<<"SSL fingerprint check: Unable to retrieve SSL server certificate."; return false; } // COmpare digests if(cert.digest().toHex() != m_requiredSslFingerprint) { qWarning()<<"SSL fingerprint check: FINGERPRINT MISMATCH! Server digest="<<cert.digest().toHex()<<", requiered ssl digest="<<m_requiredSslFingerprint; return false; } return true; }
void SslCertificateMonitor::socketReady(QObject *sockobj) { QSslSocket *sock = qobject_cast<QSslSocket *>(sockobj); if (!sock) return; QString peerName = sock->peerName(); QSslCertificate certificate = sock->peerCertificate(); if (*(d->acceptedCache.object(peerName)) == certificate) return; // Fast path for most recently accepted certificates // Have we been here before? QSslCertificate previousCertificate = cachedCertificate(peerName); if (!previousCertificate.isNull()) { if (certificate == previousCertificate) { // We need to add the certificate to the cache here as well as when we add to // the on-disk cache so that we don't hit the disk again for this site. d->acceptedCache.insert(peerName,new QSslCertificate(certificate)); return; // All is well } // Cert has changed QString message = evaluateCertificateChange( peerName, previousCertificate, certificate, sock->sslErrors().isEmpty() ); d->acceptCurrent = false; emit certificateWarning(sock, message); } else { // The certificate is new. We don't show anything to user because then // we're simply training them to click through our warning message without // thinking. d->acceptCurrent = true; } // If the user has chosen to accept the certificate or the certficate is new // then we store the updated entry. if (d->acceptCurrent) { d->acceptedCache.insert(peerName,new QSslCertificate(certificate)); addCertificate(peerName, certificate); } else { // Certficate has been considered dangerous by the user sock->abort(); } }
/*! * Handles incoming HTTP requests and dispatches them to the appropriate service. * * The \a requestID is an opaque value generated by the connector. * * Subclasses may override this function to perform preprocessing on each * request, but they must call the base class implementation in order to * generate and dispatch the appropriate events. * * To facilitate use with multi-threaded applications, the event will remain * valid until a response is posted. */ void QxtHttpSessionManager::incomingRequest(quint32 requestID, const QHttpRequestHeader& header, QxtWebContent* content) { QMultiHash<QString, QString> cookies; foreach(const QString& cookie, header.allValues("cookie")) // QHttpHeader is case-insensitive, thankfully { foreach(const QString& kv, cookie.split("; ")) { int pos = kv.indexOf('='); if (pos == -1) continue; cookies.insert(kv.left(pos), kv.mid(pos + 1)); } } int sessionID; QString sessionCookie = cookies.value(qxt_d().sessionCookieName); qxt_d().sessionLock.lock(); if (qxt_d().sessionKeys.contains(sessionCookie)) { sessionID = qxt_d().sessionKeys[sessionCookie]; if(!sessionID && header.majorVersion() > 0 && qxt_d().autoCreateSession) sessionID = newSession(); } else if (header.majorVersion() > 0 && qxt_d().autoCreateSession) { sessionID = newSession(); } else { sessionID = 0; } QIODevice* device = connector()->getRequestConnection(requestID); QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device]; state.sessionID = sessionID; state.httpMajorVersion = header.majorVersion(); state.httpMinorVersion = header.minorVersion(); if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0) || header.value("connection").toLower() == "close") state.keepAlive = false; else state.keepAlive = true; qxt_d().sessionLock.unlock(); QxtWebRequestEvent* event = new QxtWebRequestEvent(sessionID, requestID, QUrl::fromEncoded(header.path().toUtf8())); qxt_d().eventLock.lock(); qxt_d().pendingRequests.insert(QPair<int,int>(sessionID, requestID), event); qxt_d().eventLock.unlock(); QTcpSocket* socket = qobject_cast<QTcpSocket*>(device); if (socket) { event->remoteAddress = socket->peerAddress(); #if defined(QT_SECURETRANSPORT) || !defined(QT_NO_OPENSSL) QSslSocket* sslSocket = qobject_cast<QSslSocket*>(socket); if(sslSocket) { event->isSecure = true; event->clientCertificate = sslSocket->peerCertificate(); } #endif } event->method = header.method(); event->cookies = cookies; event->url.setScheme("http"); if (event->url.host().isEmpty()) event->url.setHost(header.value("host")); if (event->url.port() == -1) event->url.setPort(port()); event->contentType = header.contentType(); event->content = content; typedef QPair<QString, QString> StringPair; foreach(const StringPair& line, header.values()) { if (line.first.toLower() == "cookie") continue; event->headers.insert(line.first, line.second); } event->headers.insert("X-Request-Protocol", "HTTP/" + QString::number(state.httpMajorVersion) + '.' + QString::number(state.httpMinorVersion)); if (sessionID && session(sessionID)) { QxtAbstractWebService *service = session(sessionID); if(content) content->setParent(service); // Set content ownership to the service service->pageRequestedEvent(event); } else if (qxt_d().staticService) { qxt_d().staticService->pageRequestedEvent(event); } else { postEvent(new QxtWebErrorEvent(0, requestID, 500, "Internal Configuration Error")); } }