mirror of
https://github.com/SWG-Source/src.git
synced 2026-01-17 00:04:25 -05:00
Admin Account Routing Refactor
This commit is contained in:
@@ -394,19 +394,41 @@ ClientConnection::onIdValidated(bool canLogin, bool canCreateRegularCharacter, b
|
|||||||
// Save lists of claimed rewards, which won't be used again until later in the login sequence
|
// Save lists of claimed rewards, which won't be used again until later in the login sequence
|
||||||
m_consumedRewardEvents = consumedRewardEvents;
|
m_consumedRewardEvents = consumedRewardEvents;
|
||||||
m_claimedRewardItems = claimedRewardItems;
|
m_claimedRewardItems = claimedRewardItems;
|
||||||
|
bool isAdmin = false;
|
||||||
|
|
||||||
|
// Revised - SWG Source - 2021 (Aconite)
|
||||||
int level = 0;
|
// Determine if this account is in the Admin Table
|
||||||
if (AdminAccountManager::isAdminAccount(Unicode::toLower(getAccountName()), level) && (level !=
|
if(AdminAccountManager::getAdminLevel(Unicode::toLower(getAccountName())) > 0)
|
||||||
0)) // Note: not checking IP, so that owners of god accounts can create characters to play from home without having to erase the characters they use for work
|
|
||||||
{
|
{
|
||||||
|
// Determine if we are using Secure Login (IP restricted)
|
||||||
|
if(ConfigConnectionServer::getUseSecureLoginForGodAccess())
|
||||||
|
{
|
||||||
|
// If we *require* secure login, and we are *not* from a secure IP, disconnect the client
|
||||||
|
// as they should not be inside this account
|
||||||
|
if(!AdminAccountManager::isInternalIp(getRemoteAddress()))
|
||||||
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] login to this admin account failed because secure login was required but the remote IP address connected was not in the allowed range.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getRemoteAddress().c_str()));
|
||||||
|
disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_isSecure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we're here, we're an admin account, and we have the correct IP (if applicable)
|
||||||
|
// so we're overriding the ClientPermissionMessage values
|
||||||
canLogin = true;
|
canLogin = true;
|
||||||
canCreateRegularCharacter = true;
|
canCreateRegularCharacter = true;
|
||||||
canSkipTutorial = true;
|
canSkipTutorial = true;
|
||||||
m_isAdminAccount = true;
|
m_isAdminAccount = true;
|
||||||
|
isAdmin = true; // this flag goes to the client to let it know we can connect to a Locked Cluster
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] validating this account to the Connection Server after successful authentication.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterId().getValueString().c_str(), getRemoteAddress().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial);
|
ClientPermissionsMessage c(canLogin, canCreateRegularCharacter, canCreateJediCharacter, canSkipTutorial, isAdmin);
|
||||||
send(c, true);
|
send(c, true);
|
||||||
|
|
||||||
DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID()));
|
DEBUG_REPORT_LOG(true, ("Permissions for %lu:\n", getSUID()));
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ void ConfigConnectionServer::install(void)
|
|||||||
KEY_STRING (altPublicBindAddress, "");
|
KEY_STRING (altPublicBindAddress, "");
|
||||||
KEY_BOOL (useOldSuidGenerator, false);
|
KEY_BOOL (useOldSuidGenerator, false);
|
||||||
|
|
||||||
|
KEY_BOOL (useSecureLoginForGodAccess, false);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
char const * result = 0;
|
char const * result = 0;
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ public:
|
|||||||
int connectionServerNumber;
|
int connectionServerNumber;
|
||||||
int fakeBuddyPoints;
|
int fakeBuddyPoints;
|
||||||
|
|
||||||
|
bool useSecureLoginForGodAccess;
|
||||||
|
|
||||||
bool useOldSuidGenerator;
|
bool useOldSuidGenerator;
|
||||||
|
|
||||||
const char *altPublicBindAddress;
|
const char *altPublicBindAddress;
|
||||||
@@ -187,6 +189,9 @@ public:
|
|||||||
static const char *getPublicBindAddress();
|
static const char *getPublicBindAddress();
|
||||||
|
|
||||||
static bool getUseOldSuidGenerator();
|
static bool getUseOldSuidGenerator();
|
||||||
|
|
||||||
|
static bool getUseSecureLoginForGodAccess();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Data *data;
|
static Data *data;
|
||||||
};
|
};
|
||||||
@@ -480,4 +485,9 @@ inline bool ConfigConnectionServer::getUseOldSuidGenerator() {
|
|||||||
return data->useOldSuidGenerator;
|
return data->useOldSuidGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool ConfigConnectionServer::getUseSecureLoginForGodAccess()
|
||||||
|
{
|
||||||
|
return data->useSecureLoginForGodAccess;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _ConfigConnectionServer_H
|
#endif // _ConfigConnectionServer_H
|
||||||
|
|||||||
@@ -943,10 +943,10 @@ LoginServer::validateAccount(const StationId &stationId, uint32 clusterId, uint3
|
|||||||
bool clientIsInternal = false;
|
bool clientIsInternal = false;
|
||||||
ClientConnection *conn = getValidatedClient(stationId);
|
ClientConnection *conn = getValidatedClient(stationId);
|
||||||
if (conn) {
|
if (conn) {
|
||||||
clientIsInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress());
|
clientIsInternal = conn->getAdminLevel() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clientIsInternal && ConfigLoginServer::getInternalBypassOnlineLimit()) {
|
if (clientIsInternal) {
|
||||||
canLogin = true;
|
canLogin = true;
|
||||||
} else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) {
|
} else if (cle->m_numPlayers <= cle->m_onlinePlayerLimit) {
|
||||||
canLogin = true;
|
canLogin = true;
|
||||||
@@ -968,6 +968,12 @@ LoginServer::validateAccount(const StationId &stationId, uint32 clusterId, uint3
|
|||||||
canSkipTutorial = true;
|
canSkipTutorial = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// double check locked cluster
|
||||||
|
if(cle->m_locked)
|
||||||
|
{
|
||||||
|
canLogin = clientIsInternal;
|
||||||
|
}
|
||||||
|
|
||||||
ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems);
|
ValidateAccountReplyMessage msg(stationId, canLogin, canCreateRegular, canCreateJedi, canSkipTutorial, track, consumedRewardEvents, claimedRewardItems);
|
||||||
cle->m_centralServerConnection->send(msg, true);
|
cle->m_centralServerConnection->send(msg, true);
|
||||||
}
|
}
|
||||||
@@ -1228,32 +1234,8 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien
|
|||||||
NOT_NULL(conn);
|
NOT_NULL(conn);
|
||||||
WARNING_STRICT_FATAL(getValidatedClient(suid), ("Validating an already valid client in onValidateClient(). StationId: %d UserName: %s", suid, username.c_str()));
|
WARNING_STRICT_FATAL(getValidatedClient(suid), ("Validating an already valid client in onValidateClient(). StationId: %d UserName: %s", suid, username.c_str()));
|
||||||
|
|
||||||
int adminLevel = 0;
|
// determine if this is an admin account
|
||||||
const bool isAdminAccount = AdminAccountManager::isAdminAccount(Unicode::toLower(username), adminLevel);
|
const bool isAdminAccount = AdminAccountManager::getAdminLevel(username) > 0;
|
||||||
|
|
||||||
if (conn->getRequestedAdminSuid() != 0) {
|
|
||||||
//verify internal, secure, is on the god list
|
|
||||||
bool loginOK = false;
|
|
||||||
if (!isSecure) {
|
|
||||||
LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not using a SecureID token", username.c_str(), suid, conn->getRequestedAdminSuid()));
|
|
||||||
} else {
|
|
||||||
if (!AdminAccountManager::isInternalIp(conn->getRemoteAddress())) {
|
|
||||||
LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but was not logging in from an internal IP", username.c_str(), suid, conn->getRequestedAdminSuid()));
|
|
||||||
} else {
|
|
||||||
if (!isAdminAccount || adminLevel < 10) {
|
|
||||||
LOG("CustomerService", ("AdminLogin: User %s (account %li) attempted to log into account %li, but did not have sufficient permissions", username.c_str(), suid, conn->getRequestedAdminSuid()));
|
|
||||||
} else {
|
|
||||||
suid = conn->getRequestedAdminSuid();
|
|
||||||
loginOK = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!loginOK) {
|
|
||||||
conn->disconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// encrypt the clients credentials with the key, return
|
// encrypt the clients credentials with the key, return
|
||||||
// the cipher text to the client for use as a connection
|
// the cipher text to the client for use as a connection
|
||||||
@@ -1297,14 +1279,11 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien
|
|||||||
conn->send(k, true);
|
conn->send(k, true);
|
||||||
delete[] keyBuffer;
|
delete[] keyBuffer;
|
||||||
|
|
||||||
// send cluster enum
|
|
||||||
bool clientInternal = AdminAccountManager::isInternalIp(conn->getRemoteAddress());
|
|
||||||
|
|
||||||
std::vector <LoginEnumCluster::ClusterData> data;
|
std::vector <LoginEnumCluster::ClusterData> data;
|
||||||
|
|
||||||
for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) {
|
for (ClusterListType::const_iterator j = m_clusterList.begin(); j != m_clusterList.end(); ++j) {
|
||||||
ClusterListEntry *cle = *j;
|
ClusterListEntry *cle = *j;
|
||||||
if (cle && cle->m_clusterId != 0 && cle->m_clusterName.size() != 0 && (clientInternal || !cle->m_secret)) {
|
if (cle && cle->m_clusterId != 0 && cle->m_clusterName.size() != 0 && (isAdminAccount || !cle->m_secret)) {
|
||||||
LoginEnumCluster::ClusterData item;
|
LoginEnumCluster::ClusterData item;
|
||||||
item.m_clusterId = cle->m_clusterId;
|
item.m_clusterId = cle->m_clusterId;
|
||||||
item.m_clusterName = cle->m_clusterName;
|
item.m_clusterName = cle->m_clusterName;
|
||||||
@@ -1331,7 +1310,7 @@ LoginServer::onValidateClient(StationId suid, const std::string &username, Clien
|
|||||||
conn->setIsValidated(true);
|
conn->setIsValidated(true);
|
||||||
conn->setStationId(suid);
|
conn->setStationId(suid);
|
||||||
conn->setIsSecure(isSecure);
|
conn->setIsSecure(isSecure);
|
||||||
conn->setAdminLevel(isAdminAccount ? adminLevel : -1);
|
conn->setAdminLevel(isAdminAccount ? AdminAccountManager::getAdminLevel(username) : -1);
|
||||||
IGNORE_RETURN(m_validatedClientMap.insert(std::pair<StationId, ClientConnection *>(suid, conn)));
|
IGNORE_RETURN(m_validatedClientMap.insert(std::pair<StationId, ClientConnection *>(suid, conn)));
|
||||||
|
|
||||||
//Must be done after setting various information in the connection object above
|
//Must be done after setting various information in the connection object above
|
||||||
@@ -1408,11 +1387,16 @@ void LoginServer::sendExtendedClusterInfo(ClientConnection &client) const {
|
|||||||
/**
|
/**
|
||||||
* Send the list of active clusters to a client.
|
* Send the list of active clusters to a client.
|
||||||
* Also picks a connection server for the client to use.
|
* Also picks a connection server for the client to use.
|
||||||
* @todo We'd like to resend this to all clients whenever the status
|
*
|
||||||
* of any servers changes
|
* Note: *** should send to individual clients - NOT all connected
|
||||||
|
* clients due to admin permissions check ***
|
||||||
*/
|
*/
|
||||||
void LoginServer::sendClusterStatus(ClientConnection &conn) const {
|
void LoginServer::sendClusterStatus(ClientConnection &conn) const {
|
||||||
const bool clientIsPrivate = AdminAccountManager::isInternalIp(conn.getRemoteAddress());
|
|
||||||
|
// Validate admin level here as clientIsPrivate. We don't need to check secure/IP because the
|
||||||
|
// connection server will force disconnect non-secure connections if they are required by configuration.
|
||||||
|
const bool clientIsPrivate = conn.getAdminLevel() > 0;
|
||||||
|
|
||||||
const unsigned int subscriptionBits = conn.getSubscriptionBits();
|
const unsigned int subscriptionBits = conn.getSubscriptionBits();
|
||||||
const bool isFreeTrialAccount = (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) &&
|
const bool isFreeTrialAccount = (((subscriptionBits & ClientSubscriptionFeature::FreeTrial) != 0) &&
|
||||||
((subscriptionBits & ClientSubscriptionFeature::Base) == 0));
|
((subscriptionBits & ClientSubscriptionFeature::Base) == 0));
|
||||||
@@ -1451,10 +1435,7 @@ void LoginServer::sendClusterStatus(ClientConnection &conn) const {
|
|||||||
if (item.m_connectionServerPort) {
|
if (item.m_connectionServerPort) {
|
||||||
item.m_connectionServerPingPort = connServer.pingPort;
|
item.m_connectionServerPingPort = connServer.pingPort;
|
||||||
|
|
||||||
// for security/confidential information issue, only report
|
if (clientIsPrivate) {
|
||||||
// population count to secured internal connections with
|
|
||||||
// admin privilege >= 10
|
|
||||||
if (clientIsPrivate && conn.getIsSecure() && (conn.getAdminLevel() >= 10)) {
|
|
||||||
item.m_populationOnline = cle->m_numPlayers;
|
item.m_populationOnline = cle->m_numPlayers;
|
||||||
} else {
|
} else {
|
||||||
item.m_populationOnline = -1;
|
item.m_populationOnline = -1;
|
||||||
@@ -1493,10 +1474,14 @@ void LoginServer::sendClusterStatus(ClientConnection &conn) const {
|
|||||||
} else {
|
} else {
|
||||||
item.m_status = LoginClusterStatus::ClusterData::S_loading;
|
item.m_status = LoginClusterStatus::ClusterData::S_loading;
|
||||||
}
|
}
|
||||||
if (cle->m_locked && !clientIsPrivate) {
|
if (cle->m_locked) {
|
||||||
item.m_status = LoginClusterStatus::ClusterData::S_locked;
|
item.m_status = LoginClusterStatus::ClusterData::S_locked;
|
||||||
} // locked takes precedence over up or loading
|
} // locked takes precedence over up or loading
|
||||||
|
|
||||||
|
// flag as admin/secret (see LoginClusterStatus.h)
|
||||||
|
item.m_isAdmin = clientIsPrivate;
|
||||||
|
item.m_isSecret = cle->m_secret;
|
||||||
|
|
||||||
item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral);
|
item.m_dontRecommend = (cle->m_notRecommendedDatabase || cle->m_notRecommendedCentral);
|
||||||
item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit;
|
item.m_onlinePlayerLimit = cle->m_onlinePlayerLimit;
|
||||||
item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit;
|
item.m_onlineFreeTrialLimit = cle->m_onlineFreeTrialLimit;
|
||||||
|
|||||||
@@ -501,6 +501,12 @@ void Client::addControlledObject(ServerObject &object) {
|
|||||||
setGodMode(true);
|
setGodMode(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validate isUsingAdminLogin each onClientReady() call per SWG Source change - 2021 (Aconite)
|
||||||
|
// isUsingAdminLogin is used to check if an *account* is in the admin table
|
||||||
|
// so we can monitor admin accessed accounts *regardless* of their current god mode/level
|
||||||
|
setUsingAdminLogin(AdminAccountManager::getAdminLevel(getAccountName()) > 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
@@ -1937,53 +1943,131 @@ float Client::computeDeltaTimeInSeconds(uint32 const syncStampLong) const {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setGodMode
|
||||||
|
* Processes the request to turn God Mode in the Client on,
|
||||||
|
* enabling admin commands and admin-treatment of a CreatureObject.
|
||||||
|
*
|
||||||
|
* @param value true = god mode on; false = god mode off
|
||||||
|
* @return true if successful, false if not
|
||||||
|
*
|
||||||
|
* Handling was rewritten by SWG Source - 2021 for applicability
|
||||||
|
* to Source/VM context
|
||||||
|
* Authors: Aconite
|
||||||
|
*/
|
||||||
bool Client::setGodMode(bool value) {
|
bool Client::setGodMode(bool value) {
|
||||||
// (re?) check god permissions
|
|
||||||
m_godLevel = AdminAccountManager::getAdminLevel(m_accountName.c_str());
|
|
||||||
|
|
||||||
if (ConfigServerGame::getAdminGodToAll() || (m_godLevel > 0)) {
|
const bool wasInGodMode = m_godMode;
|
||||||
m_godValidated = true;
|
auto * creatureObject = safe_cast<CreatureObject *>(m_primaryControlledObject.getObject());
|
||||||
if (ConfigServerGame::getAdminGodToAll()) {
|
ScriptParams params;
|
||||||
m_godLevel = ConfigServerGame::getAdminGodToAllGodLevel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wasInGodMode = m_godMode;
|
if(!creatureObject)
|
||||||
m_godMode = value;
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode failed because we couldn't get the CreatureObject.",
|
||||||
if (value && !m_godValidated) {
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
LOG("CustomerService", ("Avatar:%s denied god mode because it wasn't validated.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str()));
|
|
||||||
m_godMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreatureObject *primaryControlledObject = safe_cast<CreatureObject *>(m_primaryControlledObject.getObject());
|
|
||||||
if (!primaryControlledObject) {
|
|
||||||
if (value && !wasInGodMode) {
|
|
||||||
LOG("CustomerService", ("Avatar:%s denied god mode because it has no associated character.", m_accountName.c_str()));
|
|
||||||
}
|
|
||||||
m_godMode = false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_godMode) {
|
// Request to turn God Mode Off, in which case we don't need to validate permissions, because off isn't bad
|
||||||
IGNORE_RETURN(primaryControlledObject->grantCommand(AdminAccountManager::getAdminCommandName(), false));
|
if(!value)
|
||||||
} else {
|
{
|
||||||
primaryControlledObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true);
|
// If we were already in god mode, then we've already made an authenticated request to be in god mode,
|
||||||
}
|
// so log the event and proceed as an authorized activity, unless a script trigger blocks the switch.
|
||||||
|
if(wasInGodMode)
|
||||||
if (m_godMode != wasInGodMode) {
|
{
|
||||||
if (m_godMode) {
|
// allow a SCRIPT_OVERRIDE to block turning god mode off if necessary
|
||||||
LOG("CustomerService", ("Avatar:%s granted god mode %s level %d.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str(), AdminAccountManager::getAdminCommandName(), m_godLevel));
|
// see OnTurnedGodModeOff in script.player.base_player.java
|
||||||
} else {
|
if(creatureObject->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_SET_GOD_MODE_OFF, params) != SCRIPT_CONTINUE)
|
||||||
LOG("CustomerService", ("Avatar:%s dropped god mode.", PlayerObject::getAccountDescription(getCharacterObjectId()).c_str()));
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode off failed because OnSetGodModeOff did not return SCRIPT_CONTINUE.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode off success.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m_godLevel = 0;
|
||||||
// cell permissions may change for us for all cells, so observe all buildings in range for the change
|
m_godMode = false;
|
||||||
CellPermissions::ViewerChangeObserver o(primaryControlledObject);
|
m_godValidated = false;
|
||||||
|
// remove the characterAbility "admin" so GM commands aren't sent by the client while not in God Mode
|
||||||
ObserveTracker::onGodModeChanged(*this);
|
IGNORE_RETURN(creatureObject->revokeCommand(AdminAccountManager::getAdminCommandName(), false, true));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return (value == m_godMode); // return true if the value was set to what was requested, false otherwise
|
|
||||||
|
// If we're here, it's because the request is to turn God Mode ON
|
||||||
|
// First, determine if we're using Secure Login Mode (IP-restricted)
|
||||||
|
if(ConfigServerGame::getUseSecureLoginForGodAccess())
|
||||||
|
{
|
||||||
|
if(!AdminAccountManager::isInternalIp(getIpAddress()))
|
||||||
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because secure login was required and the connection IP was not approved.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we aren't required to be secure, or if we are and we are secure, begin permission checks
|
||||||
|
// Start with if everyone can have God Mode, in which case we don't need to bother otherwise
|
||||||
|
int godLevel = 0;
|
||||||
|
if(ConfigServerGame::getAdminGodToAll() && ConfigServerGame::getAdminGodToAllGodLevel() > 0)
|
||||||
|
{
|
||||||
|
// Make sure the account isn't in the admin table, because that should supersede
|
||||||
|
// whatever the adminGodToAll level is.
|
||||||
|
if(AdminAccountManager::getAdminLevel(m_accountName) == 0)
|
||||||
|
{
|
||||||
|
godLevel = ConfigServerGame::getAdminGodToAllGodLevel();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
godLevel = AdminAccountManager::getAdminLevel(m_accountName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We aren't giving god to everyone, so validate actual god level permissions
|
||||||
|
else
|
||||||
|
{
|
||||||
|
godLevel = AdminAccountManager::getAdminLevel(m_accountName);
|
||||||
|
}
|
||||||
|
// Grant God Mode
|
||||||
|
if(godLevel > 0)
|
||||||
|
{
|
||||||
|
// Allow a SCRIPT_OVERRIDE to block turning God Mode on via OnSetGodModeOn trigger
|
||||||
|
// see script.player.player_base.java
|
||||||
|
if(creatureObject->getScriptObject()->trigAllScripts(Scripting::TRIG_ON_SET_GOD_MODE_ON, params) != SCRIPT_CONTINUE)
|
||||||
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because OnSetGodModeOn did not return SCRIPT_CONTINUE.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// flags
|
||||||
|
m_godMode = true;
|
||||||
|
m_godValidated = true;
|
||||||
|
m_godLevel = godLevel;
|
||||||
|
|
||||||
|
// grant all commands with the "admin" characterAbility
|
||||||
|
IGNORE_RETURN(creatureObject->grantCommand(AdminAccountManager::getAdminCommandName(), false));
|
||||||
|
|
||||||
|
// reset observers and notify cells of potential change
|
||||||
|
CellPermissions::ViewerChangeObserver o(creatureObject);
|
||||||
|
ObserveTracker::onGodModeChanged(*this);
|
||||||
|
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on success.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we're here, it's because someone tried to use /setGod who doesn't have permissions
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("GodMode", ("[%s : %s : %s : %s] /setGodMode on failed because the requesting account does not have permissions.",
|
||||||
|
getAccountName().c_str(), getCharacterName().c_str(), getCharacterObjectId().getValueString().c_str(), getIpAddress().c_str()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@@ -2165,12 +2249,20 @@ void Client::launchWebBrowser(std::string const &url) const {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
bool Client::isUsingAdminLogin() const {
|
bool Client::isUsingAdminLogin() const
|
||||||
|
{
|
||||||
return m_usingAdminLogin;
|
return m_usingAdminLogin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Client::setUsingAdminLogin(bool value)
|
||||||
|
{
|
||||||
|
m_usingAdminLogin = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
bool Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const {
|
bool Client::shouldReceiveCombatSpam(NetworkId const &attacker, Vector const &attackerPosition_w, NetworkId const &defender, Vector const &defenderPosition_w) const {
|
||||||
PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam");
|
PROFILER_AUTO_BLOCK_DEFINE("Client::shouldReceiveCombatSpam");
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,8 @@ public:
|
|||||||
|
|
||||||
bool isUsingAdminLogin() const;
|
bool isUsingAdminLogin() const;
|
||||||
|
|
||||||
|
void setUsingAdminLogin(bool value);
|
||||||
|
|
||||||
CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const;
|
CombatDataTable::CombatSpamFilterType getCombatSpamFilter() const;
|
||||||
|
|
||||||
int getCombatSpamRangeSquaredFilter() const;
|
int getCombatSpamRangeSquaredFilter() const;
|
||||||
|
|||||||
@@ -330,7 +330,6 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] =
|
|||||||
|
|
||||||
{Scripting::TRIG_ENTER_REGION, "OnEnterRegion", "ss"},
|
{Scripting::TRIG_ENTER_REGION, "OnEnterRegion", "ss"},
|
||||||
{Scripting::TRIG_EXIT_REGION, "OnExitRegion", "ss"},
|
{Scripting::TRIG_EXIT_REGION, "OnExitRegion", "ss"},
|
||||||
{Scripting::TRIG_ON_PLAYER_REPORTED_CHAT, "OnPlayerReportedChat", "Ou"},
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
{Scripting::TRIG_VENDOR_ITEM_COUNT_REPLY, "OnVendorItemCountReply", "ii"},
|
{Scripting::TRIG_VENDOR_ITEM_COUNT_REPLY, "OnVendorItemCountReply", "ii"},
|
||||||
@@ -380,6 +379,9 @@ static const Scripting::ScriptFuncTable ScriptFuncList[] =
|
|||||||
|
|
||||||
{Scripting::TRIG_PVP_RANKING_CHANGED, "OnPvpRankingChanged", "ii"},
|
{Scripting::TRIG_PVP_RANKING_CHANGED, "OnPvpRankingChanged", "ii"},
|
||||||
|
|
||||||
|
{Scripting::TRIG_ON_SET_GOD_MODE_ON, "OnSetGodModeOn", ""},
|
||||||
|
{Scripting::TRIG_ON_SET_GOD_MODE_OFF, "OnSetGodModeOff", ""},
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
//-- buff builder
|
//-- buff builder
|
||||||
|
|||||||
@@ -480,7 +480,8 @@ enum TrigId
|
|||||||
TRIG_ON_ABANDON_PLAYER_QUEST = 302,
|
TRIG_ON_ABANDON_PLAYER_QUEST = 302,
|
||||||
TRIG_ON_GCW_SCORE_CATEGORY_PERCENTILE_CHANGE = 303,
|
TRIG_ON_GCW_SCORE_CATEGORY_PERCENTILE_CHANGE = 303,
|
||||||
TRIG_WAYPOINT_WARP = 304,
|
TRIG_WAYPOINT_WARP = 304,
|
||||||
TRIG_ON_PLAYER_REPORTED_CHAT = 305,
|
TRIG_ON_SET_GOD_MODE_ON = 305,
|
||||||
|
TRIG_ON_SET_GOD_MODE_OFF = 306,
|
||||||
TRIG_LAST_TRIGGER
|
TRIG_LAST_TRIGGER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,19 @@
|
|||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
ClientPermissionsMessage::ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial) :
|
ClientPermissionsMessage::ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, bool isAdmin) :
|
||||||
GameNetworkMessage("ClientPermissionsMessage"),
|
GameNetworkMessage("ClientPermissionsMessage"),
|
||||||
m_canLogin(canLogin),
|
m_canLogin(canLogin),
|
||||||
m_canCreateRegularCharacter(canCreateRegularCharacter),
|
m_canCreateRegularCharacter(canCreateRegularCharacter),
|
||||||
m_canCreateJediCharacter(canCreateJediCharacter),
|
m_canCreateJediCharacter(canCreateJediCharacter),
|
||||||
m_canSkipTutorial(canSkipTutorial)
|
m_canSkipTutorial(canSkipTutorial),
|
||||||
|
m_isAdmin(isAdmin)
|
||||||
{
|
{
|
||||||
addVariable(m_canLogin);
|
addVariable(m_canLogin);
|
||||||
addVariable(m_canCreateRegularCharacter);
|
addVariable(m_canCreateRegularCharacter);
|
||||||
addVariable(m_canCreateJediCharacter);
|
addVariable(m_canCreateJediCharacter);
|
||||||
addVariable(m_canSkipTutorial);
|
addVariable(m_canSkipTutorial);
|
||||||
|
addVariable(m_isAdmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@@ -30,12 +32,14 @@ ClientPermissionsMessage::ClientPermissionsMessage(Archive::ReadIterator & sourc
|
|||||||
m_canLogin(),
|
m_canLogin(),
|
||||||
m_canCreateRegularCharacter(),
|
m_canCreateRegularCharacter(),
|
||||||
m_canCreateJediCharacter(),
|
m_canCreateJediCharacter(),
|
||||||
m_canSkipTutorial()
|
m_canSkipTutorial(),
|
||||||
|
m_isAdmin()
|
||||||
{
|
{
|
||||||
addVariable(m_canLogin);
|
addVariable(m_canLogin);
|
||||||
addVariable(m_canCreateRegularCharacter);
|
addVariable(m_canCreateRegularCharacter);
|
||||||
addVariable(m_canCreateJediCharacter);
|
addVariable(m_canCreateJediCharacter);
|
||||||
addVariable(m_canSkipTutorial);
|
addVariable(m_canSkipTutorial);
|
||||||
|
addVariable(m_isAdmin);
|
||||||
|
|
||||||
unpack(source);
|
unpack(source);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
class ClientPermissionsMessage : public GameNetworkMessage
|
class ClientPermissionsMessage : public GameNetworkMessage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial);
|
ClientPermissionsMessage(bool canLogin, bool canCreateRegularCharacter, bool canCreateJediCharacter, bool canSkipTutorial, bool isAdmin);
|
||||||
explicit ClientPermissionsMessage(Archive::ReadIterator & source);
|
explicit ClientPermissionsMessage(Archive::ReadIterator & source);
|
||||||
virtual ~ClientPermissionsMessage();
|
virtual ~ClientPermissionsMessage();
|
||||||
|
|
||||||
@@ -33,12 +33,14 @@ class ClientPermissionsMessage : public GameNetworkMessage
|
|||||||
bool getCanCreateRegularCharacter() const;
|
bool getCanCreateRegularCharacter() const;
|
||||||
bool getCanCreateJediCharacter() const;
|
bool getCanCreateJediCharacter() const;
|
||||||
bool getCanSkipTutorial() const;
|
bool getCanSkipTutorial() const;
|
||||||
|
bool getIsAdmin() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Archive::AutoVariable<bool> m_canLogin;
|
Archive::AutoVariable<bool> m_canLogin;
|
||||||
Archive::AutoVariable<bool> m_canCreateRegularCharacter;
|
Archive::AutoVariable<bool> m_canCreateRegularCharacter;
|
||||||
Archive::AutoVariable<bool> m_canCreateJediCharacter;
|
Archive::AutoVariable<bool> m_canCreateJediCharacter;
|
||||||
Archive::AutoVariable<bool> m_canSkipTutorial;
|
Archive::AutoVariable<bool> m_canSkipTutorial;
|
||||||
|
Archive::AutoVariable<bool> m_isAdmin;
|
||||||
|
|
||||||
ClientPermissionsMessage();
|
ClientPermissionsMessage();
|
||||||
ClientPermissionsMessage(const ClientPermissionsMessage&);
|
ClientPermissionsMessage(const ClientPermissionsMessage&);
|
||||||
@@ -73,6 +75,13 @@ inline bool ClientPermissionsMessage::getCanSkipTutorial() const
|
|||||||
return m_canSkipTutorial.get();
|
return m_canSkipTutorial.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline bool ClientPermissionsMessage::getIsAdmin() const
|
||||||
|
{
|
||||||
|
return m_isAdmin.get();
|
||||||
|
}
|
||||||
|
|
||||||
// ======================================================================
|
// ======================================================================
|
||||||
|
|
||||||
#endif // _INCLUDED_ClientCentralMessages_H
|
#endif // _INCLUDED_ClientCentralMessages_H
|
||||||
|
|||||||
@@ -31,6 +31,17 @@ struct LoginClusterStatus_ClusterData
|
|||||||
bool m_dontRecommend;
|
bool m_dontRecommend;
|
||||||
uint32 m_onlinePlayerLimit;
|
uint32 m_onlinePlayerLimit;
|
||||||
uint32 m_onlineFreeTrialLimit;
|
uint32 m_onlineFreeTrialLimit;
|
||||||
|
|
||||||
|
// This flag tells the client that the account which requested the cluster information
|
||||||
|
// is considered an admin by the server (in Admin Account Table). This enables connection
|
||||||
|
// to locked clusters and viewing secret clusters. We don't need to worry about this flag
|
||||||
|
// being manipulated because the Connection Server verifies admin permissions after the fact.
|
||||||
|
// This flag merely unblocks client-side user interface elements for locked/secret clusters.
|
||||||
|
// We also send this flag in the ClientPermissionsMessage header for character creation.
|
||||||
|
bool m_isAdmin;
|
||||||
|
// Flag so we can append (Secret) in Client (for admins)
|
||||||
|
bool m_isSecret;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,6 +96,8 @@ namespace Archive
|
|||||||
get(source,c.m_dontRecommend);
|
get(source,c.m_dontRecommend);
|
||||||
get(source,c.m_onlinePlayerLimit);
|
get(source,c.m_onlinePlayerLimit);
|
||||||
get(source,c.m_onlineFreeTrialLimit);
|
get(source,c.m_onlineFreeTrialLimit);
|
||||||
|
get(source, c.m_isAdmin);
|
||||||
|
get(source,c.m_isSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void put(ByteStream & target, const LoginClusterStatus_ClusterData &c)
|
inline void put(ByteStream & target, const LoginClusterStatus_ClusterData &c)
|
||||||
@@ -101,6 +114,8 @@ namespace Archive
|
|||||||
put(target,c.m_dontRecommend);
|
put(target,c.m_dontRecommend);
|
||||||
put(target,c.m_onlinePlayerLimit);
|
put(target,c.m_onlinePlayerLimit);
|
||||||
put(target,c.m_onlineFreeTrialLimit);
|
put(target,c.m_onlineFreeTrialLimit);
|
||||||
|
put(target,c.m_isAdmin);
|
||||||
|
put(target,c.m_isSecret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user