summaryrefslogtreecommitdiff
path: root/protocols/JabberG
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2020-06-29 12:21:47 +0300
committerGeorge Hazan <ghazan@miranda.im>2020-06-29 12:21:47 +0300
commitd95fc3ef9e7576ad4ab4dd099c4508c4302d91e5 (patch)
tree4af20db8bd74b1a6dc7498f1aae44221b4d814b3 /protocols/JabberG
parenta38638ab3da26d7ece314231c3fc5803512b6cfb (diff)
fixes #2469 (Jabber: implement SCRAM-SHA-1-PLUS auth)
Diffstat (limited to 'protocols/JabberG')
-rwxr-xr-xprotocols/JabberG/src/jabber_proto.h25
-rw-r--r--protocols/JabberG/src/jabber_secur.cpp28
-rw-r--r--protocols/JabberG/src/jabber_secur.h35
-rwxr-xr-xprotocols/JabberG/src/jabber_thread.cpp71
4 files changed, 88 insertions, 71 deletions
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<CJabberProto>, 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);
}
}