Jump to content

Authsocket : Where is the password verification ?


Auntie Mangos

Recommended Posts

@Patman128

http://getmangos.eu/community/post/136475/#p136475

@XtremeX

_HandleLogonChallenge is where the user's account info is loaded from the DB and used to calculate B.

In _HandleLogonProof, everything before lines 594-668 are the server's SRP6 algorithm (line 668 is the comparison against the client's proof) - anything that follows is handling success/failure of that comparison.

The password is never inspected/compared directly. SRP6 calculates a cryptographic hash of the password - you can read info on it here: http://srp.stanford.edu/design.html

Link to comment
Share on other sites

  • 41 years later...

Hello,

I've looked the "Authsocket.cpp" and "Authsocket.h" scripts for to understand how it works, but i don't understand where is the password verification.

I think it's here :

[== c++ ==]
  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();
   BigNumber u;
   u.SetBinary(sha.GetDigest(), 20);
   BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N);

   uint8 t[32];
   uint8 t1[16];
   uint8 vK[40];
   memcpy(t, S.AsByteArray(32), 32);
   for (int i = 0; i < 16; ++i)
   {
       t1[i] = t[i * 2];
   }
   sha.Initialize();
   sha.UpdateData(t1, 16);
   sha.Finalize();
   for (int i = 0; i < 20; ++i)
   {
       vK[i * 2] = sha.GetDigest()[i];
   }
   for (int i = 0; i < 16; ++i)
   {
       t1[i] = t[i * 2 + 1];
   }
   sha.Initialize();
   sha.UpdateData(t1, 16);
   sha.Finalize();
   for (int i = 0; i < 20; ++i)
   {
       vK[i * 2 + 1] = sha.GetDigest()[i];
   }
   K.SetBinary(vK, 40);

   uint8 hash[20];

   sha.Initialize();
   sha.UpdateBigNumbers(&N, NULL);
   sha.Finalize();
   memcpy(hash, sha.GetDigest(), 20);
   sha.Initialize();
   sha.UpdateBigNumbers(&g, NULL);
   sha.Finalize();
   for (int i = 0; i < 20; ++i)
   {
       hash[i] ^= sha.GetDigest()[i];
   }
   BigNumber t3;
   t3.SetBinary(hash, 20);

   sha.Initialize();
   sha.UpdateData(_login);
   sha.Finalize();
   uint8 t4[sHA_DIGEST_LENGTH];
   memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH);

   sha.Initialize();
   sha.UpdateBigNumbers(&t3, NULL);
   sha.UpdateData(t4, SHA_DIGEST_LENGTH);
   sha.UpdateBigNumbers(&s, &A, &B, &K, NULL);
   sha.Finalize();
   BigNumber M;
   M.SetBinary(sha.GetDigest(), 20);

   ///- Check if SRP6 results match (password is correct), else send an error
   if (!memcmp(M.AsByteArray(), lp.M1, 20))
   {
       BASIC_LOG("User '%s' successfully authenticated", _login.c_str());

       ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
       // No SQL injection (escaped user name) and IP address as received by socket
       const char* K_hex = K.AsHexStr();
       LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, get_remote_address().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() );
       OPENSSL_free((void*)K_hex);

       ///- Finish SRP6 and send the final result to the client
       sha.Initialize();
       sha.UpdateBigNumbers(&A, &M, &K, NULL);
       sha.Finalize();

       SendProof(sha);

       ///- Set _authed to true!
       _authed = true;
   }
   else
   {
       if (_build > 6005) // > 1.12.2
       {
           char data[4] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0};
           send(data, sizeof(data));
       }
       else
       {
           // 1.x not react incorrectly at 4-byte message use 3 as real error
           char data[2] = { CMD_AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT};
           send(data, sizeof(data));
       }
       BASIC_LOG("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ());

       uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0);
       if(MaxWrongPassCount > 0)
       {
           //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
           LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str());

           if(QueryResult *loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str()))
           {
               Field* fields = loginfail->Fetch();
               uint32 failed_logins = fields[1].GetUInt32();

               if( failed_logins >= MaxWrongPassCount )
               {
                   uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600);
                   bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false);

                   if(WrongPassBanType)
                   {
                       uint32 acc_id = fields[0].GetUInt32();
                       LoginDatabase.PExecute("INSERT INTO account_banned VALUES
('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban',1)",
                           acc_id, WrongPassBanTime);
                       BASIC_LOG("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
                           _login.c_str(), WrongPassBanTime, failed_logins);
                   }
                   else
                   {
                       std::string current_ip = get_remote_address();
                       LoginDatabase.escape_string(current_ip);
                       LoginDatabase.PExecute("INSERT INTO ip_banned VALUES
('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','MaNGOS realmd','Failed login autoban')",
                           current_ip.c_str(), WrongPassBanTime);
                       BASIC_LOG("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times",
                           current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins);
                   }
               }
               delete loginfail;
           }
       }
   }

But I don't understand where is the comparison with the password in the database..

Can someone help me to understand it please ?

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use