aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/LLLoginService/LLLoginService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/LLLoginService/LLLoginService.cs')
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs494
1 files changed, 494 insertions, 0 deletions
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
new file mode 100644
index 0000000..b0e36f1
--- /dev/null
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -0,0 +1,494 @@
1using System;
2using System.Collections.Generic;
3using System.Net;
4using System.Reflection;
5using System.Text.RegularExpressions;
6
7using log4net;
8using Nini.Config;
9using OpenMetaverse;
10
11using OpenSim.Framework;
12using OpenSim.Framework.Capabilities;
13using OpenSim.Framework.Console;
14using OpenSim.Server.Base;
15using OpenSim.Services.Interfaces;
16using GridRegion = OpenSim.Services.Interfaces.GridRegion;
17
18namespace OpenSim.Services.LLLoginService
19{
20 public class LLLoginService : ILoginService
21 {
22 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
23 private static bool Initialized = false;
24
25 private IUserAccountService m_UserAccountService;
26 private IAuthenticationService m_AuthenticationService;
27 private IInventoryService m_InventoryService;
28 private IGridService m_GridService;
29 private IPresenceService m_PresenceService;
30 private ISimulationService m_LocalSimulationService;
31 private ISimulationService m_RemoteSimulationService;
32 private ILibraryService m_LibraryService;
33 private IAvatarService m_AvatarService;
34
35 private string m_DefaultRegionName;
36 private string m_WelcomeMessage;
37 private bool m_RequireInventory;
38 private int m_MinLoginLevel;
39
40 public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
41 {
42 IConfig serverConfig = config.Configs["LoginService"];
43 if (serverConfig == null)
44 throw new Exception(String.Format("No section LoginService in config file"));
45
46 string accountService = serverConfig.GetString("UserAccountService", String.Empty);
47 string authService = serverConfig.GetString("AuthenticationService", String.Empty);
48 string invService = serverConfig.GetString("InventoryService", String.Empty);
49 string gridService = serverConfig.GetString("GridService", String.Empty);
50 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
51 string libService = serverConfig.GetString("LibraryService", String.Empty);
52 string avatarService = serverConfig.GetString("AvatarService", String.Empty);
53 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
54
55 m_DefaultRegionName = serverConfig.GetString("DefaultRegion", String.Empty);
56 m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
57 m_RequireInventory = serverConfig.GetBoolean("RequireInventory", true);
58
59 // These are required; the others aren't
60 if (accountService == string.Empty || authService == string.Empty)
61 throw new Exception("LoginService is missing service specifications");
62
63 Object[] args = new Object[] { config };
64 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
65 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args);
66 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
67 if (gridService != string.Empty)
68 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
69 if (presenceService != string.Empty)
70 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
71 if (avatarService != string.Empty)
72 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarService, args);
73 if (simulationService != string.Empty)
74 m_RemoteSimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
75 //
76 // deal with the services given as argument
77 //
78 m_LocalSimulationService = simService;
79 if (libraryService != null)
80 {
81 m_log.DebugFormat("[LLOGIN SERVICE]: Using LibraryService given as argument");
82 m_LibraryService = libraryService;
83 }
84 else if (libService != string.Empty)
85 {
86 m_log.DebugFormat("[LLOGIN SERVICE]: Using instantiated LibraryService");
87 m_LibraryService = ServerUtils.LoadPlugin<ILibraryService>(libService, args);
88 }
89
90 if (!Initialized)
91 {
92 Initialized = true;
93 RegisterCommands();
94 }
95
96 m_log.DebugFormat("[LLOGIN SERVICE]: Starting...");
97
98 }
99
100 public LLLoginService(IConfigSource config) : this(config, null, null)
101 {
102 }
103
104 public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, IPEndPoint clientIP)
105 {
106 bool success = false;
107 UUID session = UUID.Random();
108
109 try
110 {
111 //
112 // Get the account and check that it exists
113 //
114 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
115 if (account == null)
116 {
117 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found");
118 return LLFailedLoginResponse.UserProblem;
119 }
120
121 if (account.UserLevel < m_MinLoginLevel)
122 {
123 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel);
124 return LLFailedLoginResponse.LoginBlockedProblem;
125 }
126
127 //
128 // Authenticate this user
129 //
130 if (!passwd.StartsWith("$1$"))
131 passwd = "$1$" + Util.Md5Hash(passwd);
132 passwd = passwd.Remove(0, 3); //remove $1$
133 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30);
134 UUID secureSession = UUID.Zero;
135 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
136 {
137 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: authentication failed");
138 return LLFailedLoginResponse.UserProblem;
139 }
140
141 //
142 // Get the user's inventory
143 //
144 if (m_RequireInventory && m_InventoryService == null)
145 {
146 m_log.WarnFormat("[LLOGIN SERVICE]: Login failed, reason: inventory service not set up");
147 return LLFailedLoginResponse.InventoryProblem;
148 }
149 List<InventoryFolderBase> inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID);
150 if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0)))
151 {
152 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: unable to retrieve user inventory");
153 return LLFailedLoginResponse.InventoryProblem;
154 }
155
156 //
157 // Login the presence
158 //
159 PresenceInfo presence = null;
160 GridRegion home = null;
161 if (m_PresenceService != null)
162 {
163 success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession);
164 if (!success)
165 {
166 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence");
167 return LLFailedLoginResponse.GridProblem;
168 }
169
170 // Get the updated presence info
171 presence = m_PresenceService.GetAgent(session);
172
173 // Get the home region
174 if ((presence.HomeRegionID != UUID.Zero) && m_GridService != null)
175 {
176 home = m_GridService.GetRegionByUUID(account.ScopeID, presence.HomeRegionID);
177 }
178 }
179
180 //
181 // Find the destination region/grid
182 //
183 string where = string.Empty;
184 Vector3 position = Vector3.Zero;
185 Vector3 lookAt = Vector3.Zero;
186 GridRegion destination = FindDestination(account, presence, session, startLocation, out where, out position, out lookAt);
187 if (destination == null)
188 {
189 m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt);
190 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found");
191 return LLFailedLoginResponse.GridProblem;
192 }
193
194 //
195 // Get the avatar
196 //
197 AvatarData avatar = null;
198 if (m_AvatarService != null)
199 {
200 avatar = m_AvatarService.GetAvatar(account.PrincipalID);
201 }
202
203 //
204 // Instantiate/get the simulation interface and launch an agent at the destination
205 //
206 ISimulationService simConnector = null;
207 string reason = string.Empty;
208 uint circuitCode = 0;
209 AgentCircuitData aCircuit = null;
210 Object[] args = new Object[] { destination };
211 // HG standalones have both a localSimulatonDll and a remoteSimulationDll
212 // non-HG standalones have just a localSimulationDll
213 // independent login servers have just a remoteSimulationDll
214 if (!startLocation.Contains("@") && (m_LocalSimulationService != null))
215 simConnector = m_LocalSimulationService;
216 else if (m_RemoteSimulationService != null)
217 simConnector = m_RemoteSimulationService;
218 if (simConnector != null)
219 {
220 circuitCode = (uint)Util.RandomClass.Next(); ;
221 aCircuit = LaunchAgent(simConnector, destination, account, avatar, session, secureSession, circuitCode, position, out reason);
222 }
223 if (aCircuit == null)
224 {
225 // Try the fallback regions
226 List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY);
227 if (fallbacks != null)
228 {
229 foreach (GridRegion r in fallbacks)
230 {
231 aCircuit = LaunchAgent(simConnector, r, account, avatar, session, secureSession, circuitCode, position, out reason);
232 if (aCircuit != null)
233 {
234 where = "safe";
235 destination = r;
236 break;
237 }
238 }
239 }
240
241 if (aCircuit == null)
242 {
243 // we tried...
244 m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt);
245 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason);
246 return LLFailedLoginResponse.AuthorizationProblem;
247 }
248 }
249
250 // TODO: Get Friends list...
251
252 //
253 // Finally, fill out the response and return it
254 //
255 LLLoginResponse response = new LLLoginResponse(account, aCircuit, presence, destination, inventorySkel, m_LibraryService,
256 where, startLocation, position, lookAt, m_WelcomeMessage, home, clientIP);
257
258 return response;
259 }
260 catch (Exception e)
261 {
262 m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2}", firstName, lastName, e.StackTrace);
263 if (m_PresenceService != null)
264 m_PresenceService.LogoutAgent(session, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
265 return LLFailedLoginResponse.InternalError;
266 }
267 }
268
269 private GridRegion FindDestination(UserAccount account, PresenceInfo pinfo, UUID sessionID, string startLocation, out string where, out Vector3 position, out Vector3 lookAt)
270 {
271 m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation);
272
273 where = "home";
274 position = new Vector3(128, 128, 0);
275 lookAt = new Vector3(0, 1, 0);
276
277 if (m_GridService == null)
278 return null;
279
280 if (startLocation.Equals("home"))
281 {
282 // logging into home region
283 if (pinfo == null)
284 return null;
285
286 GridRegion region = null;
287
288 if (pinfo.HomeRegionID.Equals(UUID.Zero))
289 {
290 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
291 if (defaults != null && defaults.Count > 0)
292 {
293 region = defaults[0];
294 where = "safe";
295 }
296 else
297 m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a home set and this grid does not have default locations.",
298 account.FirstName, account.LastName);
299 }
300 else
301 region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.HomeRegionID);
302
303 return region;
304 }
305 else if (startLocation.Equals("last"))
306 {
307 // logging into last visited region
308 where = "last";
309
310 if (pinfo == null)
311 return null;
312
313 GridRegion region = null;
314
315 if (pinfo.RegionID.Equals(UUID.Zero))
316 {
317 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
318 if (defaults != null && defaults.Count > 0)
319 {
320 region = defaults[0];
321 where = "safe";
322 }
323 }
324 else
325 {
326 region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.RegionID);
327 position = pinfo.Position;
328 lookAt = pinfo.LookAt;
329 }
330 return region;
331
332 }
333 else
334 {
335 // free uri form
336 // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34
337 where = "url";
338 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
339 Match uriMatch = reURI.Match(startLocation);
340 if (uriMatch == null)
341 {
342 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, but can't process it", startLocation);
343 return null;
344 }
345 else
346 {
347 position = new Vector3(float.Parse(uriMatch.Groups["x"].Value),
348 float.Parse(uriMatch.Groups["y"].Value),
349 float.Parse(uriMatch.Groups["z"].Value));
350
351 string regionName = uriMatch.Groups["region"].ToString();
352 if (regionName != null)
353 {
354 if (!regionName.Contains("@"))
355 {
356
357 List<GridRegion> regions = m_GridService.GetRegionsByName(account.ScopeID, regionName, 1);
358 if ((regions == null) || (regions != null && regions.Count == 0))
359 {
360 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}. Trying defaults.", startLocation, regionName);
361 regions = m_GridService.GetDefaultRegions(UUID.Zero);
362 if (regions != null && regions.Count > 0)
363 {
364 where = "safe";
365 return regions[0];
366 }
367 else
368 {
369 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation);
370 return null;
371 }
372 }
373 return regions[0];
374 }
375 else
376 {
377 string[] parts = regionName.Split(new char[] { '@' });
378 if (parts.Length < 2)
379 {
380 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}", startLocation, regionName);
381 return null;
382 }
383 // Valid specification of a remote grid
384 regionName = parts[0];
385 string domainLocator = parts[1];
386 parts = domainLocator.Split(new char[] {':'});
387 string domainName = parts[0];
388 uint port = 0;
389 if (parts.Length > 1)
390 UInt32.TryParse(parts[1], out port);
391 GridRegion region = new GridRegion();
392 region.ExternalHostName = domainName;
393 region.HttpPort = port;
394 region.RegionName = regionName;
395 return region;
396 }
397 }
398 else
399 {
400 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
401 if (defaults != null && defaults.Count > 0)
402 {
403 where = "safe";
404 return defaults[0];
405 }
406 else
407 return null;
408 }
409 }
410 //response.LookAt = "[r0,r1,r0]";
411 //// can be: last, home, safe, url
412 //response.StartLocation = "url";
413
414 }
415
416 }
417
418 private AgentCircuitData LaunchAgent(ISimulationService simConnector, GridRegion region, UserAccount account,
419 AvatarData avatar, UUID session, UUID secureSession, uint circuit, Vector3 position, out string reason)
420 {
421 reason = string.Empty;
422 AgentCircuitData aCircuit = new AgentCircuitData();
423
424 aCircuit.AgentID = account.PrincipalID;
425 if (avatar != null)
426 aCircuit.Appearance = avatar.ToAvatarAppearance(account.PrincipalID);
427 else
428 aCircuit.Appearance = new AvatarAppearance(account.PrincipalID);
429
430 //aCircuit.BaseFolder = irrelevant
431 aCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
432 aCircuit.child = false; // the first login agent is root
433 aCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>();
434 aCircuit.circuitcode = circuit;
435 aCircuit.firstname = account.FirstName;
436 //aCircuit.InventoryFolder = irrelevant
437 aCircuit.lastname = account.LastName;
438 aCircuit.SecureSessionID = secureSession;
439 aCircuit.SessionID = session;
440 aCircuit.startpos = position;
441
442 if (simConnector.CreateAgent(region, aCircuit, 0, out reason))
443 return aCircuit;
444
445 return null;
446
447 }
448
449 #region Console Commands
450 private void RegisterCommands()
451 {
452 //MainConsole.Instance.Commands.AddCommand
453 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login level",
454 "login level <level>",
455 "Set the minimum user level to log in", HandleLoginCommand);
456
457 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login reset",
458 "login reset",
459 "Reset the login level to allow all users",
460 HandleLoginCommand);
461
462 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login text",
463 "login text <text>",
464 "Set the text users will see on login", HandleLoginCommand);
465
466 }
467
468 private void HandleLoginCommand(string module, string[] cmd)
469 {
470 string subcommand = cmd[1];
471
472 switch (subcommand)
473 {
474 case "level":
475 // Set the minimum level to allow login
476 // Useful to allow grid update without worrying about users.
477 // or fixing critical issues
478 //
479 if (cmd.Length > 2)
480 Int32.TryParse(cmd[2], out m_MinLoginLevel);
481 break;
482 case "reset":
483 m_MinLoginLevel = 0;
484 break;
485 case "text":
486 if (cmd.Length > 2)
487 m_WelcomeMessage = cmd[2];
488 break;
489 }
490 }
491 }
492
493 #endregion
494}