@@ -208,64 +208,97 @@ ResponseCode CHTTPD::RequestLogin(HttpRequest* ipoHttpRequest, HttpResponse* ipo
208208
209209CAccount* CHTTPD::CheckAuthentication (HttpRequest* ipoHttpRequest)
210210{
211- string authorization = ipoHttpRequest->oRequestHeaders [" authorization" ];
212- if (authorization.length () > 6 )
211+ const std::string strAuthorization = ipoHttpRequest->oRequestHeaders [" authorization" ];
212+
213+ if (strAuthorization.length () < 7 || strAuthorization.substr (0 , 6 ) != " Basic " )
214+ {
215+ return m_pGuestAccount;
216+ }
217+
218+ const std::string strAddress = ipoHttpRequest->GetAddress ();
219+ const char * szAddress = strAddress.c_str ();
220+ const bool bIsFlooding = m_BruteForceProtect.IsFlooding (szAddress);
221+
222+ // Basic auth
223+ SString strAuthName, strAuthPassword;
224+
225+ // If we're not flooding, or authorization header value isn't crazy long, let's parse it to get the username for console logs
226+ if (!bIsFlooding || strAuthorization.length () < 768 )
213227 {
214- if (authorization.substr (0 , 6 ) == " Basic " )
228+ SString strAuthDecoded = SharedUtil::Base64decode (strAuthorization.substr (6 ));
229+ strAuthDecoded.Split (" :" , &strAuthName, &strAuthPassword);
230+ }
231+
232+ if (bIsFlooding)
233+ {
234+ if (strAuthName.length () > 0 )
215235 {
216- // Basic auth
217- SString strAuthDecoded = SharedUtil::Base64decode (authorization.substr (6 ));
236+ CLogger::AuthPrintf (" HTTP: Ignoring login attempt for user '%s' from %s\n " , strAuthName.substr (0 , CAccountManager::MAX_USERNAME_LENGTH).c_str (),
237+ szAddress);
238+ }
239+ else
240+ {
241+ CLogger::AuthPrintf (" HTTP: Ignoring login attempt from %s\n " , szAddress);
242+ }
218243
219- SString authName, authPassword ;
220- strAuthDecoded. Split ( " : " , &authName, &authPassword);
244+ return m_pGuestAccount ;
245+ }
221246
222- if (m_BruteForceProtect.IsFlooding (ipoHttpRequest->GetAddress ().c_str ()))
223- {
224- CLogger::AuthPrintf (" HTTP: Ignoring login attempt for user '%s' from %s\n " , authName.c_str (), ipoHttpRequest->GetAddress ().c_str ());
225- return m_pGuestAccount;
226- }
247+ if (strAuthName.length () < CAccountManager::MIN_USERNAME_LENGTH || strAuthName.length () > CAccountManager::MAX_USERNAME_LENGTH ||
248+ strAuthPassword.length () < MIN_PASSWORD_LENGTH)
249+ {
250+ m_BruteForceProtect.AddConnect (szAddress);
227251
228- CAccount* account = g_pGame->GetAccountManager ()->Get (authName.c_str ());
229- if (account)
252+ CLogger::AuthPrintf (" HTTP: Failed login attempt from %s (bad login)\n " , szAddress);
253+
254+ return m_pGuestAccount;
255+ }
256+
257+ if (CAccount* pAccount = g_pGame->GetAccountManager ()->Get (strAuthName.c_str ()); pAccount)
258+ {
259+ bool bSkipIpCheck;
260+
261+ // Check that the password is right
262+ if (pAccount->IsPassword (strAuthPassword, &bSkipIpCheck))
263+ {
264+ // Check that it isn't the Console account
265+ if (pAccount->GetName () != CONSOLE_ACCOUNT_NAME)
230266 {
231- // Check that the password is right
232- bool bSkipIpCheck;
233- if (account->IsPassword (authPassword.c_str (), &bSkipIpCheck))
267+ // Do IP check if required
268+ if (!bSkipIpCheck && !g_pGame->GetAccountManager ()->IsHttpLoginAllowed (pAccount, strAddress))
234269 {
235- // Check that it isn't the Console account
236- std::string strAccountName = account->GetName ();
237- if (strAccountName.compare (CONSOLE_ACCOUNT_NAME) != 0 )
270+ if (m_WarnMessageTimer.Get () > 8000 || m_strWarnMessageForIp != strAddress)
238271 {
239- // Do IP check if required
240- if (!bSkipIpCheck && !g_pGame->GetAccountManager ()->IsHttpLoginAllowed (account, ipoHttpRequest->GetAddress ()))
241- {
242- if (m_WarnMessageTimer.Get () > 8000 || m_strWarnMessageForIp != ipoHttpRequest->GetAddress ())
243- {
244- m_strWarnMessageForIp = ipoHttpRequest->GetAddress ();
245- m_WarnMessageTimer.Reset ();
246- }
247- CLogger::AuthPrintf (" HTTP: Failed login for user '%s' because %s not associated with authorized serial\n " , authName.c_str (),
248- ipoHttpRequest->GetAddress ().c_str ());
249- return m_pGuestAccount;
250- }
251-
252- // Handle initial login logging
253- std::lock_guard<std::mutex> guard (m_mutexLoggedInMap);
254- if (m_LoggedInMap.find (authName) == m_LoggedInMap.end ())
255- CLogger::AuthPrintf (" HTTP: '%s' entered correct password from %s\n " , authName.c_str (), ipoHttpRequest->GetAddress ().c_str ());
256- m_LoggedInMap[authName] = GetTickCount64_ ();
257- account->OnLoginHttpSuccess (ipoHttpRequest->GetAddress ());
258- return account;
272+ m_strWarnMessageForIp = strAddress;
273+ m_WarnMessageTimer.Reset ();
259274 }
275+
276+ CLogger::AuthPrintf (" HTTP: Failed login for user '%s' because %s not associated with authorized serial\n " , strAuthName.c_str (), szAddress);
277+
278+ return m_pGuestAccount;
260279 }
261- }
262- if (authName.length () > 0 )
263- {
264- m_BruteForceProtect.AddConnect (ipoHttpRequest->GetAddress ().c_str ());
265- CLogger::AuthPrintf (" HTTP: Failed login attempt for user '%s' from %s\n " , authName.c_str (), ipoHttpRequest->GetAddress ().c_str ());
280+
281+ // Handle initial login logging
282+ std::lock_guard guard (m_mutexLoggedInMap);
283+
284+ if (m_LoggedInMap.find (strAuthName) == m_LoggedInMap.end ())
285+ {
286+ CLogger::AuthPrintf (" HTTP: '%s' entered correct password from %s\n " , strAuthName.c_str (), szAddress);
287+ }
288+
289+ m_LoggedInMap[strAuthName] = GetTickCount64_ ();
290+
291+ pAccount->OnLoginHttpSuccess (strAddress);
292+
293+ return pAccount;
266294 }
267295 }
268296 }
297+
298+ m_BruteForceProtect.AddConnect (szAddress);
299+
300+ CLogger::AuthPrintf (" HTTP: Failed login attempt for user '%s' from %s\n " , strAuthName.c_str (), szAddress);
301+
269302 return m_pGuestAccount;
270303}
271304
0 commit comments