aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim.RegionServer/UserServer/LoginServer.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim.RegionServer/UserServer/LoginServer.cs414
1 files changed, 414 insertions, 0 deletions
diff --git a/OpenSim.RegionServer/UserServer/LoginServer.cs b/OpenSim.RegionServer/UserServer/LoginServer.cs
new file mode 100644
index 0000000..86b098a
--- /dev/null
+++ b/OpenSim.RegionServer/UserServer/LoginServer.cs
@@ -0,0 +1,414 @@
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
28using Nwc.XmlRpc;
29using System;
30using System.IO;
31using System.Net;
32using System.Net.Sockets;
33using System.Text;
34using System.Text.RegularExpressions;
35using System.Threading;
36using System.Collections;
37using System.Security.Cryptography;
38using System.Xml;
39using libsecondlife;
40using OpenSim;
41using OpenSim.Framework.Interfaces;
42using OpenSim.Framework.Grid;
43using OpenSim.Framework.Inventory;
44using OpenSim.Framework.User;
45using OpenSim.Framework.Utilities;
46
47namespace OpenSim.UserServer
48{
49
50 /// <summary>
51 /// When running in local (default) mode , handles client logins.
52 /// </summary>
53 public class LoginServer : LoginService , IUserServer
54 {
55 private IGridServer _gridServer;
56 private ushort _loginPort = 8080;
57 public IPAddress clientAddress = IPAddress.Loopback;
58 public IPAddress remoteAddress = IPAddress.Any;
59 private Socket loginServer;
60 private int NumClients;
61 private string _defaultResponse;
62 private bool userAccounts = false;
63 private string _mpasswd;
64 private bool _needPasswd = false;
65 private LocalUserProfileManager userManager;
66
67 public LoginServer(IGridServer gridServer)
68 {
69 _gridServer = gridServer;
70 }
71
72 // InitializeLogin: initialize the login
73 private void InitializeLogin()
74 {
75 this._needPasswd = false;
76 //read in default response string
77 StreamReader SR;
78 string lines;
79 SR = File.OpenText("new-login.dat");
80
81 //lines=SR.ReadLine();
82
83 while (!SR.EndOfStream)
84 {
85 lines = SR.ReadLine();
86 _defaultResponse += lines;
87 //lines = SR.ReadLine();
88 }
89 SR.Close();
90 this._mpasswd = EncodePassword("testpass");
91
92 userManager = new LocalUserProfileManager(this._gridServer);
93 userManager.InitUserProfiles();
94 userManager.SetKeys("", "", "", "Welcome to OpenSim");
95
96 loginServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
97 loginServer.Bind(new IPEndPoint(remoteAddress, _loginPort));
98 loginServer.Listen(1);
99 }
100
101 public void Startup()
102 {
103 this.InitializeLogin();
104 Thread runLoginProxy = new Thread(new ThreadStart(RunLogin));
105 runLoginProxy.IsBackground = true;
106 runLoginProxy.Start();
107 }
108
109 private void RunLogin()
110 {
111 Console.WriteLine("Starting Login Server");
112 try
113 {
114 for (; ; )
115 {
116 Socket client = loginServer.Accept();
117 IPEndPoint clientEndPoint = (IPEndPoint)client.RemoteEndPoint;
118
119
120 NetworkStream networkStream = new NetworkStream(client);
121 StreamReader networkReader = new StreamReader(networkStream);
122 StreamWriter networkWriter = new StreamWriter(networkStream);
123
124 try
125 {
126 LoginRequest(networkReader, networkWriter);
127 }
128 catch (Exception e)
129 {
130 Console.WriteLine(e.Message);
131 }
132
133 networkWriter.Close();
134 networkReader.Close();
135 networkStream.Close();
136
137 client.Close();
138
139 // send any packets queued for injection
140
141 }
142 }
143 catch (Exception e)
144 {
145 Console.WriteLine(e.Message);
146 Console.WriteLine(e.StackTrace);
147 }
148 }
149
150 // ProxyLogin: proxy a login request
151 private void LoginRequest(StreamReader reader, StreamWriter writer)
152 {
153 lock (this)
154 {
155 string line;
156 int contentLength = 0;
157 // read HTTP header
158 do
159 {
160 // read one line of the header
161 line = reader.ReadLine();
162
163 // check for premature EOF
164 if (line == null)
165 throw new Exception("EOF in client HTTP header");
166
167 // look for Content-Length
168 Match match = (new Regex(@"Content-Length: (\d+)$")).Match(line);
169 if (match.Success)
170 contentLength = Convert.ToInt32(match.Groups[1].Captures[0].ToString());
171 } while (line != "");
172
173 // read the HTTP body into a buffer
174 char[] content = new char[contentLength];
175 reader.Read(content, 0, contentLength);
176
177 if (this.userAccounts)
178 {
179 //ask the UserProfile Manager to process the request
180 string reply = this.userManager.ParseXMLRPC(new String(content));
181 // forward the XML-RPC response to the client
182 writer.WriteLine("HTTP/1.0 200 OK");
183 writer.WriteLine("Content-type: text/xml");
184 writer.WriteLine();
185 writer.WriteLine(reply);
186 }
187 else
188 {
189 //handle ourselves
190 XmlRpcRequest request = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(new String(content));
191 if (request.MethodName == "login_to_simulator")
192 {
193 this.ProcessXmlRequest(request, writer);
194 }
195 else
196 {
197 XmlRpcResponse PresenceErrorResp = new XmlRpcResponse();
198 Hashtable PresenceErrorRespData = new Hashtable();
199 PresenceErrorRespData["reason"] = "XmlRequest"; ;
200 PresenceErrorRespData["message"] = "Unknown Rpc request";
201 PresenceErrorRespData["login"] = "false";
202 PresenceErrorResp.Value = PresenceErrorRespData;
203 string reply = Regex.Replace(XmlRpcResponseSerializer.Singleton.Serialize(PresenceErrorResp), " encoding=\"utf-16\"", "");
204 writer.WriteLine("HTTP/1.0 200 OK");
205 writer.WriteLine("Content-type: text/xml");
206 writer.WriteLine();
207 writer.WriteLine(reply);
208 }
209 }
210 }
211 }
212
213 public bool ProcessXmlRequest(XmlRpcRequest request, StreamWriter writer)
214 {
215 Hashtable requestData = (Hashtable)request.Params[0];
216 string first;
217 string last;
218 string passwd;
219 LLUUID Agent;
220 LLUUID Session;
221
222 //get login name
223 if (requestData.Contains("first"))
224 {
225 first = (string)requestData["first"];
226 }
227 else
228 {
229 first = "test";
230 }
231
232 if (requestData.Contains("last"))
233 {
234 last = (string)requestData["last"];
235 }
236 else
237 {
238 last = "User" + NumClients.ToString();
239 }
240
241 if (requestData.Contains("passwd"))
242 {
243 passwd = (string)requestData["passwd"];
244 }
245 else
246 {
247 passwd = "notfound";
248 }
249
250 if (!Authenticate(first, last, passwd))
251 {
252 XmlRpcResponse PresenceErrorResp = new XmlRpcResponse();
253 Hashtable PresenceErrorRespData = new Hashtable();
254 PresenceErrorRespData["reason"] = "key"; ;
255 PresenceErrorRespData["message"] = "You have entered an invalid name/password combination. Check Caps/lock.";
256 PresenceErrorRespData["login"] = "false";
257 PresenceErrorResp.Value = PresenceErrorRespData;
258 string reply = Regex.Replace(XmlRpcResponseSerializer.Singleton.Serialize(PresenceErrorResp), " encoding=\"utf-16\"", "");
259 writer.WriteLine("HTTP/1.0 200 OK");
260 writer.WriteLine("Content-type: text/xml");
261 writer.WriteLine();
262 writer.WriteLine(reply);
263 return false;
264 }
265
266 NumClients++;
267
268 //create a agent and session LLUUID
269 Agent = GetAgentId(first, last);
270 int SessionRand = Util.RandomClass.Next(1, 999);
271 Session = new LLUUID("aaaabbbb-0200-" + SessionRand.ToString("0000") + "-8664-58f53e442797");
272 LLUUID secureSess = LLUUID.Random();
273 //create some login info
274 Hashtable LoginFlagsHash = new Hashtable();
275 LoginFlagsHash["daylight_savings"] = "N";
276 LoginFlagsHash["stipend_since_login"] = "N";
277 LoginFlagsHash["gendered"] = "Y";
278 LoginFlagsHash["ever_logged_in"] = "Y";
279 ArrayList LoginFlags = new ArrayList();
280 LoginFlags.Add(LoginFlagsHash);
281
282 Hashtable GlobalT = new Hashtable();
283 GlobalT["sun_texture_id"] = "cce0f112-878f-4586-a2e2-a8f104bba271";
284 GlobalT["cloud_texture_id"] = "fc4b9f0b-d008-45c6-96a4-01dd947ac621";
285 GlobalT["moon_texture_id"] = "fc4b9f0b-d008-45c6-96a4-01dd947ac621";
286 ArrayList GlobalTextures = new ArrayList();
287 GlobalTextures.Add(GlobalT);
288
289 XmlRpcResponse response = (XmlRpcResponse)(new XmlRpcResponseDeserializer()).Deserialize(this._defaultResponse);
290 Hashtable responseData = (Hashtable)response.Value;
291
292 responseData["sim_port"] = OpenSimRoot.Instance.Cfg.IPListenPort;
293 responseData["sim_ip"] = OpenSimRoot.Instance.Cfg.IPListenAddr;
294 responseData["agent_id"] = Agent.ToStringHyphenated();
295 responseData["session_id"] = Session.ToStringHyphenated();
296 responseData["secure_session_id"]= secureSess.ToStringHyphenated();
297 responseData["circuit_code"] = (Int32)(Util.RandomClass.Next());
298 responseData["seconds_since_epoch"] = (Int32)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
299 responseData["login-flags"] = LoginFlags;
300 responseData["global-textures"] = GlobalTextures;
301
302 //inventory
303 ArrayList InventoryList = (ArrayList)responseData["inventory-skeleton"];
304 Hashtable Inventory1 = (Hashtable)InventoryList[0];
305 Hashtable Inventory2 = (Hashtable)InventoryList[1];
306 LLUUID BaseFolderID = LLUUID.Random();
307 LLUUID InventoryFolderID = LLUUID.Random();
308 Inventory2["name"] = "Base";
309 Inventory2["folder_id"] = BaseFolderID.ToStringHyphenated();
310 Inventory2["type_default"] = 0;
311 Inventory1["folder_id"] = InventoryFolderID.ToStringHyphenated();
312
313 ArrayList InventoryRoot = (ArrayList)responseData["inventory-root"];
314 Hashtable Inventoryroot = (Hashtable)InventoryRoot[0];
315 Inventoryroot["folder_id"] = InventoryFolderID.ToStringHyphenated();
316
317 CustomiseLoginResponse(responseData, first, last);
318
319 Login _login = new Login();
320 //copy data to login object
321 _login.First = first;
322 _login.Last = last;
323 _login.Agent = Agent;
324 _login.Session = Session;
325 _login.SecureSession = secureSess;
326 _login.BaseFolder = BaseFolderID;
327 _login.InventoryFolder = InventoryFolderID;
328
329 //working on local computer if so lets add to the gridserver's list of sessions?
330 if (OpenSimRoot.Instance.GridServers.GridServer.GetName() == "Local")
331 {
332 ((LocalGridBase)this._gridServer).AddNewSession(_login);
333 }
334
335 // forward the XML-RPC response to the client
336 writer.WriteLine("HTTP/1.0 200 OK");
337 writer.WriteLine("Content-type: text/xml");
338 writer.WriteLine();
339
340 XmlTextWriter responseWriter = new XmlTextWriter(writer);
341 XmlRpcResponseSerializer.Singleton.Serialize(responseWriter, response);
342 responseWriter.Close();
343
344 return true;
345 }
346
347 protected virtual void CustomiseLoginResponse(Hashtable responseData, string first, string last)
348 {
349 }
350
351 protected virtual LLUUID GetAgentId(string firstName, string lastName)
352 {
353 LLUUID Agent;
354 int AgentRand = Util.RandomClass.Next(1, 9999);
355 Agent = new LLUUID("99998888-0100-" + AgentRand.ToString("0000") + "-8ec1-0b1d5cd6aead");
356 return Agent;
357 }
358
359 protected virtual bool Authenticate(string first, string last, string passwd)
360 {
361 if (this._needPasswd)
362 {
363 //every user needs the password to login
364 string encodedPass = passwd.Remove(0, 3); //remove $1$
365 if (encodedPass == this._mpasswd)
366 {
367 return true;
368 }
369 else
370 {
371 return false;
372 }
373 }
374 else
375 {
376 //do not need password to login
377 return true;
378 }
379 }
380
381 private static string EncodePassword(string passwd)
382 {
383 Byte[] originalBytes;
384 Byte[] encodedBytes;
385 MD5 md5;
386
387 md5 = new MD5CryptoServiceProvider();
388 originalBytes = ASCIIEncoding.Default.GetBytes(passwd);
389 encodedBytes = md5.ComputeHash(originalBytes);
390
391 return Regex.Replace(BitConverter.ToString(encodedBytes), "-", "").ToLower();
392 }
393
394 //IUserServer implementation
395 public AgentInventory RequestAgentsInventory(LLUUID agentID)
396 {
397 AgentInventory aInventory = null;
398 if (this.userAccounts)
399 {
400 aInventory = this.userManager.GetUsersInventory(agentID);
401 }
402
403 return aInventory;
404 }
405
406 public void SetServerInfo(string ServerUrl, string SendKey, string RecvKey)
407 {
408
409 }
410
411 }
412
413
414}