Skip to content

Commit 45783b8

Browse files
committed
Added password append option to enable http login from any ip: 'authserial <name> httppass'
1 parent 22a82aa commit 45783b8

File tree

7 files changed

+94
-30
lines changed

7 files changed

+94
-30
lines changed

Server/mods/deathmatch/logic/CAccount.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#include "StdInc.h"
1616

17-
CAccount::CAccount ( CAccountManager* pManager, EAccountType accountType, const std::string& strName, const std::string& strPassword, int iUserID, const std::string& strIP, const std::string& strSerial )
17+
CAccount::CAccount ( CAccountManager* pManager, EAccountType accountType, const std::string& strName, const std::string& strPassword, int iUserID, const std::string& strIP, const std::string& strSerial, const SString& strHttpPassAppend )
1818
{
1919
m_uiScriptID = CIdArray::PopUniqueId ( this, EIdClass::ACCOUNT );
2020
m_pClient = NULL;
@@ -26,6 +26,7 @@ CAccount::CAccount ( CAccountManager* pManager, EAccountType accountType, const
2626
m_iUserID = iUserID;
2727
m_strIP = strIP;
2828
m_strSerial = strSerial;
29+
m_strHttpPassAppend = strHttpPassAppend;
2930

3031
m_pManager->AddToList ( this );
3132

@@ -65,9 +66,31 @@ void CAccount::SetClient( CClient* pClient )
6566
}
6667

6768

68-
bool CAccount::IsPassword ( const SString& strPassword )
69+
bool CAccount::IsPassword(const SString& strPassword, bool* pbUsedHttpPassAppend)
6970
{
70-
return m_Password.IsPassword( strPassword );
71+
if (pbUsedHttpPassAppend == nullptr)
72+
{
73+
return m_Password.IsPassword(strPassword);
74+
}
75+
else
76+
{
77+
if (m_Password.IsPassword(strPassword))
78+
{
79+
*pbUsedHttpPassAppend = false;
80+
return true;
81+
}
82+
else
83+
{
84+
SString strPasswordHead = strPassword.Left(strPassword.length() - m_strHttpPassAppend.length());
85+
SString strPasswordTail = strPassword.Right(m_strHttpPassAppend.length());
86+
if (m_Password.IsPassword(strPasswordHead) && strPasswordTail == m_strHttpPassAppend)
87+
{
88+
*pbUsedHttpPassAppend = true;
89+
return true;
90+
}
91+
return false;
92+
}
93+
}
7194
}
7295

7396

@@ -87,6 +110,13 @@ SString CAccount::GetPasswordHash ( void )
87110
}
88111

89112

113+
void CAccount::SetHttpPassAppend( const SString& strHttpPassAppend )
114+
{
115+
m_strHttpPassAppend = strHttpPassAppend;
116+
m_pManager->MarkAsChanged ( this );
117+
}
118+
119+
90120
CAccountData* CAccount::GetDataPointer ( const std::string& strKey )
91121
{
92122
return MapFind( m_Data, strKey );

Server/mods/deathmatch/logic/CAccount.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class CAccount
6767
};
6868

6969
ZERO_ON_NEW
70-
CAccount ( class CAccountManager* pManager, EAccountType accountType, const std::string& strName, const std::string& strPassword = "", int iUserID = 0, const std::string& strIP = "", const std::string& strSerial = "" );
70+
CAccount ( class CAccountManager* pManager, EAccountType accountType, const std::string& strName, const std::string& strPassword = "", int iUserID = 0, const std::string& strIP = "", const std::string& strSerial = "", const SString& strHttpPassAppend = "" );
7171
~CAccount ( void );
7272

7373
bool IsRegistered ( void ) { return m_AccountType != EAccountType::Guest; }
@@ -79,8 +79,10 @@ class CAccount
7979
void SetName ( const std::string& strName );
8080

8181
void SetPassword ( const SString& strPassword );
82-
bool IsPassword ( const SString& strPassword );
82+
bool IsPassword ( const SString& strPassword, bool* pbUsedHttpPassAppend=nullptr );
8383
SString GetPasswordHash ( void );
84+
const SString& GetHttpPassAppend ( void ) { return m_strHttpPassAppend; }
85+
void SetHttpPassAppend ( const SString& strHttpPassAppend );
8486

8587
inline const std::string& GetIP ( void ) { return m_strIP; }
8688
inline const std::string& GetSerial ( void ) { return m_strSerial; }
@@ -119,6 +121,7 @@ class CAccount
119121
EAccountType m_AccountType;
120122
SString m_strName;
121123
CAccountPassword m_Password;
124+
SString m_strHttpPassAppend;
122125
std::string m_strIP;
123126
std::string m_strSerial;
124127
int m_iUserID;

Server/mods/deathmatch/logic/CAccountManager.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,18 @@ CAccountManager::CAccountManager ( const SString& strDbPathFilename )
9494
// Add unique index
9595
m_pDatabaseManager->Execf ( m_hDbConnection, "CREATE UNIQUE INDEX IF NOT EXISTS IDX_USERDATA_USERID_KEY_U on userdata(userid,key)" );
9696
}
97-
97+
9898
// Ensure old indexes are removed
9999
m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_ACCOUNTS_NAME" );
100100
m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID" );
101101
m_pDatabaseManager->Execf ( m_hDbConnection, "DROP INDEX IF EXISTS IDX_USERDATA_USERID_KEY" );
102+
103+
// Check if httppass has been added yet
104+
m_pDatabaseManager->QueryWithResultf(m_hDbConnection, &result, "PRAGMA table_info(accounts)");
105+
if (ListContains(result->ColNames, "httppass") == false)
106+
{
107+
m_pDatabaseManager->Execf(m_hDbConnection, "ALTER TABLE accounts ADD COLUMN httppass TEXT");
108+
}
102109
}
103110

104111

@@ -129,7 +136,7 @@ bool CAccountManager::Load( void )
129136
//Create a registry result
130137
CRegistryResult result;
131138
//Select all our required information from the accounts database
132-
m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT id,name,password,ip,serial from accounts" );
139+
m_pDatabaseManager->QueryWithResultf ( m_hDbConnection, &result, "SELECT id,name,password,ip,serial,httppass from accounts" );
133140

134141
//Initialize all our variables
135142
m_iAccounts = 0;
@@ -145,6 +152,7 @@ bool CAccountManager::Load( void )
145152
SString strPassword = (const char *)row[2].pVal;
146153
SString strIP = (const char *)row[3].pVal;
147154
SString strSerial = (const char *)row[4].pVal;
155+
SString strHttpPassAppend = (const char *)row[5].pVal;
148156

149157
// Check for overlong names and incorrect escapement
150158
bool bRemoveAccount = false;
@@ -181,7 +189,7 @@ bool CAccountManager::Load( void )
181189
}
182190

183191
//Create a new account with the specified information
184-
CAccount* pAccount = g_pGame->GetAccountManager ()->AddPlayerAccount ( strName, strPassword, iUserID, strIP, strSerial );
192+
CAccount* pAccount = g_pGame->GetAccountManager ()->AddPlayerAccount ( strName, strPassword, iUserID, strIP, strSerial, strHttpPassAppend );
185193

