mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[8445] Fixed redundant calculation of v and s on every login
The SRP-6 specifications clearly say, that v and s are only to be calculated on registering a user and changing his password; calculating them on every login is plain waste.
This commit is contained in:
parent
4d0088e7a9
commit
3b1b68595b
8 changed files with 47 additions and 60 deletions
|
|
@ -142,7 +142,8 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accid, std::string new_passwd)
|
||||||
normalizeString(new_passwd);
|
normalizeString(new_passwd);
|
||||||
|
|
||||||
loginDatabase.escape_string(new_passwd);
|
loginDatabase.escape_string(new_passwd);
|
||||||
if(!loginDatabase.PExecute("UPDATE account SET sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd.c_str(), accid))
|
// also reset s and v to force update at next realmd login
|
||||||
|
if(!loginDatabase.PExecute("UPDATE account SET v='0', s='0', sha_pass_hash=SHA1("_CONCAT3_("username","':'","'%s'")") WHERE id='%d'", new_passwd.c_str(), accid))
|
||||||
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
return AOR_DB_INTERNAL_ERROR; // unexpected error
|
||||||
|
|
||||||
return AOR_OK;
|
return AOR_OK;
|
||||||
|
|
|
||||||
|
|
@ -119,9 +119,6 @@ class CharacterHandler
|
||||||
|
|
||||||
void WorldSession::HandleCharEnum(QueryResult * result)
|
void WorldSession::HandleCharEnum(QueryResult * result)
|
||||||
{
|
{
|
||||||
// keys can be non cleared if player open realm list and close it by 'cancel'
|
|
||||||
loginDatabase.PExecute("UPDATE account SET v = '0', s = '0' WHERE id = '%u'", GetAccountId());
|
|
||||||
|
|
||||||
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
|
WorldPacket data(SMSG_CHAR_ENUM, 100); // we guess size
|
||||||
|
|
||||||
uint8 num = 0;
|
uint8 num = 0;
|
||||||
|
|
|
||||||
|
|
@ -760,7 +760,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||||
LocaleConstant locale;
|
LocaleConstant locale;
|
||||||
std::string account;
|
std::string account;
|
||||||
Sha1Hash sha1;
|
Sha1Hash sha1;
|
||||||
BigNumber v, s, g, N, x, I;
|
BigNumber v, s, g, N;
|
||||||
WorldPacket packet, SendAddonPacked;
|
WorldPacket packet, SendAddonPacked;
|
||||||
|
|
||||||
BigNumber K;
|
BigNumber K;
|
||||||
|
|
@ -792,12 +792,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||||
"sessionkey, " //2
|
"sessionkey, " //2
|
||||||
"last_ip, " //3
|
"last_ip, " //3
|
||||||
"locked, " //4
|
"locked, " //4
|
||||||
"sha_pass_hash, " //5
|
"v, " //5
|
||||||
"v, " //6
|
"s, " //6
|
||||||
"s, " //7
|
"expansion, " //7
|
||||||
"expansion, " //8
|
"mutetime, " //8
|
||||||
"mutetime, " //9
|
"locale " //9
|
||||||
"locale " //10
|
|
||||||
"FROM account "
|
"FROM account "
|
||||||
"WHERE username = '%s'",
|
"WHERE username = '%s'",
|
||||||
safe_account.c_str ());
|
safe_account.c_str ());
|
||||||
|
|
@ -816,57 +815,21 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||||
|
|
||||||
Field* fields = result->Fetch ();
|
Field* fields = result->Fetch ();
|
||||||
|
|
||||||
expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[8].GetUInt8()) ? fields[8].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION));
|
expansion = ((sWorld.getConfig(CONFIG_EXPANSION) > fields[7].GetUInt8()) ? fields[7].GetUInt8() : sWorld.getConfig(CONFIG_EXPANSION));
|
||||||
|
|
||||||
N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
|
N.SetHexStr ("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7");
|
||||||
g.SetDword (7);
|
g.SetDword (7);
|
||||||
I.SetHexStr (fields[5].GetString ());
|
|
||||||
|
|
||||||
//In case of leading zeros in the I hash, restore them
|
v.SetHexStr(fields[5].GetString());
|
||||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
s.SetHexStr (fields[6].GetString ());
|
||||||
memset (mDigest, 0, SHA_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
if (I.GetNumBytes () <= SHA_DIGEST_LENGTH)
|
|
||||||
memcpy (mDigest, I.AsByteArray (), I.GetNumBytes ());
|
|
||||||
|
|
||||||
std::reverse (mDigest, mDigest + SHA_DIGEST_LENGTH);
|
|
||||||
|
|
||||||
s.SetHexStr (fields[7].GetString ());
|
|
||||||
sha1.UpdateData (s.AsByteArray (), s.GetNumBytes ());
|
|
||||||
sha1.UpdateData (mDigest, SHA_DIGEST_LENGTH);
|
|
||||||
sha1.Finalize ();
|
|
||||||
x.SetBinary (sha1.GetDigest (), sha1.GetLength ());
|
|
||||||
v = g.ModExp (x, N);
|
|
||||||
|
|
||||||
const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free()
|
const char* sStr = s.AsHexStr (); //Must be freed by OPENSSL_free()
|
||||||
const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free()
|
const char* vStr = v.AsHexStr (); //Must be freed by OPENSSL_free()
|
||||||
const char* vold = fields[6].GetString ();
|
|
||||||
|
|
||||||
DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v_old: %s v_new: %s",
|
DEBUG_LOG ("WorldSocket::HandleAuthSession: (s,v) check s: %s v: %s",
|
||||||
sStr,
|
sStr,
|
||||||
vold,
|
|
||||||
vStr);
|
vStr);
|
||||||
|
|
||||||
loginDatabase.PExecute ("UPDATE account "
|
|
||||||
"SET "
|
|
||||||
"v = '0', "
|
|
||||||
"s = '0' "
|
|
||||||
"WHERE username = '%s'",
|
|
||||||
safe_account.c_str ());
|
|
||||||
|
|
||||||
if (!vold || strcmp (vStr, vold))
|
|
||||||
{
|
|
||||||
packet.Initialize (SMSG_AUTH_RESPONSE, 1);
|
|
||||||
packet << uint8 (AUTH_UNKNOWN_ACCOUNT);
|
|
||||||
SendPacket (packet);
|
|
||||||
delete result;
|
|
||||||
OPENSSL_free ((void*) sStr);
|
|
||||||
OPENSSL_free ((void*) vStr);
|
|
||||||
|
|
||||||
sLog.outBasic ("WorldSocket::HandleAuthSession: User not logged.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
OPENSSL_free ((void*) sStr);
|
OPENSSL_free ((void*) sStr);
|
||||||
OPENSSL_free ((void*) vStr);
|
OPENSSL_free ((void*) vStr);
|
||||||
|
|
||||||
|
|
@ -892,9 +855,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
||||||
|
|
||||||
K.SetHexStr (fields[2].GetString ());
|
K.SetHexStr (fields[2].GetString ());
|
||||||
|
|
||||||
time_t mutetime = time_t (fields[9].GetUInt64 ());
|
time_t mutetime = time_t (fields[8].GetUInt64 ());
|
||||||
|
|
||||||
locale = LocaleConstant (fields[10].GetUInt8 ());
|
locale = LocaleConstant (fields[9].GetUInt8 ());
|
||||||
if (locale >= MAX_LOCALE)
|
if (locale >= MAX_LOCALE)
|
||||||
locale = LOCALE_enUS;
|
locale = LOCALE_enUS;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -246,7 +246,6 @@ void AuthSocket::OnAccept()
|
||||||
sLog.outBasic("Accepting connection from '%s:%d'",
|
sLog.outBasic("Accepting connection from '%s:%d'",
|
||||||
GetRemoteAddress().c_str(), GetRemotePort());
|
GetRemoteAddress().c_str(), GetRemotePort());
|
||||||
|
|
||||||
s.SetRand(s_BYTE_SIZE * 8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the packet from the client
|
/// Read the packet from the client
|
||||||
|
|
@ -295,6 +294,8 @@ void AuthSocket::OnRead()
|
||||||
/// Make the SRP6 calculation from hash in dB
|
/// Make the SRP6 calculation from hash in dB
|
||||||
void AuthSocket::_SetVSFields(const std::string& rI)
|
void AuthSocket::_SetVSFields(const std::string& rI)
|
||||||
{
|
{
|
||||||
|
s.SetRand(s_BYTE_SIZE * 8);
|
||||||
|
|
||||||
BigNumber I;
|
BigNumber I;
|
||||||
I.SetHexStr(rI.c_str());
|
I.SetHexStr(rI.c_str());
|
||||||
|
|
||||||
|
|
@ -396,7 +397,7 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||||
///- Get the account details from the account table
|
///- Get the account details from the account table
|
||||||
// No SQL injection (escaped user name)
|
// No SQL injection (escaped user name)
|
||||||
|
|
||||||
result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ());
|
result = loginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel,v,s FROM account WHERE username = '%s'",_safelogin.c_str ());
|
||||||
if( result )
|
if( result )
|
||||||
{
|
{
|
||||||
///- If the IP is 'locked', check that the player comes indeed from the correct IP address
|
///- If the IP is 'locked', check that the player comes indeed from the correct IP address
|
||||||
|
|
@ -446,7 +447,21 @@ bool AuthSocket::_HandleLogonChallenge()
|
||||||
{
|
{
|
||||||
///- Get the password from the account table, upper it, and make the SRP6 calculation
|
///- Get the password from the account table, upper it, and make the SRP6 calculation
|
||||||
std::string rI = (*result)[0].GetCppString();
|
std::string rI = (*result)[0].GetCppString();
|
||||||
_SetVSFields(rI);
|
|
||||||
|
///- Don't calculate (v, s) if there are already some in the database
|
||||||
|
std::string databaseV = (*result)[5].GetCppString();
|
||||||
|
std::string databaseS = (*result)[6].GetCppString();
|
||||||
|
|
||||||
|
sLog.outDebug("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());
|
||||||
|
|
||||||
|
// multiply with 2, bytes are stored as hexstring
|
||||||
|
if(databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2)
|
||||||
|
_SetVSFields(rI);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.SetHexStr(databaseS.c_str());
|
||||||
|
v.SetHexStr(databaseV.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
b.SetRand(19 * 8);
|
b.SetRand(19 * 8);
|
||||||
BigNumber gmod = g.ModExp(b, N);
|
BigNumber gmod = g.ModExp(b, N);
|
||||||
|
|
@ -591,8 +606,13 @@ bool AuthSocket::_HandleLogonProof()
|
||||||
|
|
||||||
///- Continue the SRP6 calculation based on data received from the client
|
///- Continue the SRP6 calculation based on data received from the client
|
||||||
BigNumber A;
|
BigNumber A;
|
||||||
|
|
||||||
A.SetBinary(lp.A, 32);
|
A.SetBinary(lp.A, 32);
|
||||||
|
|
||||||
|
// SRP safeguard: abort if A==0
|
||||||
|
if (A.isZero())
|
||||||
|
return false;
|
||||||
|
|
||||||
Sha1Hash sha;
|
Sha1Hash sha;
|
||||||
sha.UpdateBigNumbers(&A, &B, NULL);
|
sha.UpdateBigNumbers(&A, &B, NULL);
|
||||||
sha.Finalize();
|
sha.Finalize();
|
||||||
|
|
@ -603,7 +623,7 @@ bool AuthSocket::_HandleLogonProof()
|
||||||
uint8 t[32];
|
uint8 t[32];
|
||||||
uint8 t1[16];
|
uint8 t1[16];
|
||||||
uint8 vK[40];
|
uint8 vK[40];
|
||||||
memcpy(t, S.AsByteArray(), 32);
|
memcpy(t, S.AsByteArray(32), 32);
|
||||||
for (int i = 0; i < 16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
{
|
{
|
||||||
t1[i] = t[i * 2];
|
t1[i] = t[i * 2];
|
||||||
|
|
@ -905,8 +925,6 @@ bool AuthSocket::_HandleRealmList()
|
||||||
|
|
||||||
SendBuf((char const*)hdr.contents(), hdr.size());
|
SendBuf((char const*)hdr.contents(), hdr.size());
|
||||||
|
|
||||||
// Set check field before possible relogin to realm
|
|
||||||
_SetVSFields(rI);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ extern int main(int argc, char **argv)
|
||||||
sLog.outError("Could not find configuration file %s.", cfg_file);
|
sLog.outError("Could not find configuration file %s.", cfg_file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
sLog.Initialize();
|
||||||
|
|
||||||
sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
|
sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
|
||||||
sLog.outString( "<Ctrl-C> to stop.\n" );
|
sLog.outString( "<Ctrl-C> to stop.\n" );
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,11 @@ uint32 BigNumber::AsDword()
|
||||||
return (uint32)BN_get_word(_bn);
|
return (uint32)BN_get_word(_bn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BigNumber::isZero() const
|
||||||
|
{
|
||||||
|
return BN_is_zero(_bn)!=0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8 *BigNumber::AsByteArray(int minSize)
|
uint8 *BigNumber::AsByteArray(int minSize)
|
||||||
{
|
{
|
||||||
int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
|
int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ class BigNumber
|
||||||
return t %= bn;
|
return t %= bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isZero() const;
|
||||||
|
|
||||||
BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
|
BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
|
||||||
BigNumber Exp(const BigNumber &);
|
BigNumber Exp(const BigNumber &);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8444"
|
#define REVISION_NR "8445"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue