Commit 9531e07a authored by David Faure's avatar David Faure
Browse files

pop3: implement handling of SSL errors

(taken from IMAP sessionpool and imap resource)
parent 784a0792
......@@ -50,6 +50,7 @@ target_link_libraries( akonadi_pop3_resource
KF5::MailTransport
KF5::AkonadiAgentBase
KF5::I18n
KF5::KIOWidgets # SslUi
KF5::Notifications
Qt::DBus
Qt::Network # QNetworkProxy
......
......@@ -10,6 +10,7 @@
#include <MailTransport/Transport>
#include "pop3resource_debug.h"
#include <KIO/SslUi>
#include <KLocalizedString>
#include "pop3protocol.h"
......@@ -30,9 +31,16 @@ void POPSession::setCurrentJob(BaseJob *job)
mCurrentJob = job;
}
void POPSession::handleSslError(const KSslErrorUiData &errorData)
{
const bool cont = KIO::SslUi::askIgnoreSslErrors(errorData, KIO::SslUi::RecallAndStoreRules);
mProtocol->setContinueAfterSslError(cont);
}
Result POPSession::createProtocol()
{
mProtocol.reset(new POP3Protocol(mSettings, mPassword));
connect(mProtocol.get(), &POP3Protocol::sslError, this, &POPSession::handleSslError);
return mProtocol->openConnection();
}
......
......@@ -15,6 +15,7 @@
#include <QMap>
#include <QObject>
class KSslErrorUiData;
class BaseJob;
class POP3Protocol;
class Settings;
......@@ -36,6 +37,8 @@ public:
void setCurrentJob(BaseJob *job);
private:
void handleSslError(const KSslErrorUiData &);
std::unique_ptr<POP3Protocol> mProtocol;
BaseJob *mCurrentJob = nullptr;
const QString mPassword;
......
......@@ -29,6 +29,8 @@ extern "C" {
#include <QSslSocket>
#include <string.h>
#include <KIOCore/KSslErrorUiData>
#define GREETING_BUF_LEN 1024
#define MAX_RESPONSE_LEN 512
#define MAX_COMMANDS 10
......@@ -661,26 +663,31 @@ Result POP3Protocol::openConnection()
}
}
if (mSettings.useSSL() || mSettings.useTLS()) {
mSocket->ignoreSslErrors(); // Don't worry, errors are handled manually below
mSocket->startClientEncryption();
const bool encryptionStarted = mSocket->waitForEncrypted(s_connectTimeout);
const QSslCipher cipher = mSocket->sessionCipher();
if (!encryptionStarted || mSocket->mode() != QSslSocket::SslClientMode || cipher.isNull() || cipher.usedBits() == 0
|| mSocket->peerCertificateChain().isEmpty()) {
closeConnection();
return Result::fail(ERR_SSL_FAILURE, i18n("Initial SSL handshake failed"));
}
const QList<QSslError> errors = mSocket->sslHandshakeErrors();
if (!errors.isEmpty()) {
QString errorString;
std::accumulate(errors.begin(), errors.end(), QString(), [](QString cur, const QSslError &error) {
if (!encryptionStarted || !errors.isEmpty() || !mSocket->isEncrypted() || cipher.isNull() || cipher.usedBits() == 0) {
QString errorString = std::accumulate(errors.begin(), errors.end(), QString(), [](QString cur, const QSslError &error) {
if (!cur.isEmpty())
cur += QLatin1Char('\n');
cur += error.errorString();
return cur;
});
qCDebug(POP3_LOG) << "TLS setup has failed. Aborting." << errorString;
closeConnection();
return Result::fail(ERR_SSL_FAILURE, i18n("SSL/TLS error: %1", errorString));
qCDebug(POP3_LOG) << "Initial SSL handshake failed. cipher.isNull() is" << cipher.isNull() << ", cipher.usedBits() is" << cipher.usedBits()
<< ", the socket says:" << mSocket->errorString() << "and the SSL errors are:" << errorString;
mContinueAfterSslError = false;
Q_EMIT sslError(KSslErrorUiData(mSocket));
if (!mContinueAfterSslError) {
if (errorString.isEmpty())
errorString = mSocket->errorString();
qCDebug(POP3_LOG) << "TLS setup has failed. Aborting." << errorString;
closeConnection();
return Result::fail(ERR_SSL_FAILURE, i18n("SSL/TLS error: %1", errorString));
}
} else {
qCDebug(POP3_LOG) << "TLS has been enabled.";
}
......@@ -942,3 +949,8 @@ Result POP3Protocol::get(const QString &_commandString)
}
return Result::pass();
}
void POP3Protocol::setContinueAfterSslError(bool b)
{
mContinueAfterSslError = b;
}
......@@ -17,6 +17,7 @@
#include <sys/types.h>
class KSslErrorUiData;
class QSslSocket;
#define MAX_PACKET_LEN 4096
......@@ -61,7 +62,13 @@ public:
*/
Q_REQUIRED_RESULT Result get(const QString &command);
/**
* Sets whether to continue or abort after a SSL error
*/
void setContinueAfterSslError(bool b);
Q_SIGNALS:
void sslError(const KSslErrorUiData &);
void data(const QByteArray &data);
void messageComplete();
......@@ -127,6 +134,7 @@ private:
QString m_sServer, m_sPass, m_sUser;
bool m_try_apop, m_try_sasl, supports_apop;
bool mConnected = false;
bool mContinueAfterSslError = false;
QString m_sError;
char readBuffer[MAX_PACKET_LEN];
ssize_t readBufferLen;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment