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.cs639
1 files changed, 639 insertions, 0 deletions
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
new file mode 100644
index 0000000..ba50e3f
--- /dev/null
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -0,0 +1,639 @@
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;
17using OpenSim.Services.Connectors.Hypergrid;
18
19namespace OpenSim.Services.LLLoginService
20{
21 public class LLLoginService : ILoginService
22 {
23 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
24 private static bool Initialized = false;
25
26 private IUserAccountService m_UserAccountService;
27 private IAuthenticationService m_AuthenticationService;
28 private IInventoryService m_InventoryService;
29 private IGridService m_GridService;
30 private IPresenceService m_PresenceService;
31 private ISimulationService m_LocalSimulationService;
32 private ISimulationService m_RemoteSimulationService;
33 private ILibraryService m_LibraryService;
34 private IAvatarService m_AvatarService;
35 private IUserAgentService m_UserAgentService;
36
37 private GatekeeperServiceConnector m_GatekeeperConnector;
38
39 private string m_DefaultRegionName;
40 private string m_WelcomeMessage;
41 private bool m_RequireInventory;
42 private int m_MinLoginLevel;
43 private string m_GatekeeperURL;
44
45 IConfig m_LoginServerConfig;
46
47 public LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)
48 {
49 m_LoginServerConfig = config.Configs["LoginService"];
50 if (m_LoginServerConfig == null)
51 throw new Exception(String.Format("No section LoginService in config file"));
52
53 string accountService = m_LoginServerConfig.GetString("UserAccountService", String.Empty);
54 string agentService = m_LoginServerConfig.GetString("UserAgentService", String.Empty);
55 string authService = m_LoginServerConfig.GetString("AuthenticationService", String.Empty);
56 string invService = m_LoginServerConfig.GetString("InventoryService", String.Empty);
57 string gridService = m_LoginServerConfig.GetString("GridService", String.Empty);
58 string presenceService = m_LoginServerConfig.GetString("PresenceService", String.Empty);
59 string libService = m_LoginServerConfig.GetString("LibraryService", String.Empty);
60 string avatarService = m_LoginServerConfig.GetString("AvatarService", String.Empty);
61 string simulationService = m_LoginServerConfig.GetString("SimulationService", String.Empty);
62
63 m_DefaultRegionName = m_LoginServerConfig.GetString("DefaultRegion", String.Empty);
64 m_WelcomeMessage = m_LoginServerConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
65 m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true);
66 m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty);
67
68 // These are required; the others aren't
69 if (accountService == string.Empty || authService == string.Empty)
70 throw new Exception("LoginService is missing service specifications");
71
72 Object[] args = new Object[] { config };
73 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
74 m_AuthenticationService = ServerUtils.LoadPlugin<IAuthenticationService>(authService, args);
75 m_InventoryService = ServerUtils.LoadPlugin<IInventoryService>(invService, args);
76 if (gridService != string.Empty)
77 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
78 if (presenceService != string.Empty)
79 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
80 if (avatarService != string.Empty)
81 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarService, args);
82 if (simulationService != string.Empty)
83 m_RemoteSimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
84 if (agentService != string.Empty)
85 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(agentService, args);
86
87 //
88 // deal with the services given as argument
89 //
90 m_LocalSimulationService = simService;
91 if (libraryService != null)
92 {
93 m_log.DebugFormat("[LLOGIN SERVICE]: Using LibraryService given as argument");
94 m_LibraryService = libraryService;
95 }
96 else if (libService != string.Empty)
97 {
98 m_log.DebugFormat("[LLOGIN SERVICE]: Using instantiated LibraryService");
99 m_LibraryService = ServerUtils.LoadPlugin<ILibraryService>(libService, args);
100 }
101
102 m_GatekeeperConnector = new GatekeeperServiceConnector();
103
104 if (!Initialized)
105 {
106 Initialized = true;
107 RegisterCommands();
108 }
109
110 m_log.DebugFormat("[LLOGIN SERVICE]: Starting...");
111
112 }
113
114 public LLLoginService(IConfigSource config) : this(config, null, null)
115 {
116 }
117
118 public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, IPEndPoint clientIP)
119 {
120 bool success = false;
121 UUID session = UUID.Random();
122
123 try
124 {
125 //
126 // Get the account and check that it exists
127 //
128 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName);
129 if (account == null)
130 {
131 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: user not found");
132 return LLFailedLoginResponse.UserProblem;
133 }
134
135 if (account.UserLevel < m_MinLoginLevel)
136 {
137 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel);
138 return LLFailedLoginResponse.LoginBlockedProblem;
139 }
140
141 //
142 // Authenticate this user
143 //
144 if (!passwd.StartsWith("$1$"))
145 passwd = "$1$" + Util.Md5Hash(passwd);
146 passwd = passwd.Remove(0, 3); //remove $1$
147 string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30);
148 UUID secureSession = UUID.Zero;
149 if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
150 {
151 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: authentication failed");
152 return LLFailedLoginResponse.UserProblem;
153 }
154
155 //
156 // Get the user's inventory
157 //
158 if (m_RequireInventory && m_InventoryService == null)
159 {
160 m_log.WarnFormat("[LLOGIN SERVICE]: Login failed, reason: inventory service not set up");
161 return LLFailedLoginResponse.InventoryProblem;
162 }
163 List<InventoryFolderBase> inventorySkel = m_InventoryService.GetInventorySkeleton(account.PrincipalID);
164 if (m_RequireInventory && ((inventorySkel == null) || (inventorySkel != null && inventorySkel.Count == 0)))
165 {
166 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: unable to retrieve user inventory");
167 return LLFailedLoginResponse.InventoryProblem;
168 }
169
170 //
171 // Login the presence
172 //
173 PresenceInfo presence = null;
174 GridRegion home = null;
175 if (m_PresenceService != null)
176 {
177 success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession);
178 if (!success)
179 {
180 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: could not login presence");
181 return LLFailedLoginResponse.GridProblem;
182 }
183
184 // Get the updated presence info
185 presence = m_PresenceService.GetAgent(session);
186
187 // Get the home region
188 if ((presence.HomeRegionID != UUID.Zero) && m_GridService != null)
189 {
190 home = m_GridService.GetRegionByUUID(account.ScopeID, presence.HomeRegionID);
191 }
192 }
193
194 //
195 // Find the destination region/grid
196 //
197 string where = string.Empty;
198 Vector3 position = Vector3.Zero;
199 Vector3 lookAt = Vector3.Zero;
200 GridRegion gatekeeper = null;
201 GridRegion destination = FindDestination(account, presence, session, startLocation, out gatekeeper, out where, out position, out lookAt);
202 if (destination == null)
203 {
204 m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt);
205 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: destination not found");
206 return LLFailedLoginResponse.GridProblem;
207 }
208
209 //
210 // Get the avatar
211 //
212 AvatarData avatar = null;
213 if (m_AvatarService != null)
214 {
215 avatar = m_AvatarService.GetAvatar(account.PrincipalID);
216 }
217
218 //
219 // Instantiate/get the simulation interface and launch an agent at the destination
220 //
221 string reason = string.Empty;
222 AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, out where, out reason);
223
224 if (aCircuit == null)
225 {
226 m_PresenceService.LogoutAgent(session, presence.Position, presence.LookAt);
227 m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: {0}", reason);
228 return LLFailedLoginResponse.AuthorizationProblem;
229
230 }
231 // TODO: Get Friends list...
232
233 //
234 // Finally, fill out the response and return it
235 //
236 LLLoginResponse response = new LLLoginResponse(account, aCircuit, presence, destination, inventorySkel, m_LibraryService,
237 where, startLocation, position, lookAt, m_WelcomeMessage, home, clientIP);
238
239 return response;
240 }
241 catch (Exception e)
242 {
243 m_log.WarnFormat("[LLOGIN SERVICE]: Exception processing login for {0} {1}: {2}", firstName, lastName, e.ToString());
244 if (m_PresenceService != null)
245 m_PresenceService.LogoutAgent(session, new Vector3(128, 128, 0), new Vector3(0, 1, 0));
246 return LLFailedLoginResponse.InternalError;
247 }
248 }
249
250 private GridRegion FindDestination(UserAccount account, PresenceInfo pinfo, UUID sessionID, string startLocation, out GridRegion gatekeeper, out string where, out Vector3 position, out Vector3 lookAt)
251 {
252 m_log.DebugFormat("[LLOGIN SERVICE]: FindDestination for start location {0}", startLocation);
253
254 gatekeeper = null;
255 where = "home";
256 position = new Vector3(128, 128, 0);
257 lookAt = new Vector3(0, 1, 0);
258
259 if (m_GridService == null)
260 return null;
261
262 if (startLocation.Equals("home"))
263 {
264 // logging into home region
265 if (pinfo == null)
266 return null;
267
268 GridRegion region = null;
269
270 if (pinfo.HomeRegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.HomeRegionID)) == null)
271 {
272 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
273 if (defaults != null && defaults.Count > 0)
274 {
275 region = defaults[0];
276 where = "safe";
277 }
278 else
279 m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a home set and this grid does not have default locations.",
280 account.FirstName, account.LastName);
281 }
282
283 return region;
284 }
285 else if (startLocation.Equals("last"))
286 {
287 // logging into last visited region
288 where = "last";
289
290 if (pinfo == null)
291 return null;
292
293 GridRegion region = null;
294
295 if (pinfo.RegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.RegionID)) == null)
296 {
297 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
298 if (defaults != null && defaults.Count > 0)
299 {
300 region = defaults[0];
301 where = "safe";
302 }
303 }
304 else
305 {
306 position = pinfo.Position;
307 lookAt = pinfo.LookAt;
308 }
309 return region;
310
311 }
312 else
313 {
314 // free uri form
315 // e.g. New Moon&135&46 New Moon@osgrid.org:8002&153&34
316 where = "url";
317 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
318 Match uriMatch = reURI.Match(startLocation);
319 if (uriMatch == null)
320 {
321 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, but can't process it", startLocation);
322 return null;
323 }
324 else
325 {
326 position = new Vector3(float.Parse(uriMatch.Groups["x"].Value),
327 float.Parse(uriMatch.Groups["y"].Value),
328 float.Parse(uriMatch.Groups["z"].Value));
329
330 string regionName = uriMatch.Groups["region"].ToString();
331 if (regionName != null)
332 {
333 if (!regionName.Contains("@"))
334 {
335
336 List<GridRegion> regions = m_GridService.GetRegionsByName(account.ScopeID, regionName, 1);
337 if ((regions == null) || (regions != null && regions.Count == 0))
338 {
339 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}. Trying defaults.", startLocation, regionName);
340 regions = m_GridService.GetDefaultRegions(UUID.Zero);
341 if (regions != null && regions.Count > 0)
342 {
343 where = "safe";
344 return regions[0];
345 }
346 else
347 {
348 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, Grid does not provide default regions.", startLocation);
349 return null;
350 }
351 }
352 return regions[0];
353 }
354 else
355 {
356 if (m_UserAgentService == null)
357 {
358 m_log.WarnFormat("[LLLOGIN SERVICE]: This llogin service is not running a user agent service, as such it can't lauch agents at foreign grids");
359 return null;
360 }
361 string[] parts = regionName.Split(new char[] { '@' });
362 if (parts.Length < 2)
363 {
364 m_log.InfoFormat("[LLLOGIN SERVICE]: Got Custom Login URI {0}, can't locate region {1}", startLocation, regionName);
365 return null;
366 }
367 // Valid specification of a remote grid
368 regionName = parts[0];
369 string domainLocator = parts[1];
370 parts = domainLocator.Split(new char[] {':'});
371 string domainName = parts[0];
372 uint port = 0;
373 if (parts.Length > 1)
374 UInt32.TryParse(parts[1], out port);
375 GridRegion region = FindForeignRegion(domainName, port, regionName, out gatekeeper);
376 return region;
377 }
378 }
379 else
380 {
381 List<GridRegion> defaults = m_GridService.GetDefaultRegions(account.ScopeID);
382 if (defaults != null && defaults.Count > 0)
383 {
384 where = "safe";
385 return defaults[0];
386 }
387 else
388 return null;
389 }
390 }
391 //response.LookAt = "[r0,r1,r0]";
392 //// can be: last, home, safe, url
393 //response.StartLocation = "url";
394
395 }
396
397 }
398
399 private GridRegion FindForeignRegion(string domainName, uint port, string regionName, out GridRegion gatekeeper)
400 {
401 gatekeeper = new GridRegion();
402 gatekeeper.ExternalHostName = domainName;
403 gatekeeper.HttpPort = port;
404 gatekeeper.RegionName = regionName;
405 gatekeeper.InternalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), 0);
406
407 UUID regionID;
408 ulong handle;
409 string imageURL = string.Empty, reason = string.Empty;
410 if (m_GatekeeperConnector.LinkRegion(gatekeeper, out regionID, out handle, out domainName, out imageURL, out reason))
411 {
412 GridRegion destination = m_GatekeeperConnector.GetHyperlinkRegion(gatekeeper, regionID);
413 return destination;
414 }
415
416 return null;
417 }
418
419 private string hostName = string.Empty;
420 private int port = 0;
421
422 private void SetHostAndPort(string url)
423 {
424 try
425 {
426 Uri uri = new Uri(url);
427 hostName = uri.Host;
428 port = uri.Port;
429 }
430 catch
431 {
432 m_log.WarnFormat("[LLLogin SERVICE]: Unable to parse GatekeeperURL {0}", url);
433 }
434 }
435
436 private AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar,
437 UUID session, UUID secureSession, Vector3 position, string currentWhere, out string where, out string reason)
438 {
439 where = currentWhere;
440 ISimulationService simConnector = null;
441 reason = string.Empty;
442 uint circuitCode = 0;
443 AgentCircuitData aCircuit = null;
444
445 if (m_UserAgentService == null)
446 {
447 // HG standalones have both a localSimulatonDll and a remoteSimulationDll
448 // non-HG standalones have just a localSimulationDll
449 // independent login servers have just a remoteSimulationDll
450 if (m_LocalSimulationService != null)
451 simConnector = m_LocalSimulationService;
452 else if (m_RemoteSimulationService != null)
453 simConnector = m_RemoteSimulationService;
454 }
455 else // User Agent Service is on
456 {
457 if (gatekeeper == null) // login to local grid
458 {
459 if (hostName == string.Empty)
460 SetHostAndPort(m_GatekeeperURL);
461
462 gatekeeper = new GridRegion(destination);
463 gatekeeper.ExternalHostName = hostName;
464 gatekeeper.HttpPort = (uint)port;
465
466 }
467 else // login to foreign grid
468 {
469 }
470 }
471
472 bool success = false;
473
474 if (m_UserAgentService == null && simConnector != null)
475 {
476 circuitCode = (uint)Util.RandomClass.Next(); ;
477 aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position);
478 success = LaunchAgentDirectly(simConnector, destination, aCircuit, out reason);
479 if (!success && m_GridService != null)
480 {
481 // Try the fallback regions
482 List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY);
483 if (fallbacks != null)
484 {
485 foreach (GridRegion r in fallbacks)
486 {
487 success = LaunchAgentDirectly(simConnector, r, aCircuit, out reason);
488 if (success)
489 {
490 where = "safe";
491 destination = r;
492 break;
493 }
494 }
495 }
496 }
497 }
498
499 if (m_UserAgentService != null)
500 {
501 circuitCode = (uint)Util.RandomClass.Next(); ;
502 aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position);
503 success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, out reason);
504 if (!success && m_GridService != null)
505 {
506 // Try the fallback regions
507 List<GridRegion> fallbacks = m_GridService.GetFallbackRegions(account.ScopeID, destination.RegionLocX, destination.RegionLocY);
508 if (fallbacks != null)
509 {
510 foreach (GridRegion r in fallbacks)
511 {
512 success = LaunchAgentIndirectly(gatekeeper, r, aCircuit, out reason);
513 if (success)
514 {
515 where = "safe";
516 destination = r;
517 break;
518 }
519 }
520 }
521 }
522 }
523
524 if (success)
525 return aCircuit;
526 else
527 return null;
528 }
529
530 private AgentCircuitData MakeAgent(GridRegion region, UserAccount account,
531 AvatarData avatar, UUID session, UUID secureSession, uint circuit, Vector3 position)
532 {
533 AgentCircuitData aCircuit = new AgentCircuitData();
534
535 aCircuit.AgentID = account.PrincipalID;
536 if (avatar != null)
537 aCircuit.Appearance = avatar.ToAvatarAppearance(account.PrincipalID);
538 else
539 aCircuit.Appearance = new AvatarAppearance(account.PrincipalID);
540
541 //aCircuit.BaseFolder = irrelevant
542 aCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
543 aCircuit.child = false; // the first login agent is root
544 aCircuit.ChildrenCapSeeds = new Dictionary<ulong, string>();
545 aCircuit.circuitcode = circuit;
546 aCircuit.firstname = account.FirstName;
547 //aCircuit.InventoryFolder = irrelevant
548 aCircuit.lastname = account.LastName;
549 aCircuit.SecureSessionID = secureSession;
550 aCircuit.SessionID = session;
551 aCircuit.startpos = position;
552 SetServiceURLs(aCircuit, account);
553
554 return aCircuit;
555
556 //m_UserAgentService.LoginAgentToGrid(aCircuit, GatekeeperServiceConnector, region, out reason);
557 //if (simConnector.CreateAgent(region, aCircuit, 0, out reason))
558 // return aCircuit;
559
560 //return null;
561
562 }
563
564 private void SetServiceURLs(AgentCircuitData aCircuit, UserAccount account)
565 {
566 aCircuit.ServiceURLs = new Dictionary<string, object>();
567 if (account.ServiceURLs == null)
568 return;
569
570 foreach (KeyValuePair<string, object> kvp in account.ServiceURLs)
571 {
572 if (kvp.Value == null || (kvp.Value != null && kvp.Value.ToString() == string.Empty))
573 {
574 aCircuit.ServiceURLs[kvp.Key] = m_LoginServerConfig.GetString(kvp.Key, string.Empty);
575 }
576 else
577 {
578 aCircuit.ServiceURLs[kvp.Key] = kvp.Value;
579 }
580 }
581 }
582
583 private bool LaunchAgentDirectly(ISimulationService simConnector, GridRegion region, AgentCircuitData aCircuit, out string reason)
584 {
585 return simConnector.CreateAgent(region, aCircuit, (int)Constants.TeleportFlags.ViaLogin, out reason);
586 }
587
588 private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, out string reason)
589 {
590 m_log.Debug("XXX Launching agent at {0}" + destination.RegionName);
591 return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, out reason);
592 }
593
594 #region Console Commands
595 private void RegisterCommands()
596 {
597 //MainConsole.Instance.Commands.AddCommand
598 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login level",
599 "login level <level>",
600 "Set the minimum user level to log in", HandleLoginCommand);
601
602 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login reset",
603 "login reset",
604 "Reset the login level to allow all users",
605 HandleLoginCommand);
606
607 MainConsole.Instance.Commands.AddCommand("loginservice", false, "login text",
608 "login text <text>",
609 "Set the text users will see on login", HandleLoginCommand);
610
611 }
612
613 private void HandleLoginCommand(string module, string[] cmd)
614 {
615 string subcommand = cmd[1];
616
617 switch (subcommand)
618 {
619 case "level":
620 // Set the minimum level to allow login
621 // Useful to allow grid update without worrying about users.
622 // or fixing critical issues
623 //
624 if (cmd.Length > 2)
625 Int32.TryParse(cmd[2], out m_MinLoginLevel);
626 break;
627 case "reset":
628 m_MinLoginLevel = 0;
629 break;
630 case "text":
631 if (cmd.Length > 2)
632 m_WelcomeMessage = cmd[2];
633 break;
634 }
635 }
636 }
637
638 #endregion
639}