diff options
Diffstat (limited to 'OpenSim/Services/HypergridService/GatekeeperService.cs')
-rw-r--r-- | OpenSim/Services/HypergridService/GatekeeperService.cs | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs new file mode 100644 index 0000000..44b26d5 --- /dev/null +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs | |||
@@ -0,0 +1,559 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Net; | ||
31 | using System.Reflection; | ||
32 | using System.Text.RegularExpressions; | ||
33 | |||
34 | using OpenSim.Framework; | ||
35 | using OpenSim.Services.Interfaces; | ||
36 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | ||
37 | using OpenSim.Server.Base; | ||
38 | using OpenSim.Services.Connectors.Hypergrid; | ||
39 | |||
40 | using OpenMetaverse; | ||
41 | |||
42 | using Nini.Config; | ||
43 | using log4net; | ||
44 | |||
45 | namespace OpenSim.Services.HypergridService | ||
46 | { | ||
47 | public class GatekeeperService : IGatekeeperService | ||
48 | { | ||
49 | private static readonly ILog m_log = | ||
50 | LogManager.GetLogger( | ||
51 | MethodBase.GetCurrentMethod().DeclaringType); | ||
52 | |||
53 | private static bool m_Initialized = false; | ||
54 | |||
55 | private static IGridService m_GridService; | ||
56 | private static IPresenceService m_PresenceService; | ||
57 | private static IUserAccountService m_UserAccountService; | ||
58 | private static IUserAgentService m_UserAgentService; | ||
59 | private static ISimulationService m_SimulationService; | ||
60 | private static IGridUserService m_GridUserService; | ||
61 | private static IBansService m_BansService; | ||
62 | |||
63 | private static string m_AllowedClients = string.Empty; | ||
64 | private static string m_DeniedClients = string.Empty; | ||
65 | private static bool m_ForeignAgentsAllowed = true; | ||
66 | private static List<string> m_ForeignsAllowedExceptions = new List<string>(); | ||
67 | private static List<string> m_ForeignsDisallowedExceptions = new List<string>(); | ||
68 | |||
69 | private static UUID m_ScopeID; | ||
70 | private static bool m_AllowTeleportsToAnyRegion; | ||
71 | private static string m_ExternalName; | ||
72 | private static Uri m_Uri; | ||
73 | private static GridRegion m_DefaultGatewayRegion; | ||
74 | |||
75 | public GatekeeperService(IConfigSource config, ISimulationService simService) | ||
76 | { | ||
77 | if (!m_Initialized) | ||
78 | { | ||
79 | m_Initialized = true; | ||
80 | |||
81 | IConfig serverConfig = config.Configs["GatekeeperService"]; | ||
82 | if (serverConfig == null) | ||
83 | throw new Exception(String.Format("No section GatekeeperService in config file")); | ||
84 | |||
85 | string accountService = serverConfig.GetString("UserAccountService", String.Empty); | ||
86 | string homeUsersService = serverConfig.GetString("UserAgentService", string.Empty); | ||
87 | string gridService = serverConfig.GetString("GridService", String.Empty); | ||
88 | string presenceService = serverConfig.GetString("PresenceService", String.Empty); | ||
89 | string simulationService = serverConfig.GetString("SimulationService", String.Empty); | ||
90 | string gridUserService = serverConfig.GetString("GridUserService", String.Empty); | ||
91 | string bansService = serverConfig.GetString("BansService", String.Empty); | ||
92 | |||
93 | // These are mandatory, the others aren't | ||
94 | if (gridService == string.Empty || presenceService == string.Empty) | ||
95 | throw new Exception("Incomplete specifications, Gatekeeper Service cannot function."); | ||
96 | |||
97 | string scope = serverConfig.GetString("ScopeID", UUID.Zero.ToString()); | ||
98 | UUID.TryParse(scope, out m_ScopeID); | ||
99 | //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); | ||
100 | m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true); | ||
101 | m_ExternalName = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", | ||
102 | new string[] { "Startup", "Hypergrid", "GatekeeperService" }, String.Empty); | ||
103 | m_ExternalName = serverConfig.GetString("ExternalName", m_ExternalName); | ||
104 | if (m_ExternalName != string.Empty && !m_ExternalName.EndsWith("/")) | ||
105 | m_ExternalName = m_ExternalName + "/"; | ||
106 | |||
107 | try | ||
108 | { | ||
109 | m_Uri = new Uri(m_ExternalName); | ||
110 | } | ||
111 | catch | ||
112 | { | ||
113 | m_log.WarnFormat("[GATEKEEPER SERVICE]: Malformed gatekeeper address {0}", m_ExternalName); | ||
114 | } | ||
115 | |||
116 | Object[] args = new Object[] { config }; | ||
117 | m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); | ||
118 | m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); | ||
119 | |||
120 | if (accountService != string.Empty) | ||
121 | m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); | ||
122 | if (homeUsersService != string.Empty) | ||
123 | m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args); | ||
124 | if (gridUserService != string.Empty) | ||
125 | m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); | ||
126 | if (bansService != string.Empty) | ||
127 | m_BansService = ServerUtils.LoadPlugin<IBansService>(bansService, args); | ||
128 | |||
129 | if (simService != null) | ||
130 | m_SimulationService = simService; | ||
131 | else if (simulationService != string.Empty) | ||
132 | m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args); | ||
133 | |||
134 | m_AllowedClients = serverConfig.GetString("AllowedClients", string.Empty); | ||
135 | m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); | ||
136 | m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); | ||
137 | |||
138 | LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions); | ||
139 | LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions); | ||
140 | |||
141 | if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) | ||
142 | throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); | ||
143 | |||
144 | m_log.Debug("[GATEKEEPER SERVICE]: Starting..."); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | public GatekeeperService(IConfigSource config) | ||
149 | : this(config, null) | ||
150 | { | ||
151 | } | ||
152 | |||
153 | protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, List<string> exceptions) | ||
154 | { | ||
155 | string value = config.GetString(variable, string.Empty); | ||
156 | string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); | ||
157 | |||
158 | foreach (string s in parts) | ||
159 | exceptions.Add(s.Trim()); | ||
160 | } | ||
161 | |||
162 | public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason) | ||
163 | { | ||
164 | regionID = UUID.Zero; | ||
165 | regionHandle = 0; | ||
166 | externalName = m_ExternalName + ((regionName != string.Empty) ? " " + regionName : ""); | ||
167 | imageURL = string.Empty; | ||
168 | reason = string.Empty; | ||
169 | GridRegion region = null; | ||
170 | |||
171 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty)? "default region" : regionName); | ||
172 | if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty) | ||
173 | { | ||
174 | List<GridRegion> defs = m_GridService.GetDefaultHypergridRegions(m_ScopeID); | ||
175 | if (defs != null && defs.Count > 0) | ||
176 | { | ||
177 | region = defs[0]; | ||
178 | m_DefaultGatewayRegion = region; | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | reason = "Grid setup problem. Try specifying a particular region here."; | ||
183 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to send information. Please specify a default region for this grid!"); | ||
184 | return false; | ||
185 | } | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | region = m_GridService.GetRegionByName(m_ScopeID, regionName); | ||
190 | if (region == null) | ||
191 | { | ||
192 | reason = "Region not found"; | ||
193 | return false; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | regionID = region.RegionID; | ||
198 | regionHandle = region.RegionHandle; | ||
199 | |||
200 | string regionimage = "regionImage" + regionID.ToString(); | ||
201 | regionimage = regionimage.Replace("-", ""); | ||
202 | imageURL = region.ServerURI + "index.php?method=" + regionimage; | ||
203 | |||
204 | return true; | ||
205 | } | ||
206 | |||
207 | public GridRegion GetHyperlinkRegion(UUID regionID, UUID agentID, string agentHomeURI, out string message) | ||
208 | { | ||
209 | message = null; | ||
210 | |||
211 | if (!m_AllowTeleportsToAnyRegion) | ||
212 | { | ||
213 | // Don't even check the given regionID | ||
214 | m_log.DebugFormat( | ||
215 | "[GATEKEEPER SERVICE]: Returning gateway region {0} {1} @ {2} to user {3}{4} as teleporting to arbitrary regions is not allowed.", | ||
216 | m_DefaultGatewayRegion.RegionName, | ||
217 | m_DefaultGatewayRegion.RegionID, | ||
218 | m_DefaultGatewayRegion.ServerURI, | ||
219 | agentID, | ||
220 | agentHomeURI == null ? "" : " @ " + agentHomeURI); | ||
221 | |||
222 | message = "Teleporting to the default region."; | ||
223 | return m_DefaultGatewayRegion; | ||
224 | } | ||
225 | |||
226 | GridRegion region = m_GridService.GetRegionByUUID(m_ScopeID, regionID); | ||
227 | |||
228 | if (region == null) | ||
229 | { | ||
230 | m_log.DebugFormat( | ||
231 | "[GATEKEEPER SERVICE]: Could not find region with ID {0} as requested by user {1}{2}. Returning null.", | ||
232 | regionID, agentID, (agentHomeURI == null) ? "" : " @ " + agentHomeURI); | ||
233 | |||
234 | message = "The teleport destination could not be found."; | ||
235 | return null; | ||
236 | } | ||
237 | |||
238 | m_log.DebugFormat( | ||
239 | "[GATEKEEPER SERVICE]: Returning region {0} {1} @ {2} to user {3}{4}.", | ||
240 | region.RegionName, | ||
241 | region.RegionID, | ||
242 | region.ServerURI, | ||
243 | agentID, | ||
244 | agentHomeURI == null ? "" : " @ " + agentHomeURI); | ||
245 | |||
246 | return region; | ||
247 | } | ||
248 | |||
249 | #region Login Agent | ||
250 | public bool LoginAgent(GridRegion source, AgentCircuitData aCircuit, GridRegion destination, out string reason) | ||
251 | { | ||
252 | reason = string.Empty; | ||
253 | |||
254 | string authURL = string.Empty; | ||
255 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) | ||
256 | authURL = aCircuit.ServiceURLs["HomeURI"].ToString(); | ||
257 | |||
258 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login request for {0} {1} @ {2} ({3}) at {4} using viewer {5}, channel {6}, IP {7}, Mac {8}, Id0 {9}, Teleport Flags: {10}. From region {11}", | ||
259 | aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionID, | ||
260 | aCircuit.Viewer, aCircuit.Channel, aCircuit.IPAddress, aCircuit.Mac, aCircuit.Id0, (TeleportFlags)aCircuit.teleportFlags, | ||
261 | (source == null) ? "Unknown" : string.Format("{0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)); | ||
262 | |||
263 | string curViewer = Util.GetViewerName(aCircuit); | ||
264 | |||
265 | // | ||
266 | // Check client | ||
267 | // | ||
268 | if (m_AllowedClients != string.Empty) | ||
269 | { | ||
270 | Regex arx = new Regex(m_AllowedClients); | ||
271 | Match am = arx.Match(curViewer); | ||
272 | |||
273 | if (!am.Success) | ||
274 | { | ||
275 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is not allowed", curViewer); | ||
276 | return false; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | if (m_DeniedClients != string.Empty) | ||
281 | { | ||
282 | Regex drx = new Regex(m_DeniedClients); | ||
283 | Match dm = drx.Match(curViewer); | ||
284 | |||
285 | if (dm.Success) | ||
286 | { | ||
287 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: client {0} is denied", curViewer); | ||
288 | return false; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | // | ||
293 | // Authenticate the user | ||
294 | // | ||
295 | if (!Authenticate(aCircuit)) | ||
296 | { | ||
297 | reason = "Unable to verify identity"; | ||
298 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Unable to verify identity of agent {0} {1}. Refusing service.", aCircuit.firstname, aCircuit.lastname); | ||
299 | return false; | ||
300 | } | ||
301 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Identity verified for {0} {1} @ {2}", aCircuit.firstname, aCircuit.lastname, authURL); | ||
302 | |||
303 | // | ||
304 | // Check for impersonations | ||
305 | // | ||
306 | UserAccount account = null; | ||
307 | if (m_UserAccountService != null) | ||
308 | { | ||
309 | // Check to see if we have a local user with that UUID | ||
310 | account = m_UserAccountService.GetUserAccount(m_ScopeID, aCircuit.AgentID); | ||
311 | if (account != null) | ||
312 | { | ||
313 | // Make sure this is the user coming home, and not a foreign user with same UUID as a local user | ||
314 | if (m_UserAgentService != null) | ||
315 | { | ||
316 | if (!m_UserAgentService.IsAgentComingHome(aCircuit.SessionID, m_ExternalName)) | ||
317 | { | ||
318 | // Can't do, sorry | ||
319 | reason = "Unauthorized"; | ||
320 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agent {0} {1} has same ID as local user. Refusing service.", | ||
321 | aCircuit.firstname, aCircuit.lastname); | ||
322 | return false; | ||
323 | |||
324 | } | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | // | ||
330 | // Foreign agents allowed? Exceptions? | ||
331 | // | ||
332 | if (account == null) | ||
333 | { | ||
334 | bool allowed = m_ForeignAgentsAllowed; | ||
335 | |||
336 | if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions)) | ||
337 | allowed = false; | ||
338 | |||
339 | if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions)) | ||
340 | allowed = true; | ||
341 | |||
342 | if (!allowed) | ||
343 | { | ||
344 | reason = "Destination does not allow visitors from your world"; | ||
345 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1} @ {2}. Refusing service.", | ||
346 | aCircuit.firstname, aCircuit.lastname, aCircuit.ServiceURLs["HomeURI"]); | ||
347 | return false; | ||
348 | } | ||
349 | } | ||
350 | |||
351 | // | ||
352 | // Is the user banned? | ||
353 | // This uses a Ban service that's more powerful than the configs | ||
354 | // | ||
355 | string uui = (account != null ? aCircuit.AgentID.ToString() : Util.ProduceUserUniversalIdentifier(aCircuit)); | ||
356 | if (m_BansService != null && m_BansService.IsBanned(uui, aCircuit.IPAddress, aCircuit.Id0, authURL)) | ||
357 | { | ||
358 | reason = "You are banned from this world"; | ||
359 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Login failed, reason: user {0} is banned", uui); | ||
360 | return false; | ||
361 | } | ||
362 | |||
363 | m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name); | ||
364 | |||
365 | bool isFirstLogin = false; | ||
366 | // | ||
367 | // Login the presence, if it's not there yet (by the login service) | ||
368 | // | ||
369 | PresenceInfo presence = m_PresenceService.GetAgent(aCircuit.SessionID); | ||
370 | if (presence != null) // it has been placed there by the login service | ||
371 | isFirstLogin = true; | ||
372 | |||
373 | else | ||
374 | { | ||
375 | if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID)) | ||
376 | { | ||
377 | reason = "Unable to login presence"; | ||
378 | m_log.InfoFormat("[GATEKEEPER SERVICE]: Presence login failed for foreign agent {0} {1}. Refusing service.", | ||
379 | aCircuit.firstname, aCircuit.lastname); | ||
380 | return false; | ||
381 | } | ||
382 | |||
383 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name); | ||
384 | |||
385 | // Also login foreigners with GridUser service | ||
386 | if (m_GridUserService != null && account == null) | ||
387 | { | ||
388 | string userId = aCircuit.AgentID.ToString(); | ||
389 | string first = aCircuit.firstname, last = aCircuit.lastname; | ||
390 | if (last.StartsWith("@")) | ||
391 | { | ||
392 | string[] parts = aCircuit.firstname.Split('.'); | ||
393 | if (parts.Length >= 2) | ||
394 | { | ||
395 | first = parts[0]; | ||
396 | last = parts[1]; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | userId += ";" + aCircuit.ServiceURLs["HomeURI"] + ";" + first + " " + last; | ||
401 | m_GridUserService.LoggedIn(userId); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | // | ||
406 | // Get the region | ||
407 | // | ||
408 | destination = m_GridService.GetRegionByUUID(m_ScopeID, destination.RegionID); | ||
409 | if (destination == null) | ||
410 | { | ||
411 | reason = "Destination region not found"; | ||
412 | return false; | ||
413 | } | ||
414 | |||
415 | m_log.DebugFormat( | ||
416 | "[GATEKEEPER SERVICE]: Destination {0} is ok for {1}", destination.RegionName, aCircuit.Name); | ||
417 | |||
418 | // | ||
419 | // Adjust the visible name | ||
420 | // | ||
421 | if (account != null) | ||
422 | { | ||
423 | aCircuit.firstname = account.FirstName; | ||
424 | aCircuit.lastname = account.LastName; | ||
425 | } | ||
426 | if (account == null) | ||
427 | { | ||
428 | if (!aCircuit.lastname.StartsWith("@")) | ||
429 | aCircuit.firstname = aCircuit.firstname + "." + aCircuit.lastname; | ||
430 | try | ||
431 | { | ||
432 | Uri uri = new Uri(aCircuit.ServiceURLs["HomeURI"].ToString()); | ||
433 | aCircuit.lastname = "@" + uri.Authority; | ||
434 | } | ||
435 | catch | ||
436 | { | ||
437 | m_log.WarnFormat("[GATEKEEPER SERVICE]: Malformed HomeURI (this should never happen): {0}", aCircuit.ServiceURLs["HomeURI"]); | ||
438 | aCircuit.lastname = "@" + aCircuit.ServiceURLs["HomeURI"].ToString(); | ||
439 | } | ||
440 | } | ||
441 | |||
442 | // | ||
443 | // Finally launch the agent at the destination | ||
444 | // | ||
445 | Constants.TeleportFlags loginFlag = isFirstLogin ? Constants.TeleportFlags.ViaLogin : Constants.TeleportFlags.ViaHGLogin; | ||
446 | |||
447 | // Preserve our TeleportFlags we have gathered so-far | ||
448 | loginFlag |= (Constants.TeleportFlags) aCircuit.teleportFlags; | ||
449 | |||
450 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Launching {0}, Teleport Flags: {1}", aCircuit.Name, loginFlag); | ||
451 | |||
452 | string version; | ||
453 | |||
454 | if (!m_SimulationService.QueryAccess( | ||
455 | destination, aCircuit.AgentID, aCircuit.ServiceURLs["HomeURI"].ToString(), | ||
456 | true, aCircuit.startpos, "SIMULATION/0.3", new List<UUID>(), out version, out reason)) | ||
457 | return false; | ||
458 | |||
459 | return m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, out reason); | ||
460 | } | ||
461 | |||
462 | protected bool Authenticate(AgentCircuitData aCircuit) | ||
463 | { | ||
464 | if (!CheckAddress(aCircuit.ServiceSessionID)) | ||
465 | return false; | ||
466 | |||
467 | if (string.IsNullOrEmpty(aCircuit.IPAddress)) | ||
468 | { | ||
469 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide a client IP address."); | ||
470 | return false; | ||
471 | } | ||
472 | |||
473 | string userURL = string.Empty; | ||
474 | if (aCircuit.ServiceURLs.ContainsKey("HomeURI")) | ||
475 | userURL = aCircuit.ServiceURLs["HomeURI"].ToString(); | ||
476 | |||
477 | if (userURL == string.Empty) | ||
478 | { | ||
479 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide an authentication server URL"); | ||
480 | return false; | ||
481 | } | ||
482 | |||
483 | if (userURL == m_ExternalName) | ||
484 | { | ||
485 | return m_UserAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID); | ||
486 | } | ||
487 | else | ||
488 | { | ||
489 | IUserAgentService userAgentService = new UserAgentServiceConnector(userURL); | ||
490 | |||
491 | try | ||
492 | { | ||
493 | return userAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID); | ||
494 | } | ||
495 | catch | ||
496 | { | ||
497 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to contact authentication service at {0}", userURL); | ||
498 | return false; | ||
499 | } | ||
500 | } | ||
501 | } | ||
502 | |||
503 | // Check that the service token was generated for *this* grid. | ||
504 | // If it wasn't then that's a fake agent. | ||
505 | protected bool CheckAddress(string serviceToken) | ||
506 | { | ||
507 | string[] parts = serviceToken.Split(new char[] { ';' }); | ||
508 | if (parts.Length < 2) | ||
509 | return false; | ||
510 | |||
511 | char[] trailing_slash = new char[] { '/' }; | ||
512 | string addressee = parts[0].TrimEnd(trailing_slash); | ||
513 | string externalname = m_ExternalName.TrimEnd(trailing_slash); | ||
514 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Verifying {0} against {1}", addressee, externalname); | ||
515 | |||
516 | Uri uri; | ||
517 | try | ||
518 | { | ||
519 | uri = new Uri(addressee); | ||
520 | } | ||
521 | catch | ||
522 | { | ||
523 | m_log.DebugFormat("[GATEKEEPER SERVICE]: Visitor provided malformed service address {0}", addressee); | ||
524 | return false; | ||
525 | } | ||
526 | |||
527 | return string.Equals(uri.GetLeftPart(UriPartial.Authority), m_Uri.GetLeftPart(UriPartial.Authority), StringComparison.OrdinalIgnoreCase) ; | ||
528 | } | ||
529 | |||
530 | #endregion | ||
531 | |||
532 | |||
533 | #region Misc | ||
534 | |||
535 | private bool IsException(AgentCircuitData aCircuit, List<string> exceptions) | ||
536 | { | ||
537 | bool exception = false; | ||
538 | if (exceptions.Count > 0) // we have exceptions | ||
539 | { | ||
540 | // Retrieve the visitor's origin | ||
541 | string userURL = aCircuit.ServiceURLs["HomeURI"].ToString(); | ||
542 | if (!userURL.EndsWith("/")) | ||
543 | userURL += "/"; | ||
544 | |||
545 | if (exceptions.Find(delegate(string s) | ||
546 | { | ||
547 | if (!s.EndsWith("/")) | ||
548 | s += "/"; | ||
549 | return s == userURL; | ||
550 | }) != null) | ||
551 | exception = true; | ||
552 | } | ||
553 | |||
554 | return exception; | ||
555 | } | ||
556 | |||
557 | #endregion | ||
558 | } | ||
559 | } | ||