About

This patch adds the admin_authenticate_user command to OpenSim and allows authenticating to OpenSim via PHP it will also show up on the release version of OpenSim from 0.8 and onward.

Code

remote_admin_authenticate.patch
--- 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 @@
             }
         }
 
+        /// <summary>
+        /// Authenticate an user.
+        /// <summary>
+        /// <param name="request">incoming XML RPC request</param>
+        /// <remarks>
+        /// XmlRpcAuthenticateUserMethod takes the following XMLRPC
+        /// parameters
+        /// <list type="table">
+        /// <listheader><term>parameter name</term><description>description</description></listheader>
+        /// <item><term>password</term>
+        ///       <description>admin password as set in OpenSim.ini</description></item>
+        /// <item><term>user_firstname</term>
+        ///       <description>avatar's first name</description></item>
+        /// <item><term>user_lastname</term>
+        ///       <description>avatar's last name</description></item>
+        /// <item><term>user_password</term>
+        ///       <description>MD5 hash of avatar's password</description></item>
+        /// <item><term>token_lifetime</term>
+        ///       <description>the lifetime of the returned token (upper bounded to 30s)</description></item>
+        /// </list>
+        ///
+        /// XmlRpcAuthenticateUserMethod returns
+        /// <list type="table">
+        /// <listheader><term>name</term><description>description</description></listheader>
+        /// <item><term>success</term>
+        ///       <description>true or false</description></item>
+        /// <item><term>token</term>
+        ///       <description>the authentication token sent by OpenSim</description></item>
+        /// <item><term>error</term>
+        ///       <description>error message if success is false</description></item>
+        /// </list>
+        /// </remarks>
+        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<IAuthenticationService>();
+                    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");
+            }
+        }
+
         /// <summary>
         /// Load an OAR file into a region..
         /// <summary>