diff options
| author | Spp <spp@jorge.gr> | 2013-02-04 08:21:25 +0100 |
|---|---|---|
| committer | Spp <spp@jorge.gr> | 2013-02-04 09:04:33 +0100 |
| commit | b980aff83e214bab60f141c879c2a392789a4d16 (patch) | |
| tree | 0f9695e62bf2027574655766970cbe6ee0a50f43 /src/server/game/Accounts/AccountMgr.cpp | |
| parent | db9b0875500da077be1d0aa808999f59ed0663bc (diff) | |
Core: Implement Role based Access Control
- This system will give more control of actions an account can perform.
System defines:
- Permissions to perform some action
- Roles: a set of permissions that have some relation
- Groups: a set of roles that have some relation
Operations:
- Grant: Assign and allow
- Deny: Assign and do not allow
- Revoke: Remove
Precedence to know if something can be done: Grant, Deny. That means, if you are granted some action by a role but you have denied the permission, the action can not be done.
Some Rules:
- Groups can only have roles
- Roles can only have permissions
- An account can be assigned granted and denied roles. Permissions inherited from roles are granted if roles is granted and denied if roles is denied
- An account can be assigned granted and denied permissions
- An account can have multiple groups, roles and permissions
- An account can not have same role granted and denied at same time
- An acconnt can not have same permission granted and denied at same time
- Id 0 can not be used to define a group, role or permission
Added some permissions as a sample of use (Instant Logout, Skip Queue, Join BGs, Join DF) and some permissions as a workaround to commands till command system is modified to use RBAC
Diffstat (limited to 'src/server/game/Accounts/AccountMgr.cpp')
| -rw-r--r-- | src/server/game/Accounts/AccountMgr.cpp | 217 |
1 files changed, 216 insertions, 1 deletions
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index 3c3eded1f68..ce382342de8 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -17,6 +17,7 @@ */ #include "AccountMgr.h" +#include "Config.h" #include "DatabaseEnv.h" #include "ObjectAccessor.h" #include "Player.h" @@ -26,6 +27,7 @@ AccountMgr::AccountMgr() { + } AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password) @@ -44,12 +46,22 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass stmt->setString(0, username); stmt->setString(1, CalculateShaPassHash(username, password)); - LoginDatabase.Execute(stmt); + LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS_INIT); LoginDatabase.Execute(stmt); + // Add default rbac groups for that security level + RBACData* rbac = new RBACData(GetId(username), username, -1); + // No need to Load From DB, as it's new data + + RBACGroupContainer const& groupsToAdd = _defaultGroups[0]; // 0: Default sec level + for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it) + rbac->AddGroup(*it, -1); + + delete rbac; + return AOR_OK; // everything's fine } @@ -303,3 +315,206 @@ bool AccountMgr::IsConsoleAccount(uint32 gmlevel) { return gmlevel == SEC_CONSOLE; } + +void AccountMgr::LoadRBAC() +{ + uint32 oldMSTime = getMSTime(); + uint32 count1 = 0; + uint32 count2 = 0; + uint32 count3 = 0; + + QueryResult result = LoginDatabase.Query("SELECT id, name FROM rbac_permissions"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account permission definitions. DB table `rbac_permissions` is empty."); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].GetUInt32(); + _permissions[id] = new RBACPermission(id, field[1].GetString()); + ++count1; + } + while (result->NextRow()); + + result = LoginDatabase.Query("SELECT id, name FROM rbac_roles"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account role definitions. DB table `rbac_roles` is empty."); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].GetUInt32(); + _roles[id] = new RBACRole(id, field[1].GetString()); + ++count2; + } + while (result->NextRow()); + + result = LoginDatabase.Query("SELECT roleId, permissionId FROM rbac_role_permissions"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account role-permission definitions. DB table `rbac_role_permissions` is empty."); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].GetUInt32(); + RBACRole* role = _roles[id]; + role->GrantPermission(field[1].GetUInt32()); + } + while (result->NextRow()); + + result = LoginDatabase.Query("SELECT id, name FROM rbac_groups"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account group definitions. DB table `rbac_groups` is empty."); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].GetUInt32(); + _groups[id] = new RBACGroup(id, field[1].GetString()); + ++count3; + } + while (result->NextRow()); + + result = LoginDatabase.Query("SELECT groupId, roleId FROM rbac_group_roles"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account group-role definitions. DB table `rbac_group_roles` is empty."); + return; + } + + do + { + Field* field = result->Fetch(); + uint32 id = field[0].GetUInt32(); + RBACGroup* group = _groups[id]; + group->GrantRole(field[1].GetUInt32()); + } + while (result->NextRow()); + + result = LoginDatabase.Query("SELECT secId, groupId FROM rbac_security_level_groups ORDER by secId ASC"); + if (!result) + { + sLog->outInfo(LOG_FILTER_SQL, ">> Loaded 0 account default groups for security levels definitions. DB table `rbac_security_level_groups` is empty."); + return; + } + + uint8 lastSecId = 255; + RBACGroupContainer* groups = NULL; + do + { + Field* field = result->Fetch(); + uint8 secId = field[0].GetUInt8(); + + if (lastSecId != secId) + groups = &_defaultGroups[secId]; + + groups->insert(field[1].GetUInt32()); + } + while (result->NextRow()); + + sLog->outInfo(LOG_FILTER_SERVER_LOADING, ">> Loaded %u permission definitions, %u role definitions and %u group definitions in %u ms", count1, count2, count3, GetMSTimeDiffToNow(oldMSTime)); +} + +void AccountMgr::UpdateAccountAccess(RBACData* rbac, uint32 accountId, uint8 securityLevel, int32 realmId) +{ + int32 serverRealmId = realmId != -1 ? realmId : ConfigMgr::GetIntDefault("RealmID", 0); + bool needDelete = false; + if (!rbac) + { + needDelete = true; + rbac = new RBACData(accountId, "", serverRealmId); + rbac->LoadFromDB(); + } + + // Get max security level and realm (checking current realm and -1) + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID); + stmt->setUInt32(0, accountId); + stmt->setInt32(1, serverRealmId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (result) + { + do + { + Field* field = result->Fetch(); + uint8 secLevel = field[0].GetUInt8(); + int32 realmId = field[1].GetUInt32(); + + RBACGroupContainer const& groupsToRemove = _defaultGroups[secLevel]; + for (RBACGroupContainer::const_iterator it = groupsToRemove.begin(); it != groupsToRemove.end(); ++it) + rbac->RemoveGroup(*it, realmId); + } + while (result->NextRow()); + } + + // Add new groups depending on the new security Level + RBACGroupContainer const& groupsToAdd = _defaultGroups[securityLevel]; + for (RBACGroupContainer::const_iterator it = groupsToAdd.begin(); it != groupsToAdd.end(); ++it) + rbac->AddGroup(*it, realmId); + + if (needDelete) + delete rbac; + + // Delete old security level from DB + if (realmId == -1) + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS); + stmt->setUInt32(0, accountId); + LoginDatabase.Execute(stmt); + } + else + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM); + stmt->setUInt32(0, accountId); + stmt->setUInt32(1, realmId); + LoginDatabase.Execute(stmt); + } + + // Add new security level + if (securityLevel) + { + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_ACCESS); + stmt->setUInt32(0, accountId); + stmt->setUInt8(1, securityLevel); + stmt->setInt32(2, realmId); + LoginDatabase.Execute(stmt); + } +} + +RBACGroup const* AccountMgr::GetRBACGroup(uint32 group) const +{ + RBACGroupsContainer::const_iterator it = _groups.find(group); + if (it != _groups.end()) + return it->second; + + return NULL; +} + +RBACRole const* AccountMgr::GetRBACRole(uint32 role) const +{ + RBACRolesContainer::const_iterator it = _roles.find(role); + if (it != _roles.end()) + return it->second; + + return NULL; +} + +RBACPermission const* AccountMgr::GetRBACPermission(uint32 permission) const +{ + RBACPermissionsContainer::const_iterator it = _permissions.find(permission); + if (it != _permissions.end()) + return it->second; + + return NULL; +} |
