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);
|
||||
|
||||
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_OK;
|
||||
|
|
|
|||
|
|
@ -119,9 +119,6 @@ class CharacterHandler
|
|||
|
||||
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
|
||||
|
||||
uint8 num = 0;
|
||||
|
|
|
|||
|
|
@ -760,7 +760,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
|||
LocaleConstant locale;
|
||||
std::string account;
|
||||
Sha1Hash sha1;
|
||||
BigNumber v, s, g, N, x, I;
|
||||
BigNumber v, s, g, N;
|
||||
WorldPacket packet, SendAddonPacked;
|
||||
|
||||
BigNumber K;
|
||||
|
|
@ -792,12 +792,11 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
|||
"sessionkey, " //2
|
||||
"last_ip, " //3
|
||||
"locked, " //4
|
||||
"sha_pass_hash, " //5
|
||||
"v, " //6
|
||||
"s, " //7
|
||||
"expansion, " //8
|
||||
"mutetime, " //9
|
||||
"locale " //10
|
||||
"v, " //5
|
||||
"s, " //6
|
||||
"expansion, " //7
|
||||
"mutetime, " //8
|
||||
"locale " //9
|
||||
"FROM account "
|
||||
"WHERE username = '%s'",
|
||||
safe_account.c_str ());
|
||||
|
|
@ -816,57 +815,21 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
|||
|
||||
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");
|
||||
g.SetDword (7);
|
||||
I.SetHexStr (fields[5].GetString ());
|
||||
|
||||
//In case of leading zeros in the I hash, restore them
|
||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||
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);
|
||||
v.SetHexStr(fields[5].GetString());
|
||||
s.SetHexStr (fields[6].GetString ());
|
||||
|
||||
const char* sStr = s.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,
|
||||
vold,
|
||||
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*) vStr);
|
||||
|
||||
|
|
@ -892,9 +855,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket)
|
|||
|
||||
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)
|
||||
locale = LOCALE_enUS;
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,6 @@ void AuthSocket::OnAccept()
|
|||
sLog.outBasic("Accepting connection from '%s:%d'",
|
||||
GetRemoteAddress().c_str(), GetRemotePort());
|
||||
|
||||
s.SetRand(s_BYTE_SIZE * 8);
|
||||
}
|
||||
|
||||
/// Read the packet from the client
|
||||
|
|
@ -295,6 +294,8 @@ void AuthSocket::OnRead()
|
|||
/// Make the SRP6 calculation from hash in dB
|
||||
void AuthSocket::_SetVSFields(const std::string& rI)
|
||||
{
|
||||
s.SetRand(s_BYTE_SIZE * 8);
|
||||
|
||||
BigNumber I;
|
||||
I.SetHexStr(rI.c_str());
|
||||
|
||||
|
|
@ -396,7 +397,7 @@ bool AuthSocket::_HandleLogonChallenge()
|
|||
///- Get the account details from the account table
|
||||
// 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 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
|
||||
std::string rI = (*result)[0].GetCppString();
|
||||
|
||||
///- 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);
|
||||
BigNumber gmod = g.ModExp(b, N);
|
||||
|
|
@ -591,8 +606,13 @@ bool AuthSocket::_HandleLogonProof()
|
|||
|
||||
///- Continue the SRP6 calculation based on data received from the client
|
||||
BigNumber A;
|
||||
|
||||
A.SetBinary(lp.A, 32);
|
||||
|
||||
// SRP safeguard: abort if A==0
|
||||
if (A.isZero())
|
||||
return false;
|
||||
|
||||
Sha1Hash sha;
|
||||
sha.UpdateBigNumbers(&A, &B, NULL);
|
||||
sha.Finalize();
|
||||
|
|
@ -603,7 +623,7 @@ bool AuthSocket::_HandleLogonProof()
|
|||
uint8 t[32];
|
||||
uint8 t1[16];
|
||||
uint8 vK[40];
|
||||
memcpy(t, S.AsByteArray(), 32);
|
||||
memcpy(t, S.AsByteArray(32), 32);
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
t1[i] = t[i * 2];
|
||||
|
|
@ -905,8 +925,6 @@ bool AuthSocket::_HandleRealmList()
|
|||
|
||||
SendBuf((char const*)hdr.contents(), hdr.size());
|
||||
|
||||
// Set check field before possible relogin to realm
|
||||
_SetVSFields(rI);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ extern int main(int argc, char **argv)
|
|||
sLog.outError("Could not find configuration file %s.", cfg_file);
|
||||
return 1;
|
||||
}
|
||||
sLog.Initialize();
|
||||
|
||||
sLog.outString( "%s [realm-daemon]", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID) );
|
||||
sLog.outString( "<Ctrl-C> to stop.\n" );
|
||||
|
|
|
|||
|
|
@ -159,6 +159,11 @@ uint32 BigNumber::AsDword()
|
|||
return (uint32)BN_get_word(_bn);
|
||||
}
|
||||
|
||||
bool BigNumber::isZero() const
|
||||
{
|
||||
return BN_is_zero(_bn)!=0;
|
||||
}
|
||||
|
||||
uint8 *BigNumber::AsByteArray(int minSize)
|
||||
{
|
||||
int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ class BigNumber
|
|||
return t %= bn;
|
||||
}
|
||||
|
||||
bool isZero() const;
|
||||
|
||||
BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
|
||||
BigNumber Exp(const BigNumber &);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8444"
|
||||
#define REVISION_NR "8445"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue