diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 76ff68b117..ba461f0d01 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -67,21 +67,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController private IConfig m_config; private IConfigSource m_configSource; private string m_requiredPassword = String.Empty; + private List m_accessIP; private string m_name = "RemoteAdminPlugin"; private string m_version = "0.0"; - //guard for XmlRpc-related methods - private void FailIfRemoteAdminDisabled(string requestName) - { - if (m_config == null) - { - string errorMessage = String.Format("[RADMIN] {0}: Remote admin request denied! Please set [RemoteAdmin]enabled=true in OpenSim.ini in order to enable remote admin functionality", requestName); - m_log.Error(errorMessage); - throw new ApplicationException(errorMessage); - } - } - public string Version { get { return m_version; } @@ -115,6 +105,20 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_requiredPassword = m_config.GetString("access_password", String.Empty); int port = m_config.GetInt("port", 0); + string accessIP = m_config.GetString("access_ip_addresses", String.Empty); + m_accessIP = new List(); + if (accessIP != String.Empty) + { + string[] ips = accessIP.Split(new char[] { ',' }); + foreach (string ip in ips) + { + string current = ip.Trim(); + + if (current != String.Empty) + m_accessIP.Add(current); + } + } + m_application = openSim; string bind_ip_address = m_config.GetString("bind_ip_address", "0.0.0.0"); IPAddress ipaddr = IPAddress.Parse(bind_ip_address); @@ -190,6 +194,31 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } + private void FailIfRemoteAdminDisabled(string requestName) + { + if (m_config == null) + { + string errorMessage = String.Format("[RADMIN] {0}: Remote admin request denied! Please set [RemoteAdmin] enabled=true in OpenSim.ini in order to enable remote admin functionality", requestName); + m_log.Error(errorMessage); + throw new ApplicationException(errorMessage); + } + } + + private void FailIfRemoteAdminNotAllowed(string password, string check_ip_address) + { + if (m_accessIP.Count > 0 && !m_accessIP.Contains(check_ip_address)) + { + m_log.WarnFormat("[RADMIN]: Unauthorized acess blocked from IP {0}", check_ip_address); + throw new Exception("not authorized"); + } + + if (m_requiredPassword != String.Empty && password != m_requiredPassword) + { + m_log.WarnFormat("[RADMIN]: Wrong password, blocked access from IP {0}", check_ip_address); + throw new Exception("wrong password"); + } + } + public XmlRpcResponse XmlRpcRestartMethod(XmlRpcRequest request, IPEndPoint remoteClient) { XmlRpcResponse response = new XmlRpcResponse(); @@ -202,11 +231,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_log.Info("[RADMIN]: Request to restart Region."); CheckStringParameters(request, new string[] {"password", "regionID"}); - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != m_requiredPassword)) - { - throw new Exception("wrong password"); - } + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); UUID regionID = new UUID((string) requestData["regionID"]); @@ -292,9 +317,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController CheckStringParameters(request, new string[] {"password", "message"}); - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != m_requiredPassword)) - throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string message = (string) requestData["message"]; m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); @@ -392,9 +415,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController CheckStringParameters(request, new string[] {"password", "filename", "regionid"}); - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != m_requiredPassword)) - throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string file = (string) requestData["filename"]; UUID regionID = (UUID) (string) requestData["regionid"]; @@ -457,9 +478,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController CheckStringParameters(request, new string[] { "password", "filename", "regionid" }); - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string)requestData["password"] != m_requiredPassword)) - throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string file = (string)requestData["filename"]; UUID regionID = (UUID)(string)requestData["regionid"]; @@ -507,9 +526,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - if (m_requiredPassword != String.Empty && - (!requestData.Contains("password") || (string) requestData["password"] != m_requiredPassword)) - throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); responseData["accepted"] = true; response.Value = responseData; @@ -681,9 +698,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController }); CheckIntegerParams(request, new string[] {"region_x", "region_y", "listen_port"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); // check whether we still have space left (iff we are using limits) if (m_regionLimit != 0 && m_application.SceneManager.Scenes.Count >= m_regionLimit) @@ -945,6 +960,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController public XmlRpcResponse XmlRpcDeleteRegionMethod(XmlRpcRequest request, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: DeleteRegion: new request"); + XmlRpcResponse response = new XmlRpcResponse(); Hashtable responseData = new Hashtable(); @@ -955,6 +971,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; CheckStringParameters(request, new string[] {"password", "region_name"}); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + Scene scene = null; string regionName = (string) requestData["region_name"]; if (!m_application.SceneManager.TryGetScene(regionName, out scene)) @@ -1024,6 +1042,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; CheckStringParameters(request, new string[] {"password"}); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + if (requestData.ContainsKey("region_id") && !String.IsNullOrEmpty((string) requestData["region_id"])) { @@ -1118,6 +1138,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; CheckStringParameters(request, new string[] {"password", "region_name"}); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + Scene scene = null; string regionName = (string) requestData["region_name"]; if (!m_application.SceneManager.TryGetScene(regionName, out scene)) @@ -1231,9 +1253,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController }); CheckIntegerParams(request, new string[] {"start_region_x", "start_region_y"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); // do the job string firstName = (string) requestData["user_firstname"]; @@ -1341,6 +1361,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController // check completeness CheckStringParameters(request, new string[] {"password", "user_firstname", "user_lastname"}); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); + string firstName = (string) requestData["user_firstname"]; string lastName = (string) requestData["user_lastname"]; @@ -1425,7 +1447,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// /// /// - public XmlRpcResponse XmlRpcUpdateUserAccountMethod(XmlRpcRequest request, IPEndPoint remoteClient) { m_log.Info("[RADMIN]: UpdateUserAccount: new request"); @@ -1447,9 +1468,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController "password", "user_firstname", "user_lastname"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); // do the job string firstName = (string) requestData["user_firstname"]; @@ -1565,7 +1584,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// file, or pre-existing in the user database. /// This should probably get moved into somewhere more core eventually. /// - private void UpdateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid) { m_log.DebugFormat("[RADMIN]: updateUserAppearance"); @@ -1647,7 +1665,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// ratified, or an appropriate default value has been adopted. The intended prototype /// is known to exist, as is the target avatar. /// - private void EstablishAppearance(UUID destination, UUID source) { m_log.DebugFormat("[RADMIN]: Initializing inventory for {0} from {1}", destination, source); @@ -1715,7 +1732,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// worn or attached to the Clothing inventory folder of the receiving avatar. /// In parallel the avatar wearables and attachments are updated. /// - private void CopyWearablesAndAttachments(UUID destination, UUID source, AvatarAppearance avatarAppearance) { IInventoryService inventoryService = m_application.SceneManager.CurrentOrFirstScene.InventoryService; @@ -1745,7 +1761,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController AvatarWearable[] wearables = avatarAppearance.Wearables; AvatarWearable wearable; - for (int i=0; i /// This method is called by establishAppearance to copy inventory folders to make /// copies of Clothing and Bodyparts inventory folders and attaches worn attachments /// - private void CopyInventoryFolders(UUID destination, UUID source, AssetType assetType, Dictionary inventoryMap, AvatarAppearance avatarAppearance) { @@ -1891,9 +1904,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController { destinationFolder = new InventoryFolderBase(); destinationFolder.ID = UUID.Random(); - if (assetType == AssetType.Clothing) { + if (assetType == AssetType.Clothing) + { destinationFolder.Name = "Clothing"; - } else { + } + else + { destinationFolder.Name = "Body Parts"; } destinationFolder.Owner = destination; @@ -1909,7 +1925,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController foreach (InventoryFolderBase folder in folders) { - extraFolder = new InventoryFolderBase(); extraFolder.ID = UUID.Random(); extraFolder.Name = folder.Name; @@ -1967,7 +1982,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// /// Apply next owner permissions. /// - private void ApplyNextOwnerPermissions(InventoryItemBase item) { if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) @@ -2360,18 +2374,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - foreach (string parameter in new string[] {"password", "filename"}) - { - if (!requestData.Contains(parameter)) - throw new Exception(String.Format("missing parameter {0}", parameter)); - if (String.IsNullOrEmpty((string) requestData[parameter])) - throw new Exception(String.Format("parameter {0} is empty", parameter)); - } + CheckStringParameters(request, new string[] { + "password", "filename"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string filename = (string) requestData["filename"]; Scene scene = null; @@ -2477,18 +2483,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - foreach (string p in new string[] {"password", "filename"}) - { - if (!requestData.Contains(p)) - throw new Exception(String.Format("missing parameter {0}", p)); - if (String.IsNullOrEmpty((string) requestData[p])) - throw new Exception(String.Format("parameter {0} is empty")); - } + CheckStringParameters(request, new string[] { + "password", "filename"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string filename = (string) requestData["filename"]; Scene scene = null; @@ -2534,11 +2532,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController { scene.EventManager.OnOarFileSaved += RemoteAdminOarSaveCompleted; archiver.ArchiveRegion(filename, options); - lock (m_saveOarLock) Monitor.Wait(m_saveOarLock,5000); + + lock (m_saveOarLock) + Monitor.Wait(m_saveOarLock,5000); + scene.EventManager.OnOarFileSaved -= RemoteAdminOarSaveCompleted; } else + { throw new Exception("Archiver module not present for scene"); + } responseData["saved"] = true; @@ -2579,18 +2582,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - foreach (string p in new string[] {"password", "filename"}) - { - if (!requestData.Contains(p)) - throw new Exception(String.Format("missing parameter {0}", p)); - if (String.IsNullOrEmpty((string) requestData[p])) - throw new Exception(String.Format("parameter {0} is empty")); - } + CheckStringParameters(request, new string[] { + "password", "filename"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string filename = (string) requestData["filename"]; if (requestData.Contains("region_uuid")) @@ -2598,6 +2593,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) @@ -2605,6 +2601,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2663,18 +2660,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController { Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - foreach (string p in new string[] {"password", "filename"}) - { - if (!requestData.Contains(p)) - throw new Exception(String.Format("missing parameter {0}", p)); - if (String.IsNullOrEmpty((string) requestData[p])) - throw new Exception(String.Format("parameter {0} is empty")); - } + CheckStringParameters(request, new string[] { + "password", "filename"}); - // check password - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); string filename = (string) requestData["filename"]; if (requestData.Contains("region_uuid")) @@ -2749,17 +2738,17 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); if (requestData.Contains("region_uuid")) { UUID region_uuid = (UUID) (string) requestData["region_uuid"]; if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); } else if (requestData.Contains("region_name")) @@ -2767,6 +2756,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); @@ -2792,6 +2782,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } m_log.Info("[RADMIN]: Query XML Administrator Request complete"); + return response; } @@ -2810,14 +2801,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - // check completeness - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password", "command"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); - if (!requestData.Contains("command")) - throw new Exception(String.Format("missing required parameter")); MainConsole.Instance.RunCommand(requestData["command"].ToString()); response.Value = responseData; @@ -2851,10 +2839,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); if (requestData.Contains("region_uuid")) { @@ -2868,12 +2856,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController string region_name = (string) requestData["region_name"]; if (!m_application.SceneManager.TrySetCurrentScene(region_name)) throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); } else throw new Exception("neither region_name nor region_uuid given"); Scene scene = m_application.SceneManager.CurrentScene; scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; + if (scene.RegionInfo.Persistent) scene.RegionInfo.EstateSettings.Save(); } @@ -2908,10 +2898,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); if (requestData.Contains("region_uuid")) { @@ -2995,10 +2985,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); if (requestData.Contains("region_uuid")) { @@ -3082,10 +3072,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable requestData = (Hashtable) request.Params[0]; - if (!requestData.Contains("password")) - throw new Exception(String.Format("missing required parameter")); - if (!String.IsNullOrEmpty(m_requiredPassword) && - (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + CheckStringParameters(request, new string[] { + "password"}); + + FailIfRemoteAdminNotAllowed((string)requestData["password"], remoteClient.Address.ToString()); if (requestData.Contains("region_uuid")) { @@ -3299,7 +3289,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController bool success = false; if (authenticationService != null) success = authenticationService.SetPassword(account.PrincipalID, password); - if (!success) { + + if (!success) + { m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", firstName, lastName); return false; @@ -3313,4 +3305,4 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } } -} +} \ No newline at end of file diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index d7959521a5..d7c3a64731 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -405,6 +405,10 @@ ;; the "password" parameter) ; access_password = "" + ;# List the IP addresses allowed to call RemoteAdmin + ;; access_ip_addresses = 0.0.0.0, 0.0.0.0 ... + ; access_ip_addresses = + ;# {create_region_enable_voice} {enabled:true} {Enable voice for newly created regions?} {true false} false ;; set this variable to true if you want the create_region XmlRpc ;; call to unconditionally enable voice on all parcels for a newly diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index c4f5592816..a2542da1fb 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -802,6 +802,10 @@ ; This password is required to make any XMLRPC call (should be set as the "password" parameter) access_password = unknown + ; List the IP addresses allowed to call RemoteAdmin + ; access_ip_addresses = 0.0.0.0, 0.0.0.0 ... + ; access_ip_addresses = + ; set this variable to true if you want the create_region XmlRpc ; call to unconditionally enable voice on all parcels for a newly ; created region [default: false]