LoginServer.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) OpenSim project, http://sim.opensecondlife.org/
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the <organization> nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
  16. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. using Nwc.XmlRpc;
  28. using System;
  29. using System.IO;
  30. using System.Net;
  31. using System.Net.Sockets;
  32. using System.Text;
  33. using System.Text.RegularExpressions;
  34. using System.Threading;
  35. using System.Collections;
  36. using System.Xml;
  37. using libsecondlife;
  38. namespace OpenSim
  39. {
  40. /// <summary>
  41. /// When running in local (default) mode , handles client logins.
  42. /// </summary>
  43. public class LoginServer
  44. {
  45. public LoginServer(IGridServer gridServer)
  46. {
  47. _gridServer = gridServer;
  48. }
  49. private Logon _login;
  50. private IGridServer _gridServer;
  51. private ushort _loginPort = Globals.Instance.LoginServerPort;
  52. public IPAddress clientAddress = IPAddress.Loopback;
  53. public IPAddress remoteAddress = IPAddress.Any;
  54. private Socket loginServer;
  55. private Random RandomClass = new Random();
  56. private int NumClients;
  57. private string _defaultResponse;
  58. private string _mpasswd;
  59. private bool _needPasswd=false;
  60. // InitializeLoginProxy: initialize the login proxy
  61. private void InitializeLoginProxy() {
  62. loginServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  63. loginServer.Bind(new IPEndPoint(remoteAddress, _loginPort));
  64. loginServer.Listen(1);
  65. this._needPasswd=Globals.Instance.NeedPasswd;
  66. //read in default response string
  67. StreamReader SR;
  68. string lines;
  69. SR=File.OpenText("new-login.dat");
  70. //lines=SR.ReadLine();
  71. while(!SR.EndOfStream)
  72. {
  73. lines = SR.ReadLine();
  74. _defaultResponse += lines;
  75. //lines = SR.ReadLine();
  76. }
  77. SR.Close();
  78. this._mpasswd = Utility.EncodePassword(Globals.Instance.Password);
  79. }
  80. public void Startup()
  81. {
  82. this.InitializeLoginProxy();
  83. Thread runLoginProxy = new Thread(new ThreadStart(RunLoginProxy));
  84. runLoginProxy.IsBackground = true;
  85. runLoginProxy.Start();
  86. }
  87. private void RunLoginProxy()
  88. {
  89. Console.WriteLine("Starting Login Server");
  90. try
  91. {
  92. for (;;)
  93. {
  94. Socket client = loginServer.Accept();
  95. IPEndPoint clientEndPoint = (IPEndPoint)client.RemoteEndPoint;
  96. NetworkStream networkStream = new NetworkStream(client);
  97. StreamReader networkReader = new StreamReader(networkStream);
  98. StreamWriter networkWriter = new StreamWriter(networkStream);
  99. try
  100. {
  101. ProxyLogin(networkReader, networkWriter);
  102. }
  103. catch (Exception e)
  104. {
  105. Console.WriteLine(e.Message);
  106. }
  107. networkWriter.Close();
  108. networkReader.Close();
  109. networkStream.Close();
  110. client.Close();
  111. // send any packets queued for injection
  112. }
  113. }
  114. catch (Exception e)
  115. {
  116. Console.WriteLine(e.Message);
  117. Console.WriteLine(e.StackTrace);
  118. }
  119. }
  120. // ProxyLogin: proxy a login request
  121. private void ProxyLogin(StreamReader reader, StreamWriter writer)
  122. {
  123. lock(this)
  124. {
  125. string line;
  126. int contentLength = 0;
  127. // read HTTP header
  128. do
  129. {
  130. // read one line of the header
  131. line = reader.ReadLine();
  132. // check for premature EOF
  133. if (line == null)
  134. throw new Exception("EOF in client HTTP header");
  135. // look for Content-Length
  136. Match match = (new Regex(@"Content-Length: (\d+)$")).Match(line);
  137. if (match.Success)
  138. contentLength = Convert.ToInt32(match.Groups[1].Captures[0].ToString());
  139. } while (line != "");
  140. // read the HTTP body into a buffer
  141. char[] content = new char[contentLength];
  142. reader.Read(content, 0, contentLength);
  143. XmlRpcRequest request = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(new String(content));
  144. if(request.MethodName == "login_to_simulator")
  145. {
  146. Hashtable requestData = (Hashtable)request.Params[0];
  147. string first;
  148. string last;
  149. string passwd;
  150. LLUUID Agent;
  151. LLUUID Session;
  152. //get login name
  153. if(requestData.Contains("first"))
  154. {
  155. first = (string)requestData["first"];
  156. }
  157. else
  158. {
  159. first = "test";
  160. }
  161. if(requestData.Contains("last"))
  162. {
  163. last = (string)requestData["last"];
  164. }
  165. else
  166. {
  167. last = "User"+NumClients.ToString();
  168. }
  169. if(requestData.Contains("passwd"))
  170. {
  171. passwd = (string)requestData["passwd"];
  172. }
  173. else
  174. {
  175. passwd = "notfound";
  176. }
  177. if( !Authenticate(first, last, passwd))
  178. {
  179. // Fail miserably
  180. writer.WriteLine("HTTP/1.0 403 Authentication Forbidden");
  181. writer.WriteLine();
  182. return;
  183. }
  184. NumClients++;
  185. //create a agent and session LLUUID
  186. Agent = GetAgentId( first, last );
  187. int SessionRand = this.RandomClass.Next(1,999);
  188. Session = new LLUUID("aaaabbbb-0200-"+SessionRand.ToString("0000")+"-8664-58f53e442797");
  189. XmlRpcResponse response =(XmlRpcResponse)(new XmlRpcResponseDeserializer()).Deserialize(this._defaultResponse);
  190. Hashtable responseData = (Hashtable)response.Value;
  191. responseData["sim_port"] = Globals.Instance.SimPort;
  192. responseData["sim_ip"] = Globals.Instance.SimIPAddress;
  193. responseData["agent_id"] = Agent.ToStringHyphenated();
  194. responseData["session_id"] = Session.ToStringHyphenated();
  195. ArrayList InventoryList = (ArrayList) responseData["inventory-skeleton"];
  196. Hashtable Inventory1 = (Hashtable)InventoryList[0];
  197. Hashtable Inventory2 = (Hashtable)InventoryList[1];
  198. LLUUID BaseFolderID = LLUUID.Random();
  199. LLUUID InventoryFolderID = LLUUID.Random();
  200. Inventory2["name"] = "Base";
  201. Inventory2["folder_id"] = BaseFolderID.ToStringHyphenated();
  202. Inventory2["type_default"] =6;
  203. Inventory1["folder_id"] = InventoryFolderID.ToStringHyphenated();
  204. ArrayList InventoryRoot = (ArrayList) responseData["inventory-root"];
  205. Hashtable Inventoryroot = (Hashtable)InventoryRoot[0];
  206. Inventoryroot["folder_id"] = InventoryFolderID.ToStringHyphenated();
  207. CustomiseLoginResponse( responseData, first, last );
  208. this._login = new Logon();
  209. //copy data to login object
  210. _login.First = first;
  211. _login.Last = last;
  212. _login.Agent = Agent;
  213. _login.Session = Session;
  214. _login.BaseFolder = BaseFolderID;
  215. _login.InventoryFolder = InventoryFolderID;
  216. //working on local computer so lets add to the gridserver's list of sessions
  217. ((GridServer)this._gridServer).AddNewSession(_login);
  218. // forward the XML-RPC response to the client
  219. writer.WriteLine("HTTP/1.0 200 OK");
  220. writer.WriteLine("Content-type: text/xml");
  221. writer.WriteLine();
  222. XmlTextWriter responseWriter = new XmlTextWriter(writer);
  223. XmlRpcResponseSerializer.Singleton.Serialize(responseWriter, response);
  224. responseWriter.Close();
  225. }
  226. else
  227. {
  228. writer.WriteLine("HTTP/1.0 403 Authentication Forbidden");
  229. writer.WriteLine();
  230. }
  231. }
  232. }
  233. protected virtual void CustomiseLoginResponse( Hashtable responseData, string first, string last )
  234. {
  235. }
  236. protected virtual LLUUID GetAgentId(string firstName, string lastName)
  237. {
  238. LLUUID Agent;
  239. int AgentRand = this.RandomClass.Next(1,9999);
  240. Agent = new LLUUID("99998888-0100-"+AgentRand.ToString("0000")+"-8ec1-0b1d5cd6aead");
  241. return Agent;
  242. }
  243. protected virtual bool Authenticate(string first, string last, string passwd)
  244. {
  245. if(this._needPasswd)
  246. {
  247. //every user needs the password to login
  248. string encodedPass = passwd.Remove(0,3); //remove $1$
  249. if(encodedPass == this._mpasswd)
  250. {
  251. return true;
  252. }
  253. else
  254. {
  255. return false;
  256. }
  257. }
  258. else
  259. {
  260. //do not need password to login
  261. return true;
  262. }
  263. }
  264. }
  265. public class Logon
  266. {
  267. public string First = "Test";
  268. public string Last = "User";
  269. public LLUUID Agent;
  270. public LLUUID Session;
  271. public LLUUID InventoryFolder;
  272. public LLUUID BaseFolder;
  273. public Logon()
  274. {
  275. }
  276. }
  277. }