问题
I want to communicate with a POP3 server with ssl and port 995 with my client app the certificate of server is self-signed and while running the app the error that received is:
The certificate is self-signed, and untrusted
A part of code is:
socket = new QSslSocket(this);
QFile certfile("D:\\hani\\cert\\localhost.localdomain.pem");
Q_ASSERT(certfile.open(QIODevice::ReadOnly));
QList<QSslCertificate> certList;
QSslCertificate cert(&certfile,QSsl::Pem);
certList.append(cert);
socket->addCaCertificate(cert);
socket->setCaCertificates(certList);
QList<QSslCertificate> serverCert = socket->caCertificates();
What can I do?
回答1:
DO NOT, let me repeat, DO NOT call ignoreSslErrors()
. It completely defeats the purpose of SSL/TLS. There are very special cases where it can be called safely, but this (self-signed certificate) is not a special case.
The following minimal code, ready to run, shows how to securely accept a server self-signed certificate. Do not shortcut it.
The driver:
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();
}
The DummyClient
class:
/*
* Show how to safely authenticate a TLS server which uses a self-signed certificate.
* Warning: No error handling to keep the code short.
*/
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<QSslError>)),
this, SLOT(onSslErrors(QList<QSslError>)));
connect(_sock, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onErrors(QAbstractSocket::SocketError)));
// Trust store: which CAs or self-signed certs we are going to trust.
//
// We use setCaCertificates() instead than QSslSocket::addCaCertificates()
// because we don't want to trust the ~200 default CAs.
QList<QSslCertificate> trustedCas = QSslCertificate::fromPath("server-cert.pem");
if (trustedCas.empty()) {
qFatal("Error: no trusted Cas");
}
_sock->setCaCertificates(trustedCas);
bool mutualAuth = false;
if (mutualAuth) {
// Our identity
_sock->setPrivateKey("client-key.pem");
_sock->setLocalCertificate("client-cert.pem");
}
_log << "Connecting" << endl;
// Note: serverName must match the cert CN or alternative name.
Qstring serverName = "myserver.example.org";
_sock->connectToHostEncrypted(serverName, 995);
}
signals:
void done();
private slots:
void onEncrypted() {
_log << "onEncrypted" << endl;
/* Everything is good. Start communicating. */
emit done();
}
void onSslErrors(QList<QSslError> errors) {
QSslError first = errors.takeFirst();
_log << "onSslErrors: " << first.errorString() << endl;
/* Something went wrong in the TLS handshake. Inform the user and quit! */
emit done();
}
void onErrors(QAbstractSocket::SocketError) {
_log << "onErrors: " << _sock->errorString() << endl;
emit done();
}
private:
QTextStream& _log;
QSslSocket* _sock;
};
回答2:
http://qt-project.org/doc/qt-5.1/qtnetwork/qsslsocket.html
Look at the description of QSslSocket::sslErrors
:
If you want to continue connecting despite the errors that have occurred,
you must call QSslSocket::ignoreSslErrors() from inside a slot connected
to this signal.
DISCLAIMER: This is very ill-advised, as it leaves the server "wide open" to man-in-the-middle attacks
来源:https://stackoverflow.com/questions/18810788/how-a-client-app-connect-to-an-ssl-server-with-a-self-signed-certificate-in-qt