--- OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs.orig 2014-05-28 17:47:10.254150459 +0100 +++ OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs 2014-05-28 17:47:13.926150343 +0100 @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Xml; using System.Net; @@ -51,6 +52,7 @@ using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PermissionMask = OpenSim.Framework.PermissionMask; +using RegionInfo = OpenSim.Framework.RegionInfo; namespace OpenSim.ApplicationPlugins.RemoteController { @@ -145,6 +147,7 @@ availableMethods["admin_create_user_email"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcCreateUserMethod); availableMethods["admin_exists_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUserExistsMethod); availableMethods["admin_update_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcUpdateUserAccountMethod); + availableMethods["admin_authenticate_user"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcAuthenticateUserMethod); // Region state management availableMethods["admin_load_xml"] = (req, ep) => InvokeXmlRpcMethod(req, ep, XmlRpcLoadXMLMethod); @@ -1280,6 +1283,139 @@ } } + /// + /// Authenticate an user. + /// + /// incoming XML RPC request + /// + /// XmlRpcAuthenticateUserMethod takes the following XMLRPC + /// parameters + /// + /// parameter namedescription + /// password + /// admin password as set in OpenSim.ini + /// user_firstname + /// avatar's first name + /// user_lastname + /// avatar's last name + /// user_password + /// MD5 hash of avatar's password + /// token_lifetime + /// the lifetime of the returned token (upper bounded to 30s) + /// + /// + /// XmlRpcAuthenticateUserMethod returns + /// + /// namedescription + /// success + /// true or false + /// token + /// the authentication token sent by OpenSim + /// error + /// error message if success is false + /// + /// + private void XmlRpcAuthenticateUserMethod(XmlRpcRequest request, XmlRpcResponse response, + IPEndPoint remoteClient) + { + m_log.Info("[RADMIN]: AuthenticateUser: new request"); + + var responseData = (Hashtable)response.Value; + var requestData = (Hashtable)request.Params[0]; + + lock (m_requestLock) + { + try + { + CheckStringParameters(requestData, responseData, new[] + { + "user_firstname", + "user_lastname", + "user_password", + "token_lifetime" + }); + + var firstName = (string)requestData["user_firstname"]; + var lastName = (string)requestData["user_lastname"]; + var password = (string)requestData["user_password"]; + + var scene = m_application.SceneManager.CurrentOrFirstScene; + + if (scene.Equals(null)) + { + m_log.Debug("scene does not exist"); + throw new Exception("Scene does not exist."); + } + + var scopeID = scene.RegionInfo.ScopeID; + var account = scene.UserAccountService.GetUserAccount(scopeID, firstName, lastName); + + if (account.Equals(null) || account.PrincipalID.Equals(UUID.Zero)) + { + m_log.DebugFormat("avatar {0} {1} does not exist", firstName, lastName); + throw new Exception(String.Format("avatar {0} {1} does not exist", firstName, lastName)); + } + + if (String.IsNullOrEmpty(password)) + { + m_log.DebugFormat("[RADMIN]: AuthenticateUser: no password provided for {0} {1}", firstName, + lastName); + throw new Exception(String.Format("no password provided for {0} {1}", firstName, + lastName)); + } + + int lifetime; + if (int.TryParse((string)requestData["token_lifetime"], NumberStyles.Integer, CultureInfo.InvariantCulture, out lifetime) == false) + { + m_log.DebugFormat("[RADMIN]: AuthenticateUser: no token lifetime provided for {0} {1}", firstName, + lastName); + throw new Exception(String.Format("no token lifetime provided for {0} {1}", firstName, + lastName)); + } + + // Upper bound on lifetime set to 30s. + if (lifetime > 30) + { + m_log.DebugFormat("[RADMIN]: AuthenticateUser: token lifetime longer than 30s for {0} {1}", firstName, + lastName); + throw new Exception(String.Format("token lifetime longer than 30s for {0} {1}", firstName, + lastName)); + } + + var authModule = scene.RequestModuleInterface(); + if (authModule == null) + { + m_log.Debug("[RADMIN]: AuthenticateUser: no authentication module loded"); + throw new Exception("no authentication module loaded"); + } + + var token = authModule.Authenticate(account.PrincipalID, password, lifetime); + if (String.IsNullOrEmpty(token)) + { + m_log.DebugFormat("[RADMIN]: AuthenticateUser: authentication failed for {0} {1}", firstName, + lastName); + throw new Exception(String.Format("authentication failed for {0} {1}", firstName, + lastName)); + } + + m_log.DebugFormat("[RADMIN]: AuthenticateUser: account for user {0} {1} identified with token {2}", + firstName, lastName, token); + + responseData["token"] = token; + responseData["success"] = true; + + } + catch (Exception e) + { + responseData["success"] = false; + responseData["error"] = e.Message; + throw e; + } + + m_log.Info("[RADMIN]: AuthenticateUser: request complete"); + } + } + /// /// Load an OAR file into a region.. ///