From d95fc3ef9e7576ad4ab4dd099c4508c4302d91e5 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 29 Jun 2020 12:21:47 +0300 Subject: fixes #2469 (Jabber: implement SCRAM-SHA-1-PLUS auth) --- protocols/JabberG/src/jabber_proto.h | 25 +++++++----- protocols/JabberG/src/jabber_secur.cpp | 28 ++++++------- protocols/JabberG/src/jabber_secur.h | 35 ++++++++-------- protocols/JabberG/src/jabber_thread.cpp | 71 ++++++++++++++++++--------------- 4 files changed, 88 insertions(+), 71 deletions(-) (limited to 'protocols/JabberG') diff --git a/protocols/JabberG/src/jabber_proto.h b/protocols/JabberG/src/jabber_proto.h index a7a65ff709..5dd2f0e8fc 100755 --- a/protocols/JabberG/src/jabber_proto.h +++ b/protocols/JabberG/src/jabber_proto.h @@ -792,15 +792,22 @@ struct CJabberProto : public PROTO, public IJabberInterface ptrA m_szGroupDelimiter; ptrW m_savedPassword; - bool m_isPlainAvailable; - bool m_isPlainOldAvailable; - bool m_isMd5Available; - bool m_isScramAvailable; - bool m_isNtlmAvailable; - bool m_isSpnegoAvailable; - bool m_isKerberosAvailable; - bool m_isAuthAvailable; - bool m_isSessionAvailable; + union { + int m_dwAuthMechs; + struct { + bool m_isPlainAvailable : 1; + bool m_isPlainOldAvailable : 1; + bool m_isMd5Available : 1; + bool m_isScramAvailable : 1; + bool m_isScramPlusAvailable : 1; + bool m_isNtlmAvailable : 1; + bool m_isSpnegoAvailable : 1; + bool m_isKerberosAvailable : 1; + bool m_isAuthAvailable : 1; + bool m_isSessionAvailable : 1; + }; + }; + char* m_gssapiHostName; void __cdecl ServerThread(JABBER_CONN_DATA *info); diff --git a/protocols/JabberG/src/jabber_secur.cpp b/protocols/JabberG/src/jabber_secur.cpp index c66c9e2e52..3d1f0a4725 100644 --- a/protocols/JabberG/src/jabber_secur.cpp +++ b/protocols/JabberG/src/jabber_secur.cpp @@ -206,8 +206,9 @@ char* TMD5Auth::getChallenge(const char *challenge) ///////////////////////////////////////////////////////////////////////////////////////// // SCRAM-SHA-1 authorization -TScramAuth::TScramAuth(ThreadData *info) : - TJabberAuth(info) +TScramAuth::TScramAuth(ThreadData *info, bool bPlusAvailable) : + TJabberAuth(info), + bPlus(bPlusAvailable) { szName = "SCRAM-SHA-1"; cnonce = msg1 = serverSignature = nullptr; @@ -238,6 +239,17 @@ void TScramAuth::Hi(BYTE* res, char* passw, size_t passwLen, char* salt, size_t } } +char* TScramAuth::getInitialRequest() +{ + unsigned char nonce[24]; + Utils_GetRandom(nonce, sizeof(nonce)); + cnonce = mir_base64_encode(nonce, sizeof(nonce)); + + CMStringA buf(FORMAT, "%c,,n=%s,r=%s", (bPlus) ? 'p' : 'n', info->conn.username, cnonce); + msg1 = mir_strdup(buf.c_str() + 3); + return mir_base64_encode(buf, buf.GetLength()); +} + char* TScramAuth::getChallenge(const char *challenge) { size_t chlLen, saltLen = 0; @@ -299,18 +311,6 @@ char* TScramAuth::getChallenge(const char *challenge) return mir_base64_encode(buf, cbLen); } -char* TScramAuth::getInitialRequest() -{ - unsigned char nonce[24]; - Utils_GetRandom(nonce, sizeof(nonce)); - cnonce = mir_base64_encode(nonce, sizeof(nonce)); - - char buf[4096]; - int cbLen = mir_snprintf(buf, "n,,n=%s,r=%s", info->conn.username, cnonce); - msg1 = mir_strdup(buf + 3); - return mir_base64_encode(buf, cbLen); -} - bool TScramAuth::validateLogin(const char *challenge) { size_t chlLen; diff --git a/protocols/JabberG/src/jabber_secur.h b/protocols/JabberG/src/jabber_secur.h index 28a9f17ed8..28d9ba1b0a 100644 --- a/protocols/JabberG/src/jabber_secur.h +++ b/protocols/JabberG/src/jabber_secur.h @@ -72,26 +72,28 @@ class TMD5Auth : public TJabberAuth { typedef TJabberAuth CSuper; - int iCallCount; + int iCallCount; public: - TMD5Auth(ThreadData*); - virtual ~TMD5Auth(); + TMD5Auth(ThreadData*); + ~TMD5Auth(); - virtual char* getChallenge(const char *challenge); + char* getChallenge(const char *challenge) override; }; class TScramAuth : public TJabberAuth { typedef TJabberAuth CSuper; - char *cnonce, *msg1, *serverSignature; + char *cnonce, *msg1, *serverSignature; + bool bPlus; + public: - TScramAuth(ThreadData*); - virtual ~TScramAuth(); + TScramAuth(ThreadData*, bool); + ~TScramAuth(); - virtual char* getInitialRequest(); - virtual char* getChallenge(const char *challenge); - virtual bool validateLogin(const char *challenge); + char* getInitialRequest() override; + char* getChallenge(const char *challenge) override; + bool validateLogin(const char *challenge) override; void Hi(BYTE* res , char* passw, size_t passwLen, char* salt, size_t saltLen, int ind); }; @@ -102,14 +104,15 @@ class TNtlmAuth : public TJabberAuth { typedef TJabberAuth CSuper; - HANDLE hProvider; - const char *szHostName; + HANDLE hProvider; + const char *szHostName; + public: - TNtlmAuth(ThreadData*, const char* mechanism, const char *hostname = nullptr); - virtual ~TNtlmAuth(); + TNtlmAuth(ThreadData*, const char* mechanism, const char *hostname = nullptr); + ~TNtlmAuth(); - virtual char* getInitialRequest(); - virtual char* getChallenge(const char *challenge); + char* getInitialRequest() override; + char* getChallenge(const char *challenge) override; bool getSpn(wchar_t* szSpn, size_t dwSpnLen); }; diff --git a/protocols/JabberG/src/jabber_thread.cpp b/protocols/JabberG/src/jabber_thread.cpp index 586e670548..69d039957d 100755 --- a/protocols/JabberG/src/jabber_thread.cpp +++ b/protocols/JabberG/src/jabber_thread.cpp @@ -50,11 +50,11 @@ struct JabberPasswordDlgParam { CJabberProto *pro; - BOOL saveOnlinePassword; - WORD dlgResult; - wchar_t onlinePassword[128]; - HANDLE hEventPasswdDlg; - char *pszJid; + BOOL saveOnlinePassword; + WORD dlgResult; + wchar_t onlinePassword[128]; + HANDLE hEventPasswdDlg; + char *pszJid; }; static INT_PTR CALLBACK JabberPasswordDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) @@ -627,9 +627,14 @@ void CJabberProto::PerformAuthentication(ThreadData *info) } } + if (auth == nullptr && m_isScramPlusAvailable) { + m_isScramPlusAvailable = false; + auth = new TScramAuth(info, true); + } + if (auth == nullptr && m_isScramAvailable) { m_isScramAvailable = false; - auth = new TScramAuth(info); + auth = new TScramAuth(info, false); } if (auth == nullptr && m_isMd5Available) { @@ -702,26 +707,28 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info) } if (!mir_strcmp(pszName, "mechanisms")) { - m_isPlainAvailable = false; - m_isPlainOldAvailable = false; - m_isMd5Available = false; - m_isScramAvailable = false; - m_isNtlmAvailable = false; - m_isSpnegoAvailable = false; - m_isKerberosAvailable = false; - mir_free(m_gssapiHostName); m_gssapiHostName = nullptr; + m_dwAuthMechs = 0; + replaceStr(m_gssapiHostName, nullptr); areMechanismsDefined = true; - //JabberLog("%d mechanisms\n",n->numChild); + for (auto *c : TiXmlEnum(n)) { if (!mir_strcmp(c->Name(), "mechanism")) { const char *szMechanism = c->GetText(); - if (!mir_strcmp(szMechanism, "PLAIN")) m_isPlainOldAvailable = m_isPlainAvailable = true; - else if (!mir_strcmp(szMechanism, "DIGEST-MD5")) m_isMd5Available = true; - else if (!mir_strcmp(szMechanism, "SCRAM-SHA-1")) m_isScramAvailable = true; - else if (!mir_strcmp(szMechanism, "NTLM")) m_isNtlmAvailable = true; - else if (!mir_strcmp(szMechanism, "GSS-SPNEGO")) m_isSpnegoAvailable = true; - else if (!mir_strcmp(szMechanism, "GSSAPI")) m_isKerberosAvailable = true; + if (!mir_strcmp(szMechanism, "PLAIN")) + m_isPlainOldAvailable = m_isPlainAvailable = true; + else if (!mir_strcmp(szMechanism, "DIGEST-MD5")) + m_isMd5Available = true; + else if (!mir_strcmp(szMechanism, "SCRAM-SHA-1")) + m_isScramAvailable = true; + else if (!mir_strcmp(szMechanism, "SCRAM-SHA-1-PLUS")) + m_isScramPlusAvailable = true; + else if (!mir_strcmp(szMechanism, "NTLM")) + m_isNtlmAvailable = true; + else if (!mir_strcmp(szMechanism, "GSS-SPNEGO")) + m_isSpnegoAvailable = true; + else if (!mir_strcmp(szMechanism, "GSSAPI")) + m_isKerberosAvailable = true; } else if (!mir_strcmp(c->Name(), "hostname")) { const char *mech = XmlGetAttr(c, "mechanism"); @@ -730,9 +737,12 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info) } } } - else if (!mir_strcmp(pszName, "register")) isRegisterAvailable = true; - else if (!mir_strcmp(pszName, "auth")) m_isAuthAvailable = true; - else if (!mir_strcmp(pszName, "session")) m_isSessionAvailable = true; + else if (!mir_strcmp(pszName, "register")) + isRegisterAvailable = true; + else if (!mir_strcmp(pszName, "auth")) + m_isAuthAvailable = true; + else if (!mir_strcmp(pszName, "session")) + m_isSessionAvailable = true; else if (m_bEnableStreamMgmt && !mir_strcmp(pszName, "sm")) m_StrmMgmt.CheckStreamFeatures(n); else if (!mir_strcmp(pszName, "csi") && n->Attribute("xmlns", JABBER_FEAT_CSI)) @@ -747,11 +757,11 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info) return; } - if (m_bEnableStreamMgmt && m_StrmMgmt.IsResumeIdPresent()) //resume should be done here + // mechanisms are not defined. + if (m_bEnableStreamMgmt && m_StrmMgmt.IsResumeIdPresent()) // resume should be done here m_StrmMgmt.CheckState(); else { - // mechanisms are not defined. - if (info->auth) { //We are already logged-in + if (info->auth) { // we are already logged-in info->send( XmlNodeIq(AddIQ(&CJabberProto::OnIqResultBind, JABBER_IQ_TYPE_SET)) << XCHILDNS("bind", JABBER_FEAT_BIND) @@ -759,12 +769,9 @@ void CJabberProto::OnProcessFeatures(const TiXmlElement *node, ThreadData *info) if (m_isSessionAvailable) info->bIsSessionAvailable = true; - - return; } - - //mechanisms not available and we are not logged in - PerformIqAuth(info); + else // mechanisms are not available and we are not logged in + PerformIqAuth(info); } } -- cgit v1.2.3