1.1 --- a/core/AdminCache.cpp Sun Jan 28 04:19:46 2007 +0000
1.2 +++ b/core/AdminCache.cpp Mon Jan 29 04:19:14 2007 +0000
1.3 @@ -26,8 +26,10 @@
1.4 m_pStrings = new BaseStringTable(1024);
1.5 m_pMemory = m_pStrings->GetMemTable();
1.6 m_FreeGroupList = m_FirstGroup = m_LastGroup = INVALID_GROUP_ID;
1.7 + m_FreeUserList = m_FirstUser = m_LastUser = INVALID_ADMIN_ID;
1.8 m_pGroups = sm_trie_create();
1.9 m_pCacheFwd = NULL;
1.10 + m_FirstGroup = -1;
1.11 }
1.12
1.13 AdminCache::~AdminCache()
1.14 @@ -52,6 +54,13 @@
1.15 delete m_pStrings;
1.16 }
1.17
1.18 +void AdminCache::OnSourceModStartup(bool late)
1.19 +{
1.20 + RegisterAuthIdentType("steam");
1.21 + RegisterAuthIdentType("name");
1.22 + RegisterAuthIdentType("ip");
1.23 +}
1.24 +
1.25 void AdminCache::OnSourceModAllInitialized()
1.26 {
1.27 m_pCacheFwd = g_Forwards.CreateForward("OnRebuildAdminCache", ET_Ignore, 1, NULL, Param_Cell);
1.28 @@ -196,6 +205,51 @@
1.29 }
1.30 }
1.31
1.32 +AdminId AdminCache::CreateAdmin(const char *name)
1.33 +{
1.34 + AdminId id;
1.35 + AdminUser *pUser;
1.36 +
1.37 + if (m_FreeUserList != INVALID_ADMIN_ID)
1.38 + {
1.39 + pUser = (AdminUser *)m_pMemory->GetAddress(m_FreeUserList);
1.40 + assert(pUser->magic == USR_MAGIC_UNSET);
1.41 + id = m_FreeUserList;
1.42 + m_FreeUserList = pUser->next_user;
1.43 + } else {
1.44 + id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser);
1.45 + pUser->grp_size = 0;
1.46 + pUser->grp_table = -1;
1.47 + pUser->auth_size = 0;
1.48 + pUser->auth_table = -1;
1.49 + }
1.50 +
1.51 + memset(pUser->flags, 0, sizeof(pUser->flags));
1.52 + memset(pUser->eflags, 0, sizeof(pUser->flags));
1.53 + pUser->grp_count = 0;
1.54 + pUser->auth_count = 0;
1.55 + pUser->password = -1;
1.56 + pUser->magic = USR_MAGIC_SET;
1.57 +
1.58 + if (m_FirstUser == INVALID_ADMIN_ID)
1.59 + {
1.60 + m_FirstUser = id;
1.61 + m_LastUser = id;
1.62 + } else {
1.63 + AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
1.64 + pPrev->next_user = id;
1.65 + pUser->prev_user = m_LastUser;
1.66 + m_LastUser = id;
1.67 + }
1.68 +
1.69 + if (name && name[0] != '\0')
1.70 + {
1.71 + pUser->nameidx = m_pStrings->AddString(name);
1.72 + }
1.73 +
1.74 + return id;
1.75 +}
1.76 +
1.77 GroupId AdminCache::AddGroup(const char *group_name)
1.78 {
1.79 if (sm_trie_retrieve(m_pGroups, group_name, NULL))
1.80 @@ -222,7 +276,6 @@
1.81 pGroup->next_grp = INVALID_GROUP_ID;
1.82 pGroup->pCmdGrpTable = NULL;
1.83 pGroup->pCmdTable = NULL;
1.84 - pGroup->nameidx = m_pStrings->AddString(group_name);
1.85 memset(pGroup->addflags, 0, sizeof(AdminFlag) * AdminFlags_TOTAL);
1.86
1.87 if (m_FirstGroup == INVALID_GROUP_ID)
1.88 @@ -238,6 +291,8 @@
1.89 m_LastGroup = id;
1.90 }
1.91
1.92 + pGroup->nameidx = m_pStrings->AddString(group_name);
1.93 +
1.94 sm_trie_insert(m_pGroups, group_name, (void *)id);
1.95
1.96 return id;
1.97 @@ -498,6 +553,80 @@
1.98 return true;
1.99 }
1.100
1.101 +Trie *AdminCache::GetMethodByIndex(unsigned int index)
1.102 +{
1.103 + List<AuthMethod>::iterator iter;
1.104 + for (iter=m_AuthMethods.begin();
1.105 + iter!=m_AuthMethods.end();
1.106 + iter++)
1.107 + {
1.108 + if (index-- == 0)
1.109 + {
1.110 + return (*iter).table;
1.111 + }
1.112 + }
1.113 +
1.114 + return NULL;
1.115 +}
1.116 +
1.117 +bool AdminCache::InvalidateAdmin(AdminId id)
1.118 +{
1.119 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.120 + AdminUser *pOther;
1.121 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.122 + {
1.123 + return false;
1.124 + }
1.125 +
1.126 + /* Unlink from the dbl link list */
1.127 + if (id == m_FirstUser && id == m_LastUser)
1.128 + {
1.129 + m_FirstUser = INVALID_ADMIN_ID;
1.130 + m_LastUser = INVALID_ADMIN_ID;
1.131 + } else if (id == m_FirstUser) {
1.132 + m_FirstUser = pUser->next_user;
1.133 + pOther = (AdminUser *)m_pMemory->GetAddress(m_FirstUser);
1.134 + pOther->prev_user = INVALID_ADMIN_ID;
1.135 + } else if (id == m_LastUser) {
1.136 + m_LastUser = pUser->prev_user;
1.137 + pOther = (AdminUser *)m_pMemory->GetAddress(m_LastUser);
1.138 + pOther->next_user = INVALID_ADMIN_ID;
1.139 + } else {
1.140 + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->prev_user);
1.141 + pOther->next_user = pUser->next_user;
1.142 + pOther = (AdminUser *)m_pMemory->GetAddress(pUser->next_user);
1.143 + pOther->prev_user = pUser->prev_user;
1.144 + }
1.145 +
1.146 + /* Unlink from auth tables */
1.147 + if (pUser->auth_count > 0)
1.148 + {
1.149 + UserAuth *pAuth = (UserAuth *)m_pMemory->GetAddress(pUser->auth_table);
1.150 + Trie *pTrie;
1.151 + for (unsigned int i=0; i<pUser->auth_count; i++)
1.152 + {
1.153 + pTrie = GetMethodByIndex(pAuth[i].index);
1.154 + if (!pTrie)
1.155 + {
1.156 + continue;
1.157 + }
1.158 + sm_trie_delete(pTrie, m_pStrings->GetString(pAuth->identidx));
1.159 + }
1.160 + }
1.161 +
1.162 + /* Clear table counts */
1.163 + pUser->grp_count = 0;
1.164 + pUser->auth_count = 0;
1.165 +
1.166 + /* Link into free list */
1.167 + pUser->magic = USR_MAGIC_UNSET;
1.168 + pUser->next_user = m_FreeUserList;
1.169 + m_FreeUserList = id;
1.170 +
1.171 + return true;
1.172 +}
1.173 +
1.174 +
1.175 void AdminCache::InvalidateGroup(GroupId id)
1.176 {
1.177 AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(id);
1.178 @@ -548,7 +677,44 @@
1.179 pGroup->next_grp = m_FreeGroupList;
1.180 m_FreeGroupList = id;
1.181
1.182 - /* :TODO: remove this group from any users */
1.183 + int idx = m_FirstUser;
1.184 + AdminUser *pUser;
1.185 + int *table;
1.186 + while (idx != INVALID_ADMIN_ID)
1.187 + {
1.188 + pUser = (AdminUser *)m_pMemory->GetAddress(idx);
1.189 + if (pUser->grp_count > 0)
1.190 + {
1.191 + table = (int *)m_pMemory->GetAddress(pUser->grp_table);
1.192 + for (unsigned int i=0; i<pUser->grp_count; i++)
1.193 + {
1.194 + if (table[i] == id)
1.195 + {
1.196 + /* We have to remove this entry */
1.197 + for (unsigned int j=i+1; j<pUser->grp_count; j++)
1.198 + {
1.199 + /* Move everything down by one */
1.200 + table[j-1] = table[j];
1.201 + }
1.202 + /* Decrease count */
1.203 + pUser->grp_count--;
1.204 + /* Recalculate effective flags */
1.205 + memset(pUser->eflags, 0, sizeof(pUser->eflags));
1.206 + for (unsigned int j=0; j<pUser->grp_count; j++)
1.207 + {
1.208 + pOther = (AdminGroup *)m_pMemory->GetAddress(table[j]);
1.209 + for (unsigned int k=0; k<AdminFlags_TOTAL; k++)
1.210 + {
1.211 + pUser->eflags[k] = (pUser->flags[k] || pOther->addflags[k]);
1.212 + }
1.213 + }
1.214 + /* Break now, duplicates aren't allowed */
1.215 + break;
1.216 + }
1.217 + }
1.218 + }
1.219 + idx = pUser->next_user;
1.220 + }
1.221 }
1.222
1.223 void AdminCache::InvalidateGroupCache()
1.224 @@ -580,7 +746,7 @@
1.225 m_FirstGroup = INVALID_GROUP_ID;
1.226 m_LastGroup = INVALID_GROUP_ID;
1.227
1.228 - /* :TODO: dump the admin cache */
1.229 + InvalidateAdminCache(false);
1.230
1.231 /* Reset the memory table */
1.232 m_pMemory->Reset();
1.233 @@ -596,6 +762,41 @@
1.234 m_hooks.remove(pListener);
1.235 }
1.236
1.237 +void AdminCache::RegisterAuthIdentType(const char *name)
1.238 +{
1.239 + if (sm_trie_retrieve(m_pAuthTables, name, NULL))
1.240 + {
1.241 + return;
1.242 + }
1.243 +
1.244 + Trie *pAuth = sm_trie_create();
1.245 +
1.246 + AuthMethod method;
1.247 + method.name.assign(name);
1.248 + method.table = pAuth;
1.249 +
1.250 + m_AuthMethods.push_back(method);
1.251 +
1.252 + sm_trie_insert(m_pAuthTables, name, pAuth);
1.253 +}
1.254 +
1.255 +void AdminCache::InvalidateAdminCache(bool unlink_admins)
1.256 +{
1.257 + /* Wipe the identity cache first */
1.258 + List<AuthMethod>::iterator iter;
1.259 + for (iter=m_AuthMethods.begin();
1.260 + iter!=m_AuthMethods.end();
1.261 + iter++)
1.262 + {
1.263 + sm_trie_clear((*iter).table);
1.264 + }
1.265 +
1.266 + while (m_FirstUser != INVALID_ADMIN_ID)
1.267 + {
1.268 + InvalidateAdmin(m_FirstUser);
1.269 + }
1.270 +}
1.271 +
1.272 void AdminCache::DumpAdminCache(int cache_flags, bool rebuild)
1.273 {
1.274 if (cache_flags & ADMIN_CACHE_OVERRIDES)
1.275 @@ -604,19 +805,19 @@
1.276 DumpCommandOverrideCache(Override_CommandGroup);
1.277 }
1.278
1.279 - if ((cache_flags & ADMIN_CACHE_ADMINS) ||
1.280 - (cache_flags & ADMIN_CACHE_GROUPS))
1.281 - {
1.282 - /* Make sure the flag is set */
1.283 - cache_flags |= ADMIN_CACHE_ADMINS;
1.284 - /* :TODO: Dump admin cache */
1.285 - }
1.286 -
1.287 + /* This will auto-invalidate the admin cache */
1.288 if (cache_flags & ADMIN_CACHE_GROUPS)
1.289 {
1.290 InvalidateGroupCache();
1.291 }
1.292
1.293 + /* If we only requested an admin rebuild, re-use the internal memory */
1.294 + if ((cache_flags & ADMIN_CACHE_ADMINS) &&
1.295 + !(cache_flags & ADMIN_CACHE_GROUPS))
1.296 + {
1.297 + InvalidateAdminCache(true);
1.298 + }
1.299 +
1.300 if (rebuild)
1.301 {
1.302 List<IAdminListener *>::iterator iter;
1.303 @@ -631,3 +832,236 @@
1.304 m_pCacheFwd->Execute(&result);
1.305 }
1.306 }
1.307 +
1.308 +const char *AdminCache::GetAdminName(AdminId id)
1.309 +{
1.310 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.311 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.312 + {
1.313 + return NULL;
1.314 + }
1.315 +
1.316 + return m_pStrings->GetString(pUser->nameidx);
1.317 +}
1.318 +
1.319 +bool AdminCache::BindAdminIdentity(AdminId id, const char *auth, const char *ident)
1.320 +{
1.321 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.322 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.323 + {
1.324 + return false;
1.325 + }
1.326 +
1.327 + Trie *pTable;
1.328 + if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
1.329 + {
1.330 + return false;
1.331 + }
1.332 +
1.333 + if (sm_trie_retrieve(pTable, ident, NULL))
1.334 + {
1.335 + return false;
1.336 + }
1.337 +
1.338 + return sm_trie_insert(pTable, ident, (void **)id);
1.339 +}
1.340 +
1.341 +AdminId AdminCache::FindAdminByIdentity(const char *auth, const char *identity)
1.342 +{
1.343 + Trie *pTable;
1.344 + if (!sm_trie_retrieve(m_pAuthTables, auth, (void **)&pTable))
1.345 + {
1.346 + return INVALID_ADMIN_ID;
1.347 + }
1.348 +
1.349 + void *object;
1.350 + if (!sm_trie_retrieve(pTable, identity, &object))
1.351 + {
1.352 + return INVALID_ADMIN_ID;
1.353 + }
1.354 +
1.355 + return (AdminId)object;
1.356 +}
1.357 +
1.358 +void AdminCache::SetAdminFlag(AdminId id, AdminFlag flag, bool enabled)
1.359 +{
1.360 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.361 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.362 + {
1.363 + return;
1.364 + }
1.365 +
1.366 + if (flag < Admin_None
1.367 + || flag >= AdminFlags_TOTAL)
1.368 + {
1.369 + return;
1.370 + }
1.371 +
1.372 + pUser->flags[enabled] = false;
1.373 +}
1.374 +
1.375 +bool AdminCache::GetAdminFlag(AdminId id, AdminFlag flag, AccessMode mode)
1.376 +{
1.377 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.378 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.379 + {
1.380 + return false;
1.381 + }
1.382 +
1.383 + if (flag < Admin_None
1.384 + || flag >= AdminFlags_TOTAL)
1.385 + {
1.386 + return false;
1.387 + }
1.388 +
1.389 + if (mode == Access_Real)
1.390 + {
1.391 + return pUser->flags[flag];
1.392 + } else if (mode == Access_Effective) {
1.393 + return (pUser->flags[flag] || pUser->eflags[flag]);
1.394 + }
1.395 +
1.396 + return false;
1.397 +}
1.398 +
1.399 +unsigned int AdminCache::GetAdminFlags(AdminId id, bool flags[], unsigned int total, AccessMode mode)
1.400 +{
1.401 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.402 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.403 + {
1.404 + return 0;
1.405 + }
1.406 +
1.407 + unsigned int i = 0;
1.408 + if (mode == Access_Real)
1.409 + {
1.410 + for (i=0; i<AdminFlags_TOTAL && i<total; i++)
1.411 + {
1.412 + flags[i] = pUser->flags[i];
1.413 + }
1.414 + } else if (mode == Access_Effective) {
1.415 + for (i=0; i<AdminFlags_TOTAL && i<total; i++)
1.416 + {
1.417 + flags[i] = (pUser->flags[i] || pUser->eflags[i]);
1.418 + }
1.419 + }
1.420 +
1.421 + return i;
1.422 +}
1.423 +
1.424 +bool AdminCache::AdminInheritGroup(AdminId id, GroupId gid)
1.425 +{
1.426 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.427 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.428 + {
1.429 + return false;
1.430 + }
1.431 +
1.432 + AdminGroup *pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
1.433 + if (!pGroup || pGroup->magic != USR_MAGIC_SET)
1.434 + {
1.435 + return false;
1.436 + }
1.437 +
1.438 + int *table;
1.439 + if (pUser->grp_count + 1 > pUser->grp_size)
1.440 + {
1.441 + int new_size = 0;
1.442 + int tblidx;
1.443 +
1.444 + if (pUser->grp_size == 0)
1.445 + {
1.446 + new_size = 2;
1.447 + } else {
1.448 + new_size = pUser->grp_size * 2;
1.449 + }
1.450 +
1.451 + /* Create and refresh pointers */
1.452 + tblidx = m_pMemory->CreateMem(new_size * sizeof(int), (void **)&table);
1.453 + pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.454 + pGroup = (AdminGroup *)m_pMemory->GetAddress(gid);
1.455 +
1.456 + /* Copy old data if necessary */
1.457 + if (pUser->grp_table != -1)
1.458 + {
1.459 + int *old_table = (int *)m_pMemory->GetAddress(pUser->grp_table);
1.460 + memcpy(table, old_table, sizeof(int) * pUser->grp_count);
1.461 + }
1.462 + pUser->grp_table = tblidx;
1.463 + pUser->grp_size = new_size;
1.464 + } else {
1.465 + table = (int *)m_pMemory->GetAddress(pUser->grp_table);
1.466 + }
1.467 +
1.468 + for (unsigned int i=0; i<pUser->grp_count; i++)
1.469 + {
1.470 + if (table[i] == gid)
1.471 + {
1.472 + return false;
1.473 + }
1.474 + }
1.475 +
1.476 + table[pUser->grp_count] = gid;
1.477 + pUser->grp_count++;
1.478 +
1.479 + /* Compute new effective flags */
1.480 + for (unsigned int i=Admin_None;
1.481 + i<AdminFlags_TOTAL;
1.482 + i++)
1.483 + {
1.484 + /* Only inherit flags additive flags we don't have */
1.485 + if (!pUser->eflags[i])
1.486 + {
1.487 + pUser->eflags[i] = pGroup->addflags[i];
1.488 + }
1.489 + }
1.490 +
1.491 + return true;
1.492 +}
1.493 +
1.494 +unsigned int AdminCache::GetAdminGroupCount(AdminId id)
1.495 +{
1.496 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.497 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.498 + {
1.499 + return 0;
1.500 + }
1.501 +
1.502 + return pUser->grp_count;
1.503 +}
1.504 +
1.505 +GroupId AdminCache::GetAdminGroup(AdminId id, unsigned int index, const char **name)
1.506 +{
1.507 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.508 + if (!pUser || pUser->magic != USR_MAGIC_SET || index >= pUser->grp_count)
1.509 + {
1.510 + return INVALID_GROUP_ID;
1.511 + }
1.512 +
1.513 + int *table = (int *)m_pMemory->GetAddress(pUser->grp_table);
1.514 +
1.515 + return table[index];
1.516 +}
1.517 +
1.518 +const char *AdminCache::GetAdminPassword(AdminId id)
1.519 +{
1.520 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.521 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.522 + {
1.523 + return NULL;
1.524 + }
1.525 +
1.526 + return m_pStrings->GetString(pUser->password);
1.527 +}
1.528 +
1.529 +void AdminCache::SetAdminPassword(AdminId id, const char *password)
1.530 +{
1.531 + AdminUser *pUser = (AdminUser *)m_pMemory->GetAddress(id);
1.532 + if (!pUser || pUser->magic != USR_MAGIC_SET)
1.533 + {
1.534 + return;
1.535 + }
1.536 +
1.537 + pUser->password = m_pStrings->AddString(password);
1.538 +}
1.539 +