2 Stimmen

Wie verbindet sich eine Client-App mit einem SSL-Server mit einem selbstsignierten Zertifikat in Qt?

Ich möchte mit einer SSL-Verbindung und Port 995 mit meiner Client-App mit einem POP3-Server kommunizieren das Zertifikat des Servers ist selbstsigniert und während der Ausführung der App lautet der Fehler, den ich erhalte:

Das Zertifikat ist selbstsigniert und nicht vertrauenswürdig

Ein Teil des Codes ist:

socket = new QSslSocket(this);
QFile certfile("D:\\hani\\cert\\localhost.localdomain.pem");
Q_ASSERT(certfile.open(QIODevice::ReadOnly));
QList certList;
QSslCertificate cert(&certfile,QSsl::Pem);
certList.append(cert);
socket->addCaCertificate(cert);
socket->setCaCertificates(certList);
QList serverCert = socket->caCertificates();

Was kann ich tun?

8voto

marco.m Punkte 4349

BITTE, ich wiederhole, BITTE rufen Sie ignoreSslErrors() NICHT auf. Dies widerspricht vollständig dem Zweck von SSL/TLS. Es gibt sehr spezielle Fälle, in denen es sicher aufgerufen werden kann, aber dies (selbstsigniertes Zertifikat) ist kein spezieller Fall.

Der folgende minimale Code, bereit zum Ausführen, zeigt, wie man ein Server-Selbstsigniertes Zertifikat sicher akzeptiert. Verkürzen Sie es nicht.

Der Treiber:

int main(int argc, char** argv) {
    QCoreApplication app(argc, argv);
    QTextStream log(stdout);
    DummyClient dummy(log);
    QObject::connect(&dummy, SIGNAL(done()), &app, SLOT(quit()));
    return app.exec();
}

Die DummyClient Klasse:

/*
 * Zeigen Sie, wie man sicher einen TLS-Server authentifiziert, der ein selbstsigniertes Zertifikat verwendet.
 * Warnung: Keine Fehlerbehandlung, um den Code kurz zu halten.
 */
class DummyClient : public QObject {
    Q_OBJECT
public:
    DummyClient(QTextStream& log)
        : _log(log),
          _sock(new QSslSocket(this)) {
        connect(_sock, SIGNAL(encrypted()), this, SLOT(onEncrypted()));
        connect(_sock, SIGNAL(sslErrors(QList)),
                this, SLOT(onSslErrors(QList)));
        connect(_sock, SIGNAL(error(QAbstractSocket::SocketError)),
                this, SLOT(onErrors(QAbstractSocket::SocketError)));

        // Trust store: welche CAs oder selbstsignierte Zertifikate vertrauen wir.
        //
        // Wir verwenden setCaCertificates() anstatt QSslSocket::addCaCertificates()
        // da wir die ~200 Standard-CAs nicht vertrauen wollen.
        QList trustedCas = QSslCertificate::fromPath("server-cert.pem");
        if (trustedCas.empty()) {
            qFatal("Fehler: keine vertrauenswürdigen Cas gefunden");
        }
        _sock->setCaCertificates(trustedCas);

        bool mutualAuth = false;
        if (mutualAuth) {
            // Unsere Identität
            _sock->setPrivateKey("client-key.pem");
            _sock->setLocalCertificate("client-cert.pem");
        }

        _log << "Verbindung wird hergestellt" << endl;
        // Hinweis: serverName muss mit dem Zertifikat CN oder Alternativnamen übereinstimmen.
        Qstring serverName = "meinserver.beispiel.org";
        _sock->connectToHostEncrypted(serverName, 995);
    }

signals:
    void done();

private slots:
    void onEncrypted() {
        _log << "onEncrypted" << endl;

        /* Alles ist gut. Kommunikation starten. */

        emit done();
    }

    void onSslErrors(QList errors) {
        QSslError first = errors.takeFirst();
        _log << "onSslErrors: " << first.errorString() << endl;

        /* Etwas ist schiefgelaufen im TLS-Handshake. Benutzer informieren und beenden! */

        emit done();
    }

    void onErrors(QAbstractSocket::SocketError) {
        _log << "onErrors: " << _sock->errorString() << endl;
        emit done();
    }

private:
    QTextStream& _log;
    QSslSocket* _sock;
};

0voto

Rudolfs Bundulis Punkte 11570

http://qt-project.org/doc/qt-5.1/qtnetwork/qsslsocket.html

Schauen Sie sich die Beschreibung von QSslSocket::sslErrors an:

Wenn Sie die Verbindung trotz der aufgetretenen Fehler fortsetzen möchten, 
müssen Sie QSslSocket::ignoreSslErrors() in einem Slot aufrufen, der mit diesem
Signal verbunden ist.

HAFTUNGSAUSSCHLUSS: Dies ist sehr nicht ratsam, da es den Server "weit offen" lässt für Man-in-the-Middle-Angriffe

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X