Commit b33f0639 authored by Volker Krause's avatar Volker Krause
Browse files

Move encryption settings from LoginJob to Session

This does not change any of the logic to apply encryption yet, ie. that
is still tied to LoginJob. This however now enables moving that logic
step by step to Session and thus enable encryption independent of a login
being required.
parent a6b9e77a
Pipeline #80977 passed with stage
in 4 minutes and 1 second
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(PIM_VERSION "5.18.40")
set(PIM_VERSION "5.18.41")
project(KSMTP VERSION ${PIM_VERSION})
......
......@@ -42,7 +42,6 @@ public:
: JobPrivate(session, name)
, m_preferedAuthMode(LoginJob::Login)
, m_actualAuthMode(LoginJob::UnknownAuth)
, m_encryptionMode(LoginJob::Unencrypted)
, q(job)
{
}
......@@ -65,7 +64,6 @@ public:
QString m_password;
LoginJob::AuthMode m_preferedAuthMode;
LoginJob::AuthMode m_actualAuthMode;
LoginJob::EncryptionMode m_encryptionMode;
sasl_conn_t *m_saslConn = nullptr;
sasl_interact_t *m_saslClient = nullptr;
......@@ -114,30 +112,19 @@ LoginJob::AuthMode LoginJob::usedAuthMode() const
return d_func()->m_actualAuthMode;
}
void LoginJob::setEncryptionMode(EncryptionMode mode)
{
Q_D(LoginJob);
d->m_encryptionMode = mode;
}
LoginJob::EncryptionMode LoginJob::encryptionMode() const
{
return d_func()->m_encryptionMode;
}
void LoginJob::doStart()
{
Q_D(LoginJob);
const auto negotiatedEnc = d->sessionInternal()->negotiatedEncryption();
if (negotiatedEnc != QSsl::UnknownProtocol) {
// Socket already encrypted, pretend we did not want any
d->m_encryptionMode = Unencrypted;
}
if (d->m_encryptionMode == SSLorTLS) {
if (negotiatedEnc != QSsl::UnknownProtocol || d->m_session->encryptionMode() == Session::Unencrypted) {
// Socket already encrypted, or no encryption requested: continue with authentication
if (!d->authenticate()) {
emitResult();
}
} else if (d->m_session->encryptionMode() == Session::TLS) {
d->sessionInternal()->startSsl();
} else if (d->m_encryptionMode == STARTTLS) {
} else if (d->m_session->encryptionMode() == Session::STARTTLS) {
if (session()->allowsTls()) {
sendCommand(QByteArrayLiteral("STARTTLS"));
} else {
......@@ -146,10 +133,6 @@ void LoginJob::doStart()
setErrorText(i18n("STARTTLS is not supported by the server, try using SSL/TLS instead."));
emitResult();
}
} else {
if (!d->authenticate()) {
emitResult();
}
}
}
......
......@@ -24,12 +24,6 @@ class KSMTP_EXPORT LoginJob : public Job
Q_DECLARE_PRIVATE(LoginJob)
public:
enum EncryptionMode {
Unencrypted,
SSLorTLS, ///< Use SSL/TLS encryption
STARTTLS ///< Use STARTTLS to upgrade an unencrypted connection to encrypted
};
enum AuthMode { UnknownAuth, Plain, Login, CramMD5, DigestMD5, NTLM, GSSAPI, Anonymous, XOAuth2 };
enum LoginError { TokenExpired = KJob::UserDefinedError + 1 };
......@@ -43,9 +37,6 @@ public:
void setPreferedAuthMode(AuthMode mode);
Q_REQUIRED_RESULT AuthMode usedAuthMode() const;
void setEncryptionMode(EncryptionMode mode);
Q_REQUIRED_RESULT EncryptionMode encryptionMode() const;
protected:
void doStart() override;
void handleResponse(const ServerResponse &r) override;
......
......@@ -136,6 +136,16 @@ Session::State Session::state() const
return d->m_state;
}
Session::EncryptionMode Session::encryptionMode() const
{
return d->m_encryptionMode;
}
void Session::setEncryptionMode(Session::EncryptionMode mode)
{
d->m_encryptionMode = mode;
}
bool Session::allowsTls() const
{
return d->m_allowsTls;
......@@ -272,7 +282,7 @@ void SessionPrivate::socketConnected()
bool useSsl = false;
if (!m_queue.isEmpty()) {
if (auto login = qobject_cast<LoginJob *>(m_queue.first())) {
useSsl = login->encryptionMode() == LoginJob::SSLorTLS;
useSsl = m_encryptionMode == Session::TLS;
}
}
......
......@@ -35,6 +35,14 @@ public:
};
Q_ENUM(State)
/** Transport encryption for a session. */
enum EncryptionMode {
Unencrypted, ///< Use no encryption.
TLS, ///< Use TLS encryption on the socket.
STARTTLS ///< Use STARTTLS to upgrade an unencrypted connection to encrypted after the initial handshake.
};
Q_ENUM(EncryptionMode)
/**
Creates a new SMTP session to the specified host and port.
After creating the session, call setUseNetworkProxy() if necessary
......@@ -68,6 +76,14 @@ public:
Q_REQUIRED_RESULT State state() const;
/** Returns the requested encryption mode for this session. */
Q_REQUIRED_RESULT EncryptionMode encryptionMode() const;
/** Sets the encryption mode for this session.
* Has to be called before @c open().
*/
void setEncryptionMode(EncryptionMode mode);
/**
Returns true if the SMTP server has indicated that it allows TLS connections, false otherwise.
The session must be at least in the NotAuthenticated state. Before that, allowsTls() always
......@@ -104,6 +120,10 @@ public:
You should connect to stateChanged() before calling this method, and wait until the session's
state is NotAuthenticated (Session is ready for a LoginJob) or Disconnected (connecting to the
server failed)
Make sure to call @c setEncryptionMode() before.
@see setEncryptionMode
*/
void open();
......
......@@ -68,6 +68,7 @@ private:
// Smtp session
Session::State m_state = Session::Disconnected;
Session::EncryptionMode m_encryptionMode = Session::Unencrypted;
SessionThread *m_thread = nullptr;
SessionUiProxy::Ptr m_uiProxy;
int m_socketTimerInterval = 60000;
......
......@@ -26,16 +26,11 @@ public:
}
};
void login(KSmtp::Session *session, const QString &user, const QString &pass, bool ssltls, bool starttls)
void login(KSmtp::Session *session, const QString &user, const QString &pass)
{
auto login = new KSmtp::LoginJob(session);
login->setUserName(user);
login->setPassword(pass);
if (ssltls) {
login->setEncryptionMode(KSmtp::LoginJob::SSLorTLS);
} else if (starttls) {
login->setEncryptionMode(KSmtp::LoginJob::STARTTLS);
}
QObject::connect(login, &KJob::result, [](KJob *job) {
if (job->error()) {
std::cout << "Login error: " << job->errorString().toStdString() << std::endl;
......@@ -76,6 +71,11 @@ int main(int argc, char **argv)
KSmtp::Session session(parser.value(hostOption), parser.value(portOption).toUInt());
session.setUiProxy(SessionUiProxy::Ptr(new SessionUiProxy));
if (parser.isSet(sslTlsOption)) {
session.setEncryptionMode(KSmtp::Session::TLS);
} else if (parser.isSet(startTlsOption)) {
session.setEncryptionMode(KSmtp::Session::STARTTLS);
}
QObject::connect(&session, &KSmtp::Session::stateChanged, [&](KSmtp::Session::State state) {
switch (state) {
case KSmtp::Session::Disconnected:
......@@ -87,7 +87,7 @@ int main(int argc, char **argv)
case KSmtp::Session::Ready:
std::cout << "Session in Ready state" << std::endl;
std::cout << std::endl;
login(&session, parser.value(userOption), parser.value(passOption), parser.isSet(sslTlsOption), parser.isSet(startTlsOption));
login(&session, parser.value(userOption), parser.value(passOption));
break;
case KSmtp::Session::Quitting:
// Internal (avoid compile warning)
......
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