diff -r fe1c5a3a4ba2 -r 673ccd0935ba core/AdminCache.cpp --- a/core/AdminCache.cpp Sun Jan 28 04:19:46 2007 +0000 +++ b/core/AdminCache.cpp Mon Jan 29 04:19:14 2007 +0000 @@ -26,8 +26,10 @@ m_pStrings = new BaseStringTable(1024); m_pMemory = m_pStrings->GetMemTable(); m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID; + m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID; m_pGroups = sm_trie_create(); m_pCacheFwd = NULL; + m_FirstGroup = -1; } AdminCache::~AdminCache() @@ -52,6 +54,13 @@ delete m_pStrings; } +void AdminCache::OnSourceModStartup(bool late) +{ + RegisterAuthIdentType("steam"); + RegisterAuthIdentType("name"); + RegisterAuthIdentType("ip"); +} + void AdminCache::OnSourceModAllInitialized() { m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell); @@ -196,6 +205,51 @@ } } +AdminId AdminCache::CreateAdmin(const char *name) +{ + AdminId id; + AdminUser *pUser; + + if (m_FreeUserList != INVALID_ADMIN_ID) + { + pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList); + assert(pUser->magic == USR_MAGIC_UNSET); + id = m_FreeUserList; + m_FreeUserList = pUser->next_user; + } else { + id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser); + pUser->grp_size = 0; + pUser->grp_table = -1; + pUser->auth_size = 0; + pUser->auth_table = -1; + } + + memset(pUser->flags, 0, sizeof(pUser->flags)); + memset(pUser->eflags, 0, sizeof(pUser->flags)); + pUser->grp_count = 0; + pUser->auth_count = 0; + pUser->password = -1; + pUser->magic = USR_MAGIC_SET; + + if (m_FirstUser == INVALID_ADMIN_ID) + { + m_FirstUser = id; + m_LastUser = id; + } else { + AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser); + pPrev->next_user = id; + pUser->prev_user = m_LastUser; + m_LastUser = id; + } + + if (name && name[0] != '\0') + { + pUser->nameidx = m_pStrings->AddString(name); + } + + return id; +} + GroupId AdminCache::AddGroup(const char *group_name) { if (sm_trie_retrieve(m_pGroups, group_name, NULL)) @@ -222,7 +276,6 @@ pGroup->next_grp = INVALID_GROUP_ID; pGroup->pCmdGrpTable = NULL; pGroup->pCmdTable = NULL; - pGroup->nameidx = m_pStrings->AddString(group_name); memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL); if (m_FirstGroup == INVALID_GROUP_ID) @@ -238,6 +291,8 @@ m_LastGroup = id; } + pGroup->nameidx = m_pStrings->AddString(group_name); + sm_trie_insert(m_pGroups, group_name, (void *)id); return id; @@ -498,6 +553,80 @@ return true; } +Trie *AdminCache::GetMethodByIndex(unsigned int index) +{ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + if (index-- == 0) + { + return (*iter).table; + } + } + + return NULL; +} + +bool AdminCache::InvalidateAdmin(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + AdminUser *pOther; + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + /* Unlink from the dbl link list */ + if (id == m_FirstUser && id == m_LastUser) + { + m_FirstUser = INVALID_ADMIN_ID; + m_LastUser = INVALID_ADMIN_ID; + } else if (id == m_FirstUser) { + m_FirstUser = pUser->next_user; + pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser); + pOther->prev_user = INVALID_ADMIN_ID; + } else if (id == m_LastUser) { + m_LastUser = pUser->prev_user; + pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser); + pOther->next_user = INVALID_ADMIN_ID; + } else { + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user); + pOther->next_user = pUser->next_user; + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user); + pOther->prev_user = pUser->prev_user; + } + + /* Unlink from auth tables */ + if (pUser->auth_count > 0) + { + UserAuth *pAuth = (UserAuth *)m_pMemory->GetAddress(pUser->auth_table); + Trie *pTrie; + for (unsigned int i=0; iauth_count; i++) + { + pTrie = GetMethodByIndex(pAuth[i].index); + if (!pTrie) + { + continue; + } + sm_trie_delete(pTrie, m_pStrings->GetString(pAuth->identidx)); + } + } + + /* Clear table counts */ + pUser->grp_count = 0; + pUser->auth_count = 0; + + /* Link into free list */ + pUser->magic = USR_MAGIC_UNSET; + pUser->next_user = m_FreeUserList; + m_FreeUserList = id; + + return true; +} + + void AdminCache::InvalidateGroup(GroupId id) { AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id); @@ -548,7 +677,44 @@ pGroup->next_grp = m_FreeGroupList; m_FreeGroupList = id; - /* :TODO: remove this group from any users */ + int idx = m_FirstUser; + AdminUser *pUser; + int *table; + while (idx != INVALID_ADMIN_ID) + { + pUser = (AdminUser *)m_pMemory->GetAddress(idx); + if (pUser->grp_count > 0) + { + table = (int *)m_pMemory->GetAddress(pUser->grp_table); + for (unsigned int i=0; igrp_count; i++) + { + if (table[i] == id) + { + /* We have to remove this entry */ + for (unsigned int j=i+1; jgrp_count; j++) + { + /* Move everything down by one */ + table[j-1] = table[j]; + } + /* Decrease count */ + pUser->grp_count--; + /* Recalculate effective flags */ + memset(pUser->eflags, 0, sizeof(pUser->eflags)); + for (unsigned int j=0; jgrp_count; j++) + { + pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]); + for (unsigned int k=0; keflags[k] = (pUser->flags[k] || pOther->addflags[k]); + } + } + /* Break now, duplicates aren't allowed */ + break; + } + } + } + idx = pUser->next_user; + } } void AdminCache::InvalidateGroupCache() @@ -580,7 +746,7 @@ m_FirstGroup = INVALID_GROUP_ID; m_LastGroup = INVALID_GROUP_ID; - /* :TODO: dump the admin cache */ + InvalidateAdminCache(false); /* Reset the memory table */ m_pMemory->Reset(); @@ -596,6 +762,41 @@ m_hooks.remove(pListener); } +void AdminCache::RegisterAuthIdentType(const char *name) +{ + if (sm_trie_retrieve(m_pAuthTables, name, NULL)) + { + return; + } + + Trie *pAuth = sm_trie_create(); + + AuthMethod method; + method.name.assign(name); + method.table = pAuth; + + m_AuthMethods.push_back(method); + + sm_trie_insert(m_pAuthTables, name, pAuth); +} + +void AdminCache::InvalidateAdminCache(bool unlink_admins) +{ + /* Wipe the identity cache first */ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + sm_trie_clear((*iter).table); + } + + while (m_FirstUser != INVALID_ADMIN_ID) + { + InvalidateAdmin(m_FirstUser); + } +} + void AdminCache::DumpAdminCache(int cache_flags, bool rebuild) { if (cache_flags & ADMIN_CACHE_OVERRIDES) @@ -604,19 +805,19 @@ DumpCommandOverrideCache(Override_CommandGroup); } - if ((cache_flags & ADMIN_CACHE_ADMINS) || - (cache_flags & ADMIN_CACHE_GROUPS)) - { - /* Make sure the flag is set */ - cache_flags |= ADMIN_CACHE_ADMINS; - /* :TODO: Dump admin cache */ - } - + /* This will auto-invalidate the admin cache */ if (cache_flags & ADMIN_CACHE_GROUPS) { InvalidateGroupCache(); } + /* If we only requested an admin rebuild, re-use the internal memory */ + if ((cache_flags & ADMIN_CACHE_ADMINS) && + !(cache_flags & ADMIN_CACHE_GROUPS)) + { + InvalidateAdminCache(true); + } + if (rebuild) { List::iterator iter; @@ -631,3 +832,236 @@ m_pCacheFwd->Execute(&result); } } + +const char *AdminCache::GetAdminName(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return NULL; + } + + return m_pStrings->GetString(pUser->nameidx); +} + +bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + Trie *pTable; + if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable)) + { + return false; + } + + if (sm_trie_retrieve(pTable, ident, NULL)) + { + return false; + } + + return sm_trie_insert(pTable, ident, (void **)id); +} + +AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity) +{ + Trie *pTable; + if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable)) + { + return INVALID_ADMIN_ID; + } + + void *object; + if (!sm_trie_retrieve(pTable, identity, &object)) + { + return INVALID_ADMIN_ID; + } + + return (AdminId)object; +} + +void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return; + } + + if (flag < Admin_None + || flag >= AdminFlags_TOTAL) + { + return; + } + + pUser->flags[enabled] = false; +} + +bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + if (flag < Admin_None + || flag >= AdminFlags_TOTAL) + { + return false; + } + + if (mode == Access_Real) + { + return pUser->flags[flag]; + } else if (mode == Access_Effective) { + return (pUser->flags[flag] || pUser->eflags[flag]); + } + + return false; +} + +unsigned int AdminCache::GetAdminFlags(AdminId id, bool flags[], unsigned int total, AccessMode mode) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + unsigned int i = 0; + if (mode == Access_Real) + { + for (i=0; iflags[i]; + } + } else if (mode == Access_Effective) { + for (i=0; iflags[i] || pUser->eflags[i]); + } + } + + return i; +} + +bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return false; + } + + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != USR_MAGIC_SET) + { + return false; + } + + int *table; + if (pUser->grp_count + 1 > pUser->grp_size) + { + int new_size = 0; + int tblidx; + + if (pUser->grp_size == 0) + { + new_size = 2; + } else { + new_size = pUser->grp_size * 2; + } + + /* Create and refresh pointers */ + tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table); + pUser = (AdminUser *)m_pMemory->GetAddress(id); + pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + + /* Copy old data if necessary */ + if (pUser->grp_table != -1) + { + int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table); + memcpy(table, old_table, sizeof(int) * pUser->grp_count); + } + pUser->grp_table = tblidx; + pUser->grp_size = new_size; + } else { + table = (int *)m_pMemory->GetAddress(pUser->grp_table); + } + + for (unsigned int i=0; igrp_count; i++) + { + if (table[i] == gid) + { + return false; + } + } + + table[pUser->grp_count] = gid; + pUser->grp_count++; + + /* Compute new effective flags */ + for (unsigned int i=Admin_None; + ieflags[i]) + { + pUser->eflags[i] = pGroup->addflags[i]; + } + } + + return true; +} + +unsigned int AdminCache::GetAdminGroupCount(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return 0; + } + + return pUser->grp_count; +} + +GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count) + { + return INVALID_GROUP_ID; + } + + int *table = (int *)m_pMemory->GetAddress(pUser->grp_table); + + return table[index]; +} + +const char *AdminCache::GetAdminPassword(AdminId id) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return NULL; + } + + return m_pStrings->GetString(pUser->password); +} + +void AdminCache::SetAdminPassword(AdminId id, const char *password) +{ + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id); + if (!pUser || pUser->magic != USR_MAGIC_SET) + { + return; + } + + pUser->password = m_pStrings->AddString(password); +} +