186194
if ( bChanged )
187195
pAccount->SetChanged ( bChanged );
@@ -245,27 +253,26 @@ void CAccountManager::Save ( CAccount* pAccount, bool bCheckForErrors )
245253
{
246254
SString strName = pAccount->GetName();
247255
SString strPassword = pAccount->GetPasswordHash();
256+
SString strHttpPassAppend = pAccount->GetHttpPassAppend();
248257
SString strIP = pAccount->GetIP();
249258
SString strSerial = pAccount->GetSerial();
250259
unsigned int iID = pAccount->GetID();
251260

252261
m_pDatabaseManager->Execf ( m_hDbConnection, "INSERT OR IGNORE INTO accounts (id, name, ip, serial, password) VALUES(?,?,?,?,?)", SQLITE_INTEGER, iID, SQLITE_TEXT, strName.c_str (), SQLITE_TEXT, strIP.c_str (), SQLITE_TEXT, strSerial.c_str (), SQLITE_TEXT, strPassword.c_str () );
253262

254-
if ( bCheckForErrors )
263+
SString strQuery;
264+
strQuery += m_pDatabaseManager->PrepareStringf(m_hDbConnection, "UPDATE accounts SET ip=?", SQLITE_TEXT, *strIP);
265+
if (!strSerial.empty())
266+
strQuery += m_pDatabaseManager->PrepareStringf(m_hDbConnection, ",serial=?", SQLITE_TEXT, *strSerial);
267+
strQuery += m_pDatabaseManager->PrepareStringf(m_hDbConnection, ",password=?, httppass=? WHERE name=?", SQLITE_TEXT, *strPassword, SQLITE_TEXT, *strHttpPassAppend, SQLITE_TEXT, *strName);
268+
269+
if (bCheckForErrors)
255270
{
256-
if ( strSerial != "" )
257-
m_pDatabaseManager->QueryWithCallbackf ( m_hDbConnection, StaticDbCallback, this, "UPDATE accounts SET ip=?, serial=?, password=? WHERE name=?", SQLITE_TEXT, strIP.c_str (), SQLITE_TEXT, strSerial.c_str (), SQLITE_TEXT, strPassword.c_str (), SQLITE_TEXT, strName.c_str () );
258-
else
259-
//If we don't have a serial then IP and password will suffice
260-
m_pDatabaseManager->QueryWithCallbackf ( m_hDbConnection, StaticDbCallback, this, "UPDATE accounts SET ip=?, password=? WHERE name=?", SQLITE_TEXT, strIP.c_str (), SQLITE_TEXT, strPassword.c_str (), SQLITE_TEXT, strName.c_str () );
271+
m_pDatabaseManager->QueryWithCallbackf(m_hDbConnection, StaticDbCallback, this, strQuery);
261272
}
262273
else
263274
{
264-
if ( strSerial != "" )
265-
m_pDatabaseManager->Execf ( m_hDbConnection, "UPDATE accounts SET ip=?, serial=?, password=? WHERE name=?", SQLITE_TEXT, strIP.c_str (), SQLITE_TEXT, strSerial.c_str (), SQLITE_TEXT, strPassword.c_str (), SQLITE_TEXT, strName.c_str () );
266-
else
267-
//If we don't have a serial then IP and password will suffice
268-
m_pDatabaseManager->Execf ( m_hDbConnection, "UPDATE accounts SET ip=?, password=? WHERE name=?", SQLITE_TEXT, strIP.c_str (), SQLITE_TEXT, strPassword.c_str (), SQLITE_TEXT, strName.c_str () );
275+
m_pDatabaseManager->Execf(m_hDbConnection, strQuery);
269276
}
270277

271278
SaveAccountSerialUsage( pAccount );
@@ -872,9 +879,9 @@ CAccount* CAccountManager::AddConsoleAccount( const SString& strName )
872879
return pAccount;
873880
}
874881

875-
CAccount* CAccountManager::AddPlayerAccount( const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial )
882+
CAccount* CAccountManager::AddPlayerAccount( const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial, const SString& strHttpPassAppend )
876883
{
877-
CAccount* pAccount = new CAccount ( this, EAccountType::Player, strName, strPassword, iUserID, strIP, strSerial );
884+
CAccount* pAccount = new CAccount ( this, EAccountType::Player, strName, strPassword, iUserID, strIP, strSerial, strHttpPassAppend );
878885
return pAccount;
879886
}
880887

Server/mods/deathmatch/logic/CAccountManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class CAccountManager
150150

151151
CAccount* AddGuestAccount ( const SString& strName );
152152
CAccount* AddConsoleAccount ( const SString& strName );
153-
CAccount* AddPlayerAccount ( const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial );
153+
CAccount* AddPlayerAccount ( const SString& strName, const SString& strPassword, int iUserID, const SString& strIP, const SString& strSerial, const SString& strHttpPassAppend );
154154
CAccount* AddNewPlayerAccount ( const SString& strName, const SString& strPassword );
155155
bool RemoveAccount ( CAccount* pAccount );
156156
bool IsAuthorizedSerialRequired ( CAccount* pAccount );

