From ee9aca9c5270e22407c3aa4aa96c76ca92f90bb9 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 25 Nov 2010 20:34:55 +0100 Subject: [PATCH] Add the ability for gods to impersonate users. For this, bit 6 needs to be set in the target's UserFlags and the impersonator must have UserLevel 200 or above. The user can then log in using the target's name and their own password. --- OpenSim/Data/IUserAccountData.cs | 1 + OpenSim/Data/MSSQL/MSSQLUserAccountData.cs | 5 ++ OpenSim/Data/MySQL/MySQLUserAccountData.cs | 15 +++++ OpenSim/Data/Null/NullUserAccountData.cs | 5 ++ OpenSim/Data/SQLite/SQLiteUserAccountData.cs | 5 ++ .../SQLiteLegacy/SQLiteUserAccountData.cs | 5 ++ .../LocalUserAccountServiceConnector.cs | 5 ++ .../AuthenticationServiceBase.cs | 8 +++ .../PasswordAuthenticationService.cs | 62 ++++++++++++++++--- .../WebkeyAuthenticationService.cs | 5 ++ .../SimianUserAccountServiceConnector.cs | 5 ++ .../UserAccountServiceConnector.cs | 5 ++ .../Interfaces/IUserAccountService.cs | 1 + .../Services/LLLoginService/LLLoginService.cs | 3 +- .../UserAccountService/UserAccountService.cs | 15 +++++ prebuild.xml | 1 + 16 files changed, 138 insertions(+), 8 deletions(-) diff --git a/OpenSim/Data/IUserAccountData.cs b/OpenSim/Data/IUserAccountData.cs index 906ba6c561..bc7eda7d16 100644 --- a/OpenSim/Data/IUserAccountData.cs +++ b/OpenSim/Data/IUserAccountData.cs @@ -50,5 +50,6 @@ namespace OpenSim.Data bool Store(UserAccountData data); bool Delete(string field, string val); UserAccountData[] GetUsers(UUID scopeID, string query); + UserAccountData[] GetUsersWhere(UUID scopeID, string where); } } diff --git a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs index e7c8dc5a7e..f24b441c44 100644 --- a/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs +++ b/OpenSim/Data/MSSQL/MSSQLUserAccountData.cs @@ -238,5 +238,10 @@ namespace OpenSim.Data.MSSQL return DoQuery(cmd); } } + + public UserAccountData[] GetUsersWhere(UUID scopeID, string where) + { + return null; + } } } diff --git a/OpenSim/Data/MySQL/MySQLUserAccountData.cs b/OpenSim/Data/MySQL/MySQLUserAccountData.cs index aa69d680a7..3b3522225c 100644 --- a/OpenSim/Data/MySQL/MySQLUserAccountData.cs +++ b/OpenSim/Data/MySQL/MySQLUserAccountData.cs @@ -80,5 +80,20 @@ namespace OpenSim.Data.MySQL return DoQuery(cmd); } + + public UserAccountData[] GetUsersWhere(UUID scopeID, string where) + { + MySqlCommand cmd = new MySqlCommand(); + + if (scopeID != UUID.Zero) + { + where = "(ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (" + where + ")"; + cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString()); + } + + cmd.CommandText = String.Format("select * from {0} where " + where, m_Realm); + + return DoQuery(cmd); + } } } diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs index ede23fb8fe..772d821731 100644 --- a/OpenSim/Data/Null/NullUserAccountData.cs +++ b/OpenSim/Data/Null/NullUserAccountData.cs @@ -156,5 +156,10 @@ namespace OpenSim.Data.Null return false; } + + public UserAccountData[] GetUsersWhere(UUID scopeID, string where) + { + return null; + } } } diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs index 7a5de5073d..4d580c08cc 100644 --- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs @@ -81,5 +81,10 @@ namespace OpenSim.Data.SQLite return DoQuery(cmd); } + + public UserAccountData[] GetUsersWhere(UUID scopeID, string where) + { + return null; + } } } diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs index 27553c61eb..41a0177ca0 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs @@ -77,5 +77,10 @@ namespace OpenSim.Data.SQLiteLegacy return DoQuery(cmd); } + + public UserAccountData[] GetUsersWhere(UUID scopeID, string where) + { + return null; + } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index 30ebb2147b..9ecbcc631e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs @@ -172,6 +172,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts return m_UserService.GetUserAccount(scopeID, Email); } + public List GetUserAccountsWhere(UUID scopeID, string query) + { + return null; + } + public List GetUserAccounts(UUID scopeID, string query) { return m_UserService.GetUserAccounts(scopeID, query); diff --git a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs index edc1097818..5980f0ce2f 100644 --- a/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs +++ b/OpenSim/Services/AuthenticationService/AuthenticationServiceBase.cs @@ -31,6 +31,8 @@ using log4net; using Nini.Config; using System.Reflection; using OpenSim.Services.Base; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; using OpenSim.Data; using OpenSim.Framework; @@ -49,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService MethodBase.GetCurrentMethod().DeclaringType); protected IAuthenticationData m_Database; + protected IUserAccountService m_UserAccountService = null; + + public AuthenticationServiceBase(IConfigSource config, IUserAccountService acct) : this(config) + { + m_UserAccountService = acct; + } public AuthenticationServiceBase(IConfigSource config) : base(config) { diff --git a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs index 17619ff14f..cf7496f434 100644 --- a/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/PasswordAuthenticationService.cs @@ -51,6 +51,12 @@ namespace OpenSim.Services.AuthenticationService LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); + public PasswordAuthenticationService(IConfigSource config, IUserAccountService userService) : + base(config, userService) + { + m_log.Debug("[AUTH SERVICE]: Started with User Account access"); + } + public PasswordAuthenticationService(IConfigSource config) : base(config) { @@ -58,28 +64,70 @@ namespace OpenSim.Services.AuthenticationService public string Authenticate(UUID principalID, string password, int lifetime) { + m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null); AuthenticationData data = m_Database.Get(principalID); + UserAccount user = null; + if (m_UserAccountService != null) + user = m_UserAccountService.GetUserAccount(UUID.Zero, principalID); - if (data != null && data.Data != null) + if (data == null || data.Data == null) { - if (!data.Data.ContainsKey("passwordHash") || + m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); + return String.Empty; + } + + if (!data.Data.ContainsKey("passwordHash") || + !data.Data.ContainsKey("passwordSalt")) + { + return String.Empty; + } + + string hashed = Util.Md5Hash(password + ":" + + data.Data["passwordSalt"].ToString()); + + m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); + + if (data.Data["passwordHash"].ToString() == hashed) + { + return GetToken(principalID, lifetime); + } + + if (user == null) + { + m_log.DebugFormat("[PASS AUTH]: No user record for {0}", principalID); + return String.Empty; + } + + int impersonateFlag = 1 << 6; + + if ((user.UserFlags & impersonateFlag) == 0) + return String.Empty; + + List accounts = m_UserAccountService.GetUserAccountsWhere(UUID.Zero, "UserLevel >= 200"); + if (accounts == null || accounts.Count == 0) + return String.Empty; + + foreach (UserAccount a in accounts) + { + data = m_Database.Get(a.PrincipalID); + if (data == null || data.Data == null || + !data.Data.ContainsKey("passwordHash") || !data.Data.ContainsKey("passwordSalt")) { - return String.Empty; + continue; } - string hashed = Util.Md5Hash(password + ":" + + hashed = Util.Md5Hash(password + ":" + data.Data["passwordSalt"].ToString()); - m_log.DebugFormat("[PASS AUTH]: got {0}; hashed = {1}; stored = {2}", password, hashed, data.Data["passwordHash"].ToString()); - if (data.Data["passwordHash"].ToString() == hashed) { + m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID); return GetToken(principalID, lifetime); } } - m_log.DebugFormat("[AUTH SERVICE]: PrincipalID {0} or its data not found", principalID); + m_log.DebugFormat("[PASS AUTH]: Impersonation of {0} failed", principalID); return String.Empty; } } diff --git a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs index d1a5b0f041..6d9aae32fa 100644 --- a/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs +++ b/OpenSim/Services/AuthenticationService/WebkeyAuthenticationService.cs @@ -47,6 +47,11 @@ namespace OpenSim.Services.AuthenticationService // LogManager.GetLogger( // MethodBase.GetCurrentMethod().DeclaringType); + public WebkeyAuthenticationService(IConfigSource config, IUserAccountService userService) : + base(config, userService) + { + } + public WebkeyAuthenticationService(IConfigSource config) : base(config) { diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index 9c150ee417..394c2b7d09 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -191,6 +191,11 @@ namespace OpenSim.Services.Connectors.SimianGrid return accounts; } + public List GetUserAccountsWhere(UUID scopeID, string query) + { + return null; + } + public bool StoreUserAccount(UserAccount data) { m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Storing user account for " + data.Name); diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 2a5df83193..205a4aa94f 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -187,6 +187,11 @@ namespace OpenSim.Services.Connectors return accounts; } + public List GetUserAccountsWhere(UUID scopeID, string where) + { + return null; // Not implemented for regions + } + public virtual bool StoreUserAccount(UserAccount data) { Dictionary sendData = new Dictionary(); diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index c580078de3..2c09a2ebe7 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -150,6 +150,7 @@ namespace OpenSim.Services.Interfaces /// /// List GetUserAccounts(UUID scopeID, string query); + List GetUserAccountsWhere(UUID scopeID, string where); /// /// Store the data given, wich replaces the stored data, therefore must be complete. diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 35adf0fde6..b26cd6e149 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -113,7 +113,8 @@ namespace OpenSim.Services.LLLoginService Object[] args = new Object[] { config }; m_UserAccountService = ServerUtils.LoadPlugin(accountService, args); m_GridUserService = ServerUtils.LoadPlugin(gridUserService, args); - m_AuthenticationService = ServerUtils.LoadPlugin(authService, args); + Object[] authArgs = new Object[] { config, m_UserAccountService }; + m_AuthenticationService = ServerUtils.LoadPlugin(authService, authArgs); m_InventoryService = ServerUtils.LoadPlugin(invService, args); if (gridService != string.Empty) diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index f376cf825b..de6d32c9ae 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -282,6 +282,21 @@ namespace OpenSim.Services.UserAccountService return ret; } + public List GetUserAccountsWhere(UUID scopeID, string where) + { + UserAccountData[] d = m_Database.GetUsersWhere(scopeID, where); + + if (d == null) + return new List(); + + List ret = new List(); + + foreach (UserAccountData data in d) + ret.Add(MakeUserAccount(data)); + + return ret; + } + #endregion #region Console commands diff --git a/prebuild.xml b/prebuild.xml index 85b31da31a..f08d0d3908 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1091,6 +1091,7 @@ +