2020-09-26 19:41:58 +00:00
|
|
|
#include "authmanager.h"
|
2019-04-06 00:46:56 +00:00
|
|
|
#include <base/hash_ctxt.h>
|
2017-03-02 15:16:29 +00:00
|
|
|
#include <engine/shared/config.h>
|
2022-03-24 00:16:05 +00:00
|
|
|
#include <game/generated/protocol.h>
|
2017-03-02 15:16:29 +00:00
|
|
|
|
|
|
|
#define ADMIN_IDENT "default_admin"
|
|
|
|
#define MOD_IDENT "default_mod"
|
|
|
|
#define HELPER_IDENT "default_helper"
|
|
|
|
|
2019-04-06 00:46:56 +00:00
|
|
|
static MD5_DIGEST HashPassword(const char *pPassword, const unsigned char aSalt[SALT_BYTES])
|
|
|
|
{
|
|
|
|
// Hash the password and the salt
|
|
|
|
MD5_CTX Md5;
|
|
|
|
md5_init(&Md5);
|
|
|
|
md5_update(&Md5, (unsigned char *)pPassword, str_length(pPassword));
|
|
|
|
md5_update(&Md5, aSalt, SALT_BYTES);
|
|
|
|
return md5_finish(&Md5);
|
|
|
|
}
|
|
|
|
|
2017-03-02 15:16:29 +00:00
|
|
|
CAuthManager::CAuthManager()
|
|
|
|
{
|
|
|
|
m_aDefault[0] = -1;
|
|
|
|
m_aDefault[1] = -1;
|
|
|
|
m_aDefault[2] = -1;
|
2017-03-04 20:06:22 +00:00
|
|
|
m_Generated = false;
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CAuthManager::Init()
|
|
|
|
{
|
2017-03-10 11:33:34 +00:00
|
|
|
int NumDefaultKeys = 0;
|
|
|
|
if(g_Config.m_SvRconPassword[0])
|
|
|
|
NumDefaultKeys++;
|
|
|
|
if(g_Config.m_SvRconModPassword[0])
|
|
|
|
NumDefaultKeys++;
|
|
|
|
if(g_Config.m_SvRconHelperPassword[0])
|
|
|
|
NumDefaultKeys++;
|
|
|
|
if(m_aKeys.size() == NumDefaultKeys && !g_Config.m_SvRconPassword[0])
|
2017-03-04 20:06:22 +00:00
|
|
|
{
|
|
|
|
secure_random_password(g_Config.m_SvRconPassword, sizeof(g_Config.m_SvRconPassword), 6);
|
2017-03-29 12:39:55 +00:00
|
|
|
AddDefaultKey(AUTHED_ADMIN, g_Config.m_SvRconPassword);
|
2017-03-04 20:06:22 +00:00
|
|
|
m_Generated = true;
|
|
|
|
}
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2019-04-06 00:46:56 +00:00
|
|
|
int CAuthManager::AddKeyHash(const char *pIdent, MD5_DIGEST Hash, const unsigned char *pSalt, int AuthLevel)
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-03-10 11:33:34 +00:00
|
|
|
if(FindKey(pIdent) >= 0)
|
2017-03-04 20:16:02 +00:00
|
|
|
return -1;
|
|
|
|
|
2017-03-02 15:16:29 +00:00
|
|
|
CKey Key;
|
2017-03-06 19:11:23 +00:00
|
|
|
str_copy(Key.m_aIdent, pIdent, sizeof(Key.m_aIdent));
|
2019-04-06 00:46:56 +00:00
|
|
|
Key.m_Pw = Hash;
|
2017-03-02 15:16:29 +00:00
|
|
|
mem_copy(Key.m_aSalt, pSalt, SALT_BYTES);
|
|
|
|
Key.m_Level = AuthLevel;
|
|
|
|
|
|
|
|
return m_aKeys.add(Key);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CAuthManager::AddKey(const char *pIdent, const char *pPw, int AuthLevel)
|
|
|
|
{
|
2017-03-06 19:11:23 +00:00
|
|
|
// Generate random salt
|
2019-04-06 00:46:56 +00:00
|
|
|
unsigned char aSalt[SALT_BYTES];
|
2017-03-02 15:16:29 +00:00
|
|
|
secure_random_fill(aSalt, SALT_BYTES);
|
2019-04-06 00:46:56 +00:00
|
|
|
return AddKeyHash(pIdent, HashPassword(pPw, aSalt), aSalt, AuthLevel);
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2017-03-06 17:02:19 +00:00
|
|
|
int CAuthManager::RemoveKey(int Slot)
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
|
|
|
m_aKeys.remove_index_fast(Slot);
|
2020-10-26 14:14:07 +00:00
|
|
|
for(int &Default : m_aDefault)
|
2017-03-10 11:33:34 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
if(Default == Slot)
|
2017-03-10 11:33:34 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
Default = -1;
|
2017-03-10 11:33:34 +00:00
|
|
|
}
|
2020-10-26 14:14:07 +00:00
|
|
|
else if(Default == m_aKeys.size())
|
2017-03-10 11:33:34 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
Default = Slot;
|
2017-03-10 11:33:34 +00:00
|
|
|
}
|
|
|
|
}
|
2017-03-06 17:02:19 +00:00
|
|
|
return m_aKeys.size();
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
int CAuthManager::FindKey(const char *pIdent) const
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
|
|
|
for(int i = 0; i < m_aKeys.size(); i++)
|
|
|
|
if(!str_comp(m_aKeys[i].m_aIdent, pIdent))
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
bool CAuthManager::CheckKey(int Slot, const char *pPw) const
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Slot < 0 || Slot >= m_aKeys.size())
|
|
|
|
return false;
|
2019-04-06 00:46:56 +00:00
|
|
|
return m_aKeys[Slot].m_Pw == HashPassword(pPw, m_aKeys[Slot].m_aSalt);
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
int CAuthManager::DefaultKey(int AuthLevel) const
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(AuthLevel < 0 || AuthLevel > AUTHED_ADMIN)
|
|
|
|
return 0;
|
2017-03-02 15:16:29 +00:00
|
|
|
return m_aDefault[AUTHED_ADMIN - AuthLevel];
|
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
int CAuthManager::KeyLevel(int Slot) const
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Slot < 0 || Slot >= m_aKeys.size())
|
|
|
|
return false;
|
2017-03-02 15:16:29 +00:00
|
|
|
return m_aKeys[Slot].m_Level;
|
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
const char *CAuthManager::KeyIdent(int Slot) const
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Slot < 0 || Slot >= m_aKeys.size())
|
|
|
|
return NULL;
|
2017-03-02 15:16:29 +00:00
|
|
|
return m_aKeys[Slot].m_aIdent;
|
|
|
|
}
|
|
|
|
|
2019-04-06 00:46:56 +00:00
|
|
|
void CAuthManager::UpdateKeyHash(int Slot, MD5_DIGEST Hash, const unsigned char *pSalt, int AuthLevel)
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Slot < 0 || Slot >= m_aKeys.size())
|
|
|
|
return;
|
2017-03-02 15:16:29 +00:00
|
|
|
|
|
|
|
CKey *pKey = &m_aKeys[Slot];
|
2019-04-06 00:46:56 +00:00
|
|
|
pKey->m_Pw = Hash;
|
2017-03-02 15:16:29 +00:00
|
|
|
mem_copy(pKey->m_aSalt, pSalt, SALT_BYTES);
|
|
|
|
pKey->m_Level = AuthLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CAuthManager::UpdateKey(int Slot, const char *pPw, int AuthLevel)
|
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Slot < 0 || Slot >= m_aKeys.size())
|
|
|
|
return;
|
2017-03-02 15:16:29 +00:00
|
|
|
|
2017-03-06 19:11:23 +00:00
|
|
|
// Generate random salt
|
2019-04-06 00:46:56 +00:00
|
|
|
unsigned char aSalt[SALT_BYTES];
|
2017-03-02 15:16:29 +00:00
|
|
|
secure_random_fill(aSalt, SALT_BYTES);
|
2019-04-06 00:46:56 +00:00
|
|
|
UpdateKeyHash(Slot, HashPassword(pPw, aSalt), aSalt, AuthLevel);
|
2017-03-02 15:16:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CAuthManager::ListKeys(FListCallback pfnListCallback, void *pUser)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < m_aKeys.size(); i++)
|
|
|
|
pfnListCallback(m_aKeys[i].m_aIdent, m_aKeys[i].m_Level, pUser);
|
|
|
|
}
|
|
|
|
|
2017-03-06 17:02:19 +00:00
|
|
|
void CAuthManager::AddDefaultKey(int Level, const char *pPw)
|
2017-03-02 15:16:29 +00:00
|
|
|
{
|
2017-06-02 16:13:15 +00:00
|
|
|
if(Level < AUTHED_HELPER || Level > AUTHED_ADMIN)
|
|
|
|
return;
|
|
|
|
|
2017-03-06 17:02:19 +00:00
|
|
|
static const char IDENTS[3][sizeof(HELPER_IDENT)] = {ADMIN_IDENT, MOD_IDENT, HELPER_IDENT};
|
|
|
|
int Index = AUTHED_ADMIN - Level;
|
2017-06-02 16:13:15 +00:00
|
|
|
if(m_aDefault[Index] >= 0)
|
|
|
|
return; // already exists
|
2017-03-06 17:02:19 +00:00
|
|
|
m_aDefault[Index] = AddKey(IDENTS[Index], pPw, Level);
|
2017-03-04 20:06:22 +00:00
|
|
|
}
|
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
bool CAuthManager::IsGenerated() const
|
2017-03-04 20:06:22 +00:00
|
|
|
{
|
|
|
|
return m_Generated;
|
2017-03-06 17:02:19 +00:00
|
|
|
}
|
2017-07-24 19:43:55 +00:00
|
|
|
|
2021-02-08 21:26:26 +00:00
|
|
|
int CAuthManager::NumNonDefaultKeys() const
|
2017-07-24 19:43:55 +00:00
|
|
|
{
|
|
|
|
int DefaultCount = (m_aDefault[0] >= 0) + (m_aDefault[1] >= 0) + (m_aDefault[2] >= 0);
|
|
|
|
return m_aKeys.size() - DefaultCount;
|
|
|
|
}
|