Server/mods/deathmatch/logic/CConsoleCommands.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,10 +1715,11 @@ bool CConsoleCommands::AuthorizeSerial( CConsole* pConsole, const char* szArgume
17151715
bool bList = strAction == "list";
17161716
bool bAllow = strAction == "";
17171717
bool bRemove = strAction == "removelast";
1718+
bool bHttpPass = strAction == "httppass";
17181719

1719-
if ( ( !bList && !bAllow && !bRemove ) || strAccountName.empty() )
1720+
if ( ( !bList && !bAllow && !bRemove && !bHttpPass ) || strAccountName.empty() )
17201721
{
1721-
pEchoClient->SendConsole( "Usage: authserial account_name [list|removelast]" );
1722+
pEchoClient->SendConsole( "Usage: authserial account_name [list|removelast|httppass]" );
17221723
return false;
17231724
}
17241725

@@ -1783,7 +1784,8 @@ bool CConsoleCommands::AuthorizeSerial( CConsole* pConsole, const char* szArgume
17831784
pEchoClient->SendConsole( SString( "authserial: No serials require authorization for '%s'", *strAccountName ) );
17841785
return false;
17851786
}
1786-
else // Remove
1787+
else
1788+
if ( bRemove )
17871789
{
17881790
// Find newest serial
17891791
time_t tNewestDate = 0;
@@ -1807,6 +1809,22 @@ bool CConsoleCommands::AuthorizeSerial( CConsole* pConsole, const char* szArgume
18071809
pEchoClient->SendConsole( SString( "authserial: No serial usage for '%s'", *strAccountName ) );
18081810
return false;
18091811
}
1812+
else
1813+
if ( bHttpPass )
1814+
{
1815+
// Generate 7 digit random number
1816+
uint randomNumber;
1817+
g_pNetServer->GenerateRandomData(&randomNumber, sizeof(randomNumber));
1818+
randomNumber = (randomNumber % 8999999) + 1000000;
1819+
SString strHttpPassAppend("%u", randomNumber);
1820+
1821+
if (pClient->GetClientType() != CClient::CLIENT_CONSOLE)
1822+
pEchoClient->SendConsole(SString("authserial: HTTP password append for '%s' is now %s", *strAccountName, *strHttpPassAppend));
1823+
CLogger::LogPrintf("AUTHSERIAL: HTTP password append for '%s' is now %s\n", *strAccountName, *strHttpPassAppend);
1824+
pAccount->SetHttpPassAppend(strHttpPassAppend);
1825+
return true;
1826+
}
1827+
return false;
18101828
}
18111829

18121830

Server/mods/deathmatch/logic/CHTTPD.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,8 @@ ResponseCode CHTTPD::HandleRequest ( HttpRequest * ipoHttpRequest,
181181

182182
ResponseCode CHTTPD::RequestLogin ( HttpRequest * ipoHttpRequest, HttpResponse * ipoHttpResponse )
183183
{
184-
if ( m_strWarnMessageForIp == ipoHttpRequest->GetAddress() )
184+
if ( m_WarnMessageTimer.Get() < 4000 && m_strWarnMessageForIp == ipoHttpRequest->GetAddress() )
185185
{
186-
m_strWarnMessageForIp.clear();
187186
SString strMessage;
188187
strMessage += SString( "Your IP address ('%s') is not associated with an authorized serial.", ipoHttpRequest->GetAddress().c_str() );
189188
strMessage += SString( "<br/><a href='%s'>See here for more information</a>", "https:""//mtasa.com/authserialhttp" );
@@ -221,15 +220,21 @@ CAccount * CHTTPD::CheckAuthentication ( HttpRequest * ipoHttpRequest )
221220
if ( account )
222221
{
223222
// Check that the password is right
224-
if ( account->IsPassword ( authPassword.c_str () ) )
223+
bool bSkipIpCheck;
224+
if ( account->IsPassword( authPassword.c_str (), &bSkipIpCheck ) )
225225
{
226226
// Check that it isn't the Console account
227227
std::string strAccountName = account->GetName ();
228228
if ( strAccountName.compare ( CONSOLE_ACCOUNT_NAME ) != 0 )
229229
{
230-
if ( !g_pGame->GetAccountManager()->IsHttpLoginAllowed( account, ipoHttpRequest->GetAddress() ) )
230+
// Do IP check if required
231+
if ( !bSkipIpCheck && !g_pGame->GetAccountManager()->IsHttpLoginAllowed( account, ipoHttpRequest->GetAddress() ) )
231232
{
232-
m_strWarnMessageForIp = ipoHttpRequest->GetAddress();
233+
if (m_WarnMessageTimer.Get() > 8000 || m_strWarnMessageForIp != ipoHttpRequest->GetAddress())
234+
{
235+
m_strWarnMessageForIp = ipoHttpRequest->GetAddress();
236+
m_WarnMessageTimer.Reset();
237+
}
233238
CLogger::AuthPrintf( "HTTP: Failed login for user '%s' because %s not associated with authorized serial\n", authName.c_str(), ipoHttpRequest->GetAddress().c_str() );
234239
return m_pGuestAccount;
235240
}

Server/mods/deathmatch/logic/CHTTPD.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class CHTTPD : public EHS
6060
std::mutex m_mutexHttpDosProtect;
6161
std::mutex m_mutexLoggedInMap;
6262
SString m_strWarnMessageForIp;
63+
CElapsedTime m_WarnMessageTimer;
6364
};
6465

6566
#endif

0 commit comments

Comments
 (0)