Advertisement
Guest User

Untitled

a guest
May 27th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.64 KB | None | 0 0
  1. /// Logon Challenge command handler
  2. bool AuthSocket::_HandleLogonChallenge()
  3. {
  4. DEBUG_LOG("Entering _HandleLogonChallenge");
  5. if (recv_len() < sizeof(sAuthLogonChallenge_C))
  6. return false;
  7.  
  8. ///- Read the first 4 bytes (header) to get the length of the remaining of the packet
  9. std::vector<uint8> buf;
  10. buf.resize(4);
  11.  
  12. recv((char *)&buf[0], 4);
  13.  
  14. EndianConvert(*((uint16*)(buf[0])));
  15. uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
  16. DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining);
  17.  
  18. if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (recv_len() < remaining))
  19. return false;
  20.  
  21. //No big fear of memory outage (size is int16, i.e. < 65536)
  22. buf.resize(remaining + buf.size() + 1);
  23. buf[buf.size() - 1] = 0;
  24. sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0];
  25.  
  26. ///- Read the remaining of the packet
  27. recv((char *)&buf[4], remaining);
  28. DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size);
  29. DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I);
  30.  
  31. // BigEndian code, nop in little endian case
  32. // size already converted
  33. EndianConvert(*((uint32*)(&ch->gamename[0])));
  34. EndianConvert(ch->build);
  35. EndianConvert(*((uint32*)(&ch->platform[0])));
  36. EndianConvert(*((uint32*)(&ch->os[0])));
  37. EndianConvert(*((uint32*)(&ch->country[0])));
  38. EndianConvert(ch->timezone_bias);
  39. EndianConvert(ch->ip);
  40.  
  41. ByteBuffer pkt;
  42.  
  43. _login = (const char*)ch->I;
  44. _build = ch->build;
  45.  
  46. ///- Normalize account name
  47. //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form
  48.  
  49. //Escape the user login to avoid further SQL injection
  50. //Memory will be freed on AuthSocket object destruction
  51. _safelogin = _login;
  52. loginDatabase.escape_string(_safelogin);
  53.  
  54. pkt << (uint8) AUTH_LOGON_CHALLENGE;
  55. pkt << (uint8) 0x00;
  56.  
  57. ///- Verify that this IP is not in the ip_banned table
  58. // No SQL injection possible (paste the IP address as passed by the socket)
  59. std::string address = get_remote_address();
  60. loginDatabase.escape_string(address);
  61. QueryResult *result = loginDatabase.PQuery("SELECT unbandate FROM ip_banned WHERE "
  62. // permanent still banned
  63. "(unbandate = bandate OR unbandate > UNIX_TIMESTAMP()) AND ip = '%s'", address.c_str());
  64. if (result)
  65. {
  66. pkt << (uint8)WOW_FAIL_BANNED;
  67. BASIC_LOG("[AuthChallenge] Banned ip %s tries to login!", get_remote_address().c_str());
  68. delete result;
  69. }
  70. else
  71. {
  72. ///- Get the account details from the account table
  73. // No SQL injection (escaped user name)
  74. result =
  75. loginDatabase.PQuery("SELECT a.sha_pass_hash,a.id,a.locked,a.last_ip,aa.gmlevel,a.v,a.s "
  76. "FROM account a "
  77. "LEFT JOIN account_access aa "
  78. "ON (a.id = aa.id) "
  79. "WHERE a.username = '%s'",_safelogin.c_str ());
  80. if (result)
  81. {
  82. ///- If the IP is 'locked', check that the player comes indeed from the correct IP address
  83. bool locked = false;
  84. if((*result)[2].GetUInt8() == 1) // if ip is locked
  85. {
  86. DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString());
  87. DEBUG_LOG("[AuthChallenge] Player address is '%s'", get_remote_address().c_str());
  88. if ( strcmp((*result)[3].GetString(),get_remote_address().c_str()) )
  89. {
  90. DEBUG_LOG("[AuthChallenge] Account IP differs");
  91. pkt << (uint8) WOW_FAIL_SUSPENDED;
  92. locked=true;
  93. }
  94. else
  95. {
  96. DEBUG_LOG("[AuthChallenge] Account IP matches");
  97. }
  98. }
  99. else
  100. {
  101. DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str());
  102. }
  103.  
  104. if (!locked)
  105. {
  106. ///- If the account is banned, reject the logon attempt
  107. QueryResult *banresult = loginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE "
  108. "id = %u AND active = 1 AND (unbandate > UNIX_TIMESTAMP() OR unbandate = bandate)", (*result)[1].GetUInt32());
  109. if(banresult)
  110. {
  111. if((*banresult)[0].GetUInt64() != (*banresult)[1].GetUInt64())
  112. {
  113. pkt << (uint8) WOW_FAIL_BANNED;
  114. BASIC_LOG("[AuthChallenge] Banned account %s tries to login!",_login.c_str ());
  115. }
  116. else
  117. {
  118. pkt << (uint8) WOW_FAIL_SUSPENDED;
  119. BASIC_LOG("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ());
  120. }
  121.  
  122. delete banresult;
  123. }
  124. else
  125. {
  126. ///- Get the password from the account table, upper it, and make the SRP6 calculation
  127. std::string rI = (*result)[0].GetCppString();
  128.  
  129. ///- Don't calculate (v, s) if there are already some in the database
  130. std::string databaseV = (*result)[5].GetCppString();
  131. std::string databaseS = (*result)[6].GetCppString();
  132.  
  133. DEBUG_LOG("database authentication values: v='%s' s='%s'", databaseV.c_str(), databaseS.c_str());
  134.  
  135. // multiply with 2, bytes are stored as hexstring
  136. if(databaseV.size() != s_BYTE_SIZE*2 || databaseS.size() != s_BYTE_SIZE*2)
  137. _SetVSFields(rI);
  138. else
  139. {
  140. s.SetHexStr(databaseS.c_str());
  141. v.SetHexStr(databaseV.c_str());
  142. }
  143.  
  144. b.SetRand(19 * 8);
  145. BigNumber gmod = g.ModExp(b, N);
  146. B = ((v * 3) + gmod) % N;
  147.  
  148. ASSERT(gmod.GetNumBytes() <= 32);
  149.  
  150. BigNumber unk3;
  151. unk3.SetRand(16 * 8);
  152.  
  153. ///- Fill the response packet with the result
  154. pkt << uint8(WOW_SUCCESS);
  155.  
  156. // B may be calculated < 32B so we force minimal length to 32B
  157. pkt.append(B.AsByteArray(32), 32); // 32 bytes
  158. pkt << uint8(1);
  159. pkt.append(g.AsByteArray(), 1);
  160. pkt << uint8(32);
  161. pkt.append(N.AsByteArray(32), 32);
  162. pkt.append(s.AsByteArray(), s.GetNumBytes());// 32 bytes
  163. pkt.append(unk3.AsByteArray(16), 16);
  164. uint8 securityFlags = 0;
  165. pkt << uint8(securityFlags); // security flags (0x0...0x04)
  166.  
  167. if(securityFlags & 0x01) // PIN input
  168. {
  169. pkt << uint32(0);
  170. pkt << uint64(0) << uint64(0); // 16 bytes hash?
  171. }
  172.  
  173. if(securityFlags & 0x02) // Matrix input
  174. {
  175. pkt << uint8(0);
  176. pkt << uint8(0);
  177. pkt << uint8(0);
  178. pkt << uint8(0);
  179. pkt << uint64(0);
  180. }
  181.  
  182. if(securityFlags & 0x04) // Security token input
  183. {
  184. pkt << uint8(1);
  185. }
  186.  
  187. uint8 secLevel = (*result)[4].GetUInt8();
  188. _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR;
  189.  
  190. _localizationName.resize(4);
  191. for(int i = 0; i < 4; ++i)
  192. _localizationName[i] = ch->country[4-i-1];
  193.  
  194. 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));
  195. }
  196. }
  197. delete result;
  198. }
  199. else // no account
  200. {
  201. pkt<< (uint8) WOW_FAIL_UNKNOWN_ACCOUNT;
  202. }
  203. }
  204. send((char const*)pkt.contents(), pkt.size());
  205. return true;
  206. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement