Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// Logon Challenge command handler
- bool AuthSocket::_HandleLogonChallenge()
- {
- DEBUG_LOG("Entering _HandleLogonChallenge");
- if (recv_len() < sizeof(sAuthLogonChallenge_C))
- return false;
- ///- Read the first 4 bytes (header) to get the length of the remaining of the packet
- std::vector<uint8> buf;
- buf.resize(4);
- recv((char *)&buf[0], 4);
- EndianConvert(*((uint16*)(buf[0])));
- uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
- DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining);
- if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining))
- return false;
- //No big fear of memory outage (size is int16, i.e. < 65536)
- buf.resize(remaining + buf.size() + 1);
- buf[buf.size() - 1] = 0;
- sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];
- ///- Read the remaining of the packet
- recv((char *)&buf[4], remaining);
- DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
- DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);
- // BigEndian code, nop in little endian case
- // size already converted
- EndianConvert(*((uint32*)(&ch->gamename[0])));
- EndianConvert(ch->build);
- EndianConvert(*((uint32*)(&ch->platform[0])));
- EndianConvert(*((uint32*)(&ch->os[0])));
- EndianConvert(*((uint32*)(&ch->country[0])));
- EndianConvert(ch->timezone_bias);
- EndianConvert(ch->ip);
- ByteBuffer pkt;
- _login = (const char*)ch->I;
- _build = ch->build;
- ///- Normalize account name
- //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form
- //Escape the user login to avoid further SQL injection
- //Memory will be freed on AuthSocket object destruction
- _safelogin = _login;
- loginDatabase.escape_string(_safelogin);
- pkt << (uint8) AUTH_LOGON_CHALLENGE;
- pkt << (uint8) 0x00;
- ///- Verify that this IP is not in the ip_banned table
- // No SQL injection possible (paste the IP address as passed by the socket)
- std::string address = get_remote_address();
- loginDatabase.escape_string(address);
- QueryResult *result = loginDatabase.PQuery("SELECT unbandate FROM ip_banned WHERE "
- // permanent still banned
- "(unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", address.c_str());
- if (result)
- {
- pkt << (uint8)WOW_FAIL_BANNED;
- BASIC_LOG("[AuthChallenge] Banned ip %s tries to login!", get_remote_address().c_str());
- delete result;
- }
- else
- {
- ///- Get the account details from the account table
- // No SQL injection (escaped user name)
- result =
- loginDatabase.PQuery("SELECT a.sha_pass_hash,a.id,a.locked,a.last_ip,aa.gmlevel,a.v,a.s "
- "FROM account a "
- "LEFT JOIN account_access aa "
- "ON (a.id = aa.id) "
- "WHERE a.username = '%s'",_safelogin.c_str ());
- if (result)
- {
- ///- If the IP is 'locked', check that the player comes indeed from the correct IP address
- bool locked = false;
- if((*result)[2].GetUInt8() == 1) // if ip is locked
- {
- DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString());
- DEBUG_LOG("[AuthChallenge] Player address is '%s'", get_remote_address().c_str());
- if ( strcmp((*result)[3].GetString(),get_remote_address().c_str()) )
- {
- DEBUG_LOG("[AuthChallenge] Account IP differs");
- pkt << (uint8) WOW_FAIL_SUSPENDED;
- locked=true;
- }
- else
- {
- DEBUG_LOG("[AuthChallenge] Account IP matches");
- }
- }
- else
- {
- DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str());
- }
- if (!locked)
- {
- ///- If the account is banned, reject the logon attempt
- QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE "
- "id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)", (*result)[1].GetUInt32());
- if(banresult)
- {
- if((*banresult)[0].GetUInt64() != (*banresult)[1].GetUInt64())
- {
- pkt << (uint8) WOW_FAIL_BANNED;
- BASIC_LOG("[AuthChallenge] Banned account %s tries to login!",_login.c_str ());
- }
- else
- {
- pkt << (uint8) WOW_FAIL_SUSPENDED;
- BASIC_LOG("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ());
- }
- delete banresult;
- }
- else
- {
- ///- 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();
- DEBUG_LOG("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);
- B = ((v * 3) + gmod) % N;
- ASSERT(gmod.GetNumBytes() <= 32);
- BigNumber unk3;
- unk3.SetRand(16 * 8);
- ///- Fill the response packet with the result
- pkt << uint8(WOW_SUCCESS);
- // B may be calculated < 32B so we force minimal length to 32B
- pkt.append(B.AsByteArray(32), 32); // 32 bytes
- pkt << uint8(1);
- pkt.append(g.AsByteArray(), 1);
- pkt << uint8(32);
- pkt.append(N.AsByteArray(32), 32);
- pkt.append(s.AsByteArray(), s.GetNumBytes());// 32 bytes
- pkt.append(unk3.AsByteArray(16), 16);
- uint8 securityFlags = 0;
- pkt << uint8(securityFlags); // security flags (0x0...0x04)
- if(securityFlags & 0x01) // PIN input
- {
- pkt << uint32(0);
- pkt << uint64(0) << uint64(0); // 16 bytes hash?
- }
- if(securityFlags & 0x02) // Matrix input
- {
- pkt << uint8(0);
- pkt << uint8(0);
- pkt << uint8(0);
- pkt << uint8(0);
- pkt << uint64(0);
- }
- if(securityFlags & 0x04) // Security token input
- {
- pkt << uint8(1);
- }
- uint8 secLevel = (*result)[4].GetUInt8();
- _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
- _localizationName.resize(4);
- for(int i = 0; i < 4; ++i)
- _localizationName[i] = ch->country[4-i-1];
- BASIC_LOG("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3], ch->country[2], ch->country[1], ch->country[0], GetLocaleByName(_localizationName));
- }
- }
- delete result;
- }
- else // no account
- {
- pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT;
- }
- }
- send((char const*)pkt.contents(), pkt.size());
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement