Core/Auth: Implement time-based token for user login as described in RFC 6238.

New column in account table is a base32 of token key bytes,
coincidentally it is the same format Google's Authenticator Android app uses.
If you want that to work, set system time on server correctly and use ntpd.

Closes #10527

Signed-off-by: Nay <dnpd.dd@gmail.com>
This commit is contained in:
raczman authored and Nay committed 2013-08-25 14:02:40 +01:00
1 parent e96aa444b0
commit ba22baebbd
10 files changed
+160 -2

No files matched your search

@@ -27,6 +27,7 @@
#include "RealmList.h"
#include "AuthSocket.h"
#include "AuthCodes.h"
#include "TOTP.h"
#include "SHA1.h"
#include "openssl/crypto.h"
@@ -492,6 +493,12 @@ bool AuthSocket::_HandleLogonChallenge()
pkt.append(s.AsByteArray().get(), s.GetNumBytes()); // 32 bytes
pkt.append(unk3.AsByteArray(16).get(), 16);
uint8 securityFlags = 0;
// Check if token is used
_tokenKey = fields[8].GetString();
if (!_tokenKey.empty())
securityFlags = 4;
pkt << uint8(securityFlags); // security flags (0x0...0x04)
if (securityFlags & 0x01) // PIN input
@@ -652,6 +659,25 @@ bool AuthSocket::_HandleLogonProof()
sha.UpdateBigNumbers(&A, &M, &K, NULL);
sha.Finalize();
// Check auth token
if ((lp.securityFlags & 0x04) || !_tokenKey.empty())
{
uint8 size;
socket().recv((char*)&size, 1);
char* token = new char[size + 1];
token[size] = '\0';
socket().recv(token, size);
unsigned int validToken = TOTP::GenerateToken(_tokenKey.c_str());
unsigned int incomingToken = atoi(token);
delete[] token;
if (validToken != incomingToken)
{
char data[] = { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0 };
socket().send(data, sizeof(data));
return false;
}
}
if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
{
sAuthLogonProof_S proof;