Skip to content

Instantly share code, notes, and snippets.

@callmephil
Last active July 8, 2016 12:50
Show Gist options
  • Save callmephil/f7081a717265917622fd to your computer and use it in GitHub Desktop.
Save callmephil/f7081a717265917622fd to your computer and use it in GitHub Desktop.
Auto Account Creation [Trinity 4.3.4] [justin7674 (Ac-Web)]
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index 91a2ff9..b3a1d34 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -22,11 +22,13 @@
#include "Database/DatabaseEnv.h"
#include "SHA1.h"
#include "TOTP.h"
+#include "Util.h"
#include "openssl/crypto.h"
#include "Configuration/Config.h"
#include "RealmList.h"
#include <boost/lexical_cast.hpp>
+
using boost::asio::ip::tcp;
enum eAuthCmd
@@ -179,7 +181,7 @@ void AuthSession::AsyncWrite(ByteBuffer& packet)
_writeQueue.push(std::move(packet));
if (needsWriteStart)
- AuthSocket::AsyncWrite(_writeQueue.front());
+ Base::AsyncWrite(_writeQueue.front());
}
bool AuthSession::HandleLogonChallenge()
@@ -334,9 +336,7 @@ bool AuthSession::HandleLogonChallenge()
unk3.SetRand(16 * 8);
// Fill the response packet with the result
- if (fields[9].GetUInt32() && AuthHelper::IsBuildSupportingBattlenet(_build))
- pkt << uint8(WOW_FAIL_USE_BATTLENET);
- else if (AuthHelper::IsAcceptedClientBuild(_build))
+ if (AuthHelper::IsAcceptedClientBuild(_build))
pkt << uint8(WOW_SUCCESS);
else
pkt << uint8(WOW_FAIL_VERSION_INVALID);
@@ -391,10 +391,29 @@ bool AuthSession::HandleLogonChallenge()
}
}
}
- else //no account
- pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
- }
-
+ else
+ { //no account
+
+
+ if (utf8length(_login) > 36){ // username's too long
+ pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
+ }else{
+
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT);
+ _regstatus = "Registering";
+ stmt->setString(0, _login);
+ stmt->setString(1, "SETONAUTH");
+ stmt->setString(2, "");
+ stmt->setString(3, "");
+
+ LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail
+
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT);
+ LoginDatabase.Execute(stmt);
+ //pkt << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
+ }
+ }
+ }
AsyncWrite(pkt);
return true;
}
@@ -491,144 +510,235 @@ bool AuthSession::HandleLogonProof()
M.SetBinary(sha.GetDigest(), sha.GetLength());
// Check if SRP6 results match (password is correct), else send an error
- if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20))
- {
- TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str());
-
- // Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account
- PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
- stmt->setString(0, K.AsHexStr());
- stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
- stmt->setUInt32(2, GetLocaleByName(_localizationName));
- stmt->setString(3, _os);
- stmt->setString(4, _login);
- LoginDatabase.DirectExecute(stmt);
-
- // Finish SRP6 and send the final result to the client
- sha.Initialize();
- sha.UpdateBigNumbers(&A, &M, &K, NULL);
- sha.Finalize();
-
- // Check auth token
- if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty())
- {
- ReadData(1);
- uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C));
- ReadData(size);
- std::string token(reinterpret_cast<char*>(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size);
- uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str());
- uint32 incomingToken = atoi(token.c_str());
- if (validToken != incomingToken)
- {
- ByteBuffer packet;
- packet << uint8(AUTH_LOGON_PROOF);
- packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
- packet << uint8(3);
- packet << uint8(0);
- AsyncWrite(packet);
- return false;
- }
- }
-
- ByteBuffer packet;
- if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
- {
- sAuthLogonProof_S proof;
- memcpy(proof.M2, sha.GetDigest(), 20);
- proof.cmd = AUTH_LOGON_PROOF;
- proof.error = 0;
- proof.AccountFlags = GAMEACCOUNT_FLAG_PROPASS_LOCK;
- proof.SurveyId = 0;
- proof.unk3 = 0;
-
- packet.resize(sizeof(proof));
- std::memcpy(packet.contents(), &proof, sizeof(proof));
- }
- else
- {
- sAuthLogonProof_S_Old proof;
- memcpy(proof.M2, sha.GetDigest(), 20);
- proof.cmd = AUTH_LOGON_PROOF;
- proof.error = 0;
- proof.unk2 = 0x00;
-
- packet.resize(sizeof(proof));
- std::memcpy(packet.contents(), &proof, sizeof(proof));
- }
-
- AsyncWrite(packet);
- _isAuthenticated = true;
- }
- else
- {
- ByteBuffer packet;
- packet << uint8(AUTH_LOGON_PROOF);
- packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
- packet << uint8(3);
- packet << uint8(0);
- AsyncWrite(packet);
-
- TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!",
- GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str());
-
- uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0);
-
- // We can not include the failed account login hook. However, this is a workaround to still log this.
- if (sConfigMgr->GetBoolDefault("Wrong.Password.Login.Logging", false))
- {
- PreparedStatement* logstmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FALP_IP_LOGGING);
- logstmt->setString(0, _login);
- logstmt->setString(1, GetRemoteIpAddress().to_string());
- logstmt->setString(2, "Logged on failed AccountLogin due wrong password");
-
- LoginDatabase.Execute(logstmt);
- }
-
- if (MaxWrongPassCount > 0)
- {
- //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
- PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_FAILEDLOGINS);
- stmt->setString(0, _login);
- LoginDatabase.Execute(stmt);
-
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_FAILEDLOGINS);
- stmt->setString(0, _login);
-
- if (PreparedQueryResult loginfail = LoginDatabase.Query(stmt))
- {
- uint32 failed_logins = (*loginfail)[1].GetUInt32();
-
- if (failed_logins >= MaxWrongPassCount)
- {
- uint32 WrongPassBanTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600);
- bool WrongPassBanType = sConfigMgr->GetBoolDefault("WrongPass.BanType", false);
-
- if (WrongPassBanType)
- {
- uint32 acc_id = (*loginfail)[0].GetUInt32();
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED);
- stmt->setUInt32(0, acc_id);
- stmt->setUInt32(1, WrongPassBanTime);
- LoginDatabase.Execute(stmt);
-
- TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
- GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str(), WrongPassBanTime, failed_logins);
- }
- else
- {
- stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED);
- stmt->setString(0, GetRemoteIpAddress().to_string());
- stmt->setUInt32(1, WrongPassBanTime);
- LoginDatabase.Execute(stmt);
-
- TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] IP got banned for '%u' seconds because account %s failed to authenticate '%u' times",
- GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), WrongPassBanTime, _login.c_str(), failed_logins);
- }
- }
- }
- }
- }
-
+ if(_regstatus == "Registering"){
+
+ PreparedStatement *stmts2 = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME);
+ stmts2->setString(0, _login);
+ PreparedQueryResult uidr = LoginDatabase.Query(stmts2);
+ if(uidr){
+ PreparedStatement *stmts = LoginDatabase.GetPreparedStatement(LOGIN_UPD_PASSWORD);
+ stmts->setString(0, ByteArrayToHexStr(sha.GetDigest(), sha.GetLength()));
+ stmts->setUInt32(1, (*uidr)[0].GetUInt32());
+
+ LoginDatabase.DirectExecute(stmts);
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _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();
+
+ PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
+ stmt->setString(0, K_hex);
+ stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
+ stmt->setUInt32(2, GetLocaleByName(_localizationName));
+ stmt->setString(3, _os);
+ stmt->setString(4, _login);
+ LoginDatabase.DirectExecute(stmt);
+
+ 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();
+
+ // Check auth token
+ if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty())
+ {
+ ReadData(1);
+ uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C));
+ ReadData(size);
+ std::string token(reinterpret_cast<char*>(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size);
+ uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str());
+ uint32 incomingToken = atoi(token.c_str());
+ if (validToken != incomingToken)
+ {
+ ByteBuffer packet;
+ packet << uint8(AUTH_LOGON_PROOF);
+ packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
+ packet << uint8(3);
+ packet << uint8(0);
+ AsyncWrite(packet);
+ return false;
+ }
+ }
+
+ ByteBuffer packet;
+ if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
+ {
+ sAuthLogonProof_S proof;
+ memcpy(proof.M2, sha.GetDigest(), 20);
+ proof.cmd = AUTH_LOGON_PROOF;
+ proof.error = 0;
+ proof.AccountFlags = 0x00800000; // 0x01 = GM, 0x08 = Trial, 0x00800000 = Pro pass (arena tournament)
+ proof.SurveyId = 0;
+ proof.unk3 = 0;
+
+ packet.resize(sizeof(proof));
+ std::memcpy(packet.contents(), &proof, sizeof(proof));
+ }
+ else
+ {
+ sAuthLogonProof_S_Old proof;
+ memcpy(proof.M2, sha.GetDigest(), 20);
+ proof.cmd = AUTH_LOGON_PROOF;
+ proof.error = 0;
+ proof.unk2 = 0x00;
+
+ packet.resize(sizeof(proof));
+ std::memcpy(packet.contents(), &proof, sizeof(proof));
+ }
+
+ AsyncWrite(packet);
+ _isAuthenticated = true;
+ }else{
+ //Ehhh wtf happened to get here? DOH for some reason the user still doesn't exist.
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' not valid despite attempting it's creation", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str());
+ }
+ }else{
+ if (!memcmp(M.AsByteArray(sha.GetLength()).get(), logonProof->M1, 20))
+ {
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' User '%s' successfully authenticated", GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _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();
+
+ PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LOGONPROOF);
+ stmt->setString(0, K_hex);
+ stmt->setString(1, GetRemoteIpAddress().to_string().c_str());
+ stmt->setUInt32(2, GetLocaleByName(_localizationName));
+ stmt->setString(3, _os);
+ stmt->setString(4, _login);
+ LoginDatabase.DirectExecute(stmt);
+
+ 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();
+
+ // Check auth token
+ if ((logonProof->securityFlags & 0x04) || !_tokenKey.empty())
+ {
+ ReadData(1);
+ uint8 size = *(GetDataBuffer() + sizeof(sAuthLogonProof_C));
+ ReadData(size);
+ std::string token(reinterpret_cast<char*>(GetDataBuffer() + sizeof(sAuthLogonProof_C) + sizeof(size)), size);
+ uint32 validToken = TOTP::GenerateToken(_tokenKey.c_str());
+ uint32 incomingToken = atoi(token.c_str());
+ if (validToken != incomingToken)
+ {
+ ByteBuffer packet;
+ packet << uint8(AUTH_LOGON_PROOF);
+ packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
+ packet << uint8(3);
+ packet << uint8(0);
+ AsyncWrite(packet);
+ return false;
+ }
+ }
+
+ ByteBuffer packet;
+ if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients
+ {
+ sAuthLogonProof_S proof;
+ memcpy(proof.M2, sha.GetDigest(), 20);
+ proof.cmd = AUTH_LOGON_PROOF;
+ proof.error = 0;
+ proof.AccountFlags = 0x00800000; // 0x01 = GM, 0x08 = Trial, 0x00800000 = Pro pass (arena tournament)
+ proof.SurveyId = 0;
+ proof.unk3 = 0;
+
+ packet.resize(sizeof(proof));
+ std::memcpy(packet.contents(), &proof, sizeof(proof));
+ }
+ else
+ {
+ sAuthLogonProof_S_Old proof;
+ memcpy(proof.M2, sha.GetDigest(), 20);
+ proof.cmd = AUTH_LOGON_PROOF;
+ proof.error = 0;
+ proof.unk2 = 0x00;
+
+ packet.resize(sizeof(proof));
+ std::memcpy(packet.contents(), &proof, sizeof(proof));
+ }
+
+ AsyncWrite(packet);
+ _isAuthenticated = true;
+ }
+ else
+ {
+ ByteBuffer packet;
+ packet << uint8(AUTH_LOGON_PROOF);
+ packet << uint8(WOW_FAIL_UNKNOWN_ACCOUNT);
+ packet << uint8(3);
+ packet << uint8(0);
+ AsyncWrite(packet);
+
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s tried to login with invalid password!",
+ GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str());
+
+ uint32 MaxWrongPassCount = sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0);
+
+ // We can not include the failed account login hook. However, this is a workaround to still log this.
+ if (sConfigMgr->GetBoolDefault("Wrong.Password.Login.Logging", false))
+ {
+ PreparedStatement* logstmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_FALP_IP_LOGGING);
+ logstmt->setString(0, _login);
+ logstmt->setString(1, GetRemoteIpAddress().to_string());
+ logstmt->setString(2, "Logged on failed AccountLogin due wrong password");
+
+ LoginDatabase.Execute(logstmt);
+ }
+
+ if (MaxWrongPassCount > 0)
+ {
+ //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_FAILEDLOGINS);
+ stmt->setString(0, _login);
+ LoginDatabase.Execute(stmt);
+
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_FAILEDLOGINS);
+ stmt->setString(0, _login);
+
+ if (PreparedQueryResult loginfail = LoginDatabase.Query(stmt))
+ {
+ uint32 failed_logins = (*loginfail)[1].GetUInt32();
+
+ if (failed_logins >= MaxWrongPassCount)
+ {
+ uint32 WrongPassBanTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600);
+ bool WrongPassBanType = sConfigMgr->GetBoolDefault("WrongPass.BanType", false);
+
+ if (WrongPassBanType)
+ {
+ uint32 acc_id = (*loginfail)[0].GetUInt32();
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED);
+ stmt->setUInt32(0, acc_id);
+ stmt->setUInt32(1, WrongPassBanTime);
+ LoginDatabase.Execute(stmt);
+
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times",
+ GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), _login.c_str(), WrongPassBanTime, failed_logins);
+ }
+ else
+ {
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED);
+ stmt->setString(0, GetRemoteIpAddress().to_string());
+ stmt->setUInt32(1, WrongPassBanTime);
+ LoginDatabase.Execute(stmt);
+
+ TC_LOG_DEBUG("server.authserver", "'%s:%d' [AuthChallenge] IP got banned for '%u' seconds because account %s failed to authenticate '%u' times",
+ GetRemoteIpAddress().to_string().c_str(), GetRemotePort(), WrongPassBanTime, _login.c_str(), failed_logins);
+ }
+ }
+ }
+ }
+ }
+ }
return true;
}
@@ -719,6 +829,41 @@ bool AuthSession::HandleReconnectProof()
}
}
+tcp::endpoint const GetAddressForClient(Realm const& realm, ip::address const& clientAddr)
+{
+ ip::address realmIp;
+
+ // Attempt to send best address for client
+ if (clientAddr.is_loopback())
+ {
+ // Try guessing if realm is also connected locally
+ if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback())
+ realmIp = clientAddr;
+ else
+ {
+ // Assume that user connecting from the machine that authserver is located on
+ // has all realms available in his local network
+ realmIp = realm.LocalAddress;
+ }
+ }
+ else
+ {
+ if (clientAddr.is_v4() &&
+ (clientAddr.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()) ==
+ (realm.LocalAddress.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()))
+ {
+ realmIp = realm.LocalAddress;
+ }
+ else
+ realmIp = realm.ExternalAddress;
+ }
+
+ tcp::endpoint endpoint(realmIp, realm.port);
+
+ // Return external IP
+ return endpoint;
+}
+
bool AuthSession::HandleRealmList()
{
TC_LOG_DEBUG("server.authserver", "Entering _HandleRealmList");
@@ -788,7 +933,7 @@ bool AuthSession::HandleRealmList()
pkt << lock; // if 1, then realm locked
pkt << uint8(flag); // RealmFlags
pkt << name;
- pkt << boost::lexical_cast<std::string>(realm.GetAddressForClient(GetRemoteIpAddress()));
+ pkt << boost::lexical_cast<std::string>(GetAddressForClient(realm, GetRemoteIpAddress()));
pkt << realm.populationLevel;
pkt << AmountOfCharacters;
pkt << realm.timezone; // realm category
@@ -883,9 +1028,17 @@ void AuthSession::SetVSFields(const std::string& rI)
x.SetBinary(sha.GetDigest(), sha.GetLength());
v = g.ModExp(x, N);
+ // No SQL injection (username escaped)
+ char *v_hex, *s_hex;
+ v_hex = v.AsHexStr();
+ s_hex = s.AsHexStr();
+
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_VS);
- stmt->setString(0, v.AsHexStr());
- stmt->setString(1, s.AsHexStr());
+ stmt->setString(0, v_hex);
+ stmt->setString(1, s_hex);
stmt->setString(2, _login);
LoginDatabase.Execute(stmt);
+
+ OPENSSL_free(v_hex);
+ OPENSSL_free(s_hex);
}
warning: LF will be replaced by CRLF in src/server/authserver/Server/AuthSession.cpp.
The file will have its original line endings in your working directory.
diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
index 04ee339..8b25d25 100644
--- a/src/server/authserver/Server/AuthSession.h
+++ b/src/server/authserver/Server/AuthSession.h
@@ -32,11 +32,11 @@ struct AuthHandler;
class AuthSession : public Socket<AuthSession, ByteBuffer>
{
- typedef Socket<AuthSession, ByteBuffer> AuthSocket;
+ typedef Socket<AuthSession, ByteBuffer> Base;
public:
static std::unordered_map<uint8, AuthHandler> InitHandlers();
-
+
AuthSession(tcp::socket&& socket) : Socket(std::move(socket), 1),
_isAuthenticated(false), _build(0), _expversion(0), _accountSecurityLevel(SEC_PLAYER)
{
@@ -49,6 +49,7 @@ public:
AsyncReadHeader();
}
+ using Base::AsyncWrite;
void AsyncWrite(ByteBuffer& packet);
protected:
@@ -79,9 +80,10 @@ private:
std::string _login;
std::string _localizationName;
std::string _os;
+ std::string _regstatus;
uint16 _build;
uint8 _expversion;
-
+
AccountTypes _accountSecurityLevel;
};
warning: LF will be replaced by CRLF in src/server/authserver/Server/AuthSession.h.
The file will have its original line endings in your working directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment