diff --git a/src/base/QXmppSasl.cpp b/src/base/QXmppSasl.cpp index 1a850dc5a..6d9b63eed 100644 --- a/src/base/QXmppSasl.cpp +++ b/src/base/QXmppSasl.cpp @@ -1018,8 +1018,8 @@ std::unique_ptr QXmppSaslClient::create(SaslMechanism mechanism [&](SaslScramMechanism scram) { return std::make_unique(scram, parent); }, - [&](SaslHtMechanism) { - return nullptr; + [&](SaslHtMechanism ht) { + return std::make_unique(ht, parent); }, [&](SaslPlainMechanism) { return std::make_unique(parent); @@ -1636,3 +1636,24 @@ QByteArray QXmppSaslDigestMd5::serializeMessage(const QMap QXmppSaslClientHt::respond(const QByteArray &challenge) +{ + // TODO: verify provided by SASL 2 (hmac key 'Responder' + cb data). + + Q_ASSERT(m_mechanism.channelBindingType == QXmpp::Private::SaslHtMechanism::None); + + if (m_done || !challenge.isEmpty()) { + return {}; + } + + // key: 'Initiator' + channel-binding data + const auto key = QByteArrayLiteral("Initiator"); + QMessageAuthenticationCode hmac( + ianaHashAlgorithmToQt(m_mechanism.hashAlgorithm), + key); + hmac.addData(password().toUtf8()); + + m_done = true; + return hmac.result(); +} diff --git a/src/base/QXmppSasl_p.h b/src/base/QXmppSasl_p.h index d305aa65b..ef22df3bd 100644 --- a/src/base/QXmppSasl_p.h +++ b/src/base/QXmppSasl_p.h @@ -519,6 +519,25 @@ class QXmppSaslClientScram : public QXmppSaslClient QByteArray m_nonce; }; +class QXmppSaslClientHt : public QXmppSaslClient +{ + Q_OBJECT + using HtMechanism = QXmpp::Private::SaslHtMechanism; + +public: + QXmppSaslClientHt(HtMechanism mechanism, QObject *parent) + : QXmppSaslClient(parent), m_mechanism(mechanism) + { + } + + QString mechanism() const override { return m_mechanism.toString(); } + std::optional respond(const QByteArray &challenge) override; + +private: + HtMechanism m_mechanism; + bool m_done = false; +}; + class QXmppSaslClientWindowsLive : public QXmppSaslClient { Q_OBJECT