aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/HypergridService
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/HypergridService')
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs321
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs244
2 files changed, 565 insertions, 0 deletions
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
new file mode 100644
index 0000000..56744b6
--- /dev/null
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -0,0 +1,321 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Interfaces;
35using GridRegion = OpenSim.Services.Interfaces.GridRegion;
36using OpenSim.Server.Base;
37using OpenSim.Services.Connectors.Hypergrid;
38
39using OpenMetaverse;
40
41using Nini.Config;
42using log4net;
43
44namespace OpenSim.Services.HypergridService
45{
46 public class GatekeeperService : IGatekeeperService
47 {
48 private static readonly ILog m_log =
49 LogManager.GetLogger(
50 MethodBase.GetCurrentMethod().DeclaringType);
51
52 IGridService m_GridService;
53 IPresenceService m_PresenceService;
54 IUserAccountService m_UserAccountService;
55 IUserAgentService m_UserAgentService;
56 ISimulationService m_SimulationService;
57
58 string m_AuthDll;
59
60 UUID m_ScopeID;
61 bool m_AllowTeleportsToAnyRegion;
62 string m_ExternalName;
63 GridRegion m_DefaultGatewayRegion;
64
65 public GatekeeperService(IConfigSource config, ISimulationService simService)
66 {
67 IConfig serverConfig = config.Configs["GatekeeperService"];
68 if (serverConfig == null)
69 throw new Exception(String.Format("No section GatekeeperService in config file"));
70
71 string accountService = serverConfig.GetString("UserAccountService", String.Empty);
72 string homeUsersService = serverConfig.GetString("HomeUsersSecurityService", string.Empty);
73 string gridService = serverConfig.GetString("GridService", String.Empty);
74 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
75 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
76
77 //m_AuthDll = serverConfig.GetString("AuthenticationService", String.Empty);
78
79 // These 3 are mandatory, the others aren't
80 if (gridService == string.Empty || presenceService == string.Empty || m_AuthDll == string.Empty)
81 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function.");
82
83 string scope = serverConfig.GetString("ScopeID", UUID.Zero.ToString());
84 UUID.TryParse(scope, out m_ScopeID);
85 //m_WelcomeMessage = serverConfig.GetString("WelcomeMessage", "Welcome to OpenSim!");
86 m_AllowTeleportsToAnyRegion = serverConfig.GetBoolean("AllowTeleportsToAnyRegion", true);
87 m_ExternalName = serverConfig.GetString("ExternalName", string.Empty);
88
89 Object[] args = new Object[] { config };
90 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
91 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
92
93 if (accountService != string.Empty)
94 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
95 if (homeUsersService != string.Empty)
96 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
97
98 if (simService != null)
99 m_SimulationService = simService;
100 else if (simulationService != string.Empty)
101 m_SimulationService = ServerUtils.LoadPlugin<ISimulationService>(simulationService, args);
102
103 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
104 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
105
106 m_log.Debug("[GATEKEEPER SERVICE]: Starting...");
107 }
108
109 public GatekeeperService(IConfigSource config)
110 : this(config, null)
111 {
112 }
113
114 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason)
115 {
116 regionID = UUID.Zero;
117 regionHandle = 0;
118 externalName = m_ExternalName;
119 imageURL = string.Empty;
120 reason = string.Empty;
121
122 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to link to {0}", (regionName == string.Empty ? "default region" : regionName));
123 if (!m_AllowTeleportsToAnyRegion || regionName == string.Empty)
124 {
125 List<GridRegion> defs = m_GridService.GetDefaultRegions(m_ScopeID);
126 if (defs != null && defs.Count > 0)
127 m_DefaultGatewayRegion = defs[0];
128
129 try
130 {
131 regionID = m_DefaultGatewayRegion.RegionID;
132 regionHandle = m_DefaultGatewayRegion.RegionHandle;
133 }
134 catch
135 {
136 reason = "Grid setup problem. Try specifying a particular region here.";
137 m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to send information. Please specify a default region for this grid!");
138 return false;
139 }
140
141 return true;
142 }
143
144 GridRegion region = m_GridService.GetRegionByName(m_ScopeID, regionName);
145 if (region == null)
146 {
147 reason = "Region not found";
148 return false;
149 }
150
151 regionID = region.RegionID;
152 regionHandle = region.RegionHandle;
153 string regionimage = "regionImage" + region.RegionID.ToString();
154 regionimage = regionimage.Replace("-", "");
155
156 imageURL = "http://" + region.ExternalHostName + ":" + region.HttpPort + "/index.php?method=" + regionimage;
157
158 return true;
159 }
160
161 public GridRegion GetHyperlinkRegion(UUID regionID)
162 {
163 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to get hyperlink region {0}", regionID);
164
165 if (!m_AllowTeleportsToAnyRegion)
166 // Don't even check the given regionID
167 return m_DefaultGatewayRegion;
168
169 GridRegion region = m_GridService.GetRegionByUUID(m_ScopeID, regionID);
170 return region;
171 }
172
173 #region Login Agent
174 public bool LoginAgent(AgentCircuitData aCircuit, GridRegion destination, out string reason)
175 {
176 reason = string.Empty;
177
178 string authURL = string.Empty;
179 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
180 authURL = aCircuit.ServiceURLs["HomeURI"].ToString();
181 m_log.DebugFormat("[GATEKEEPER SERVICE]: Request to login foreign agent {0} {1} @ {2} ({3}) at destination {4}",
182 aCircuit.firstname, aCircuit.lastname, authURL, aCircuit.AgentID, destination.RegionName);
183
184 //
185 // Authenticate the user
186 //
187 if (!Authenticate(aCircuit))
188 {
189 reason = "Unable to verify identity";
190 m_log.InfoFormat("[GATEKEEPER SERVICE]: Unable to verify identity of agent {0} {1}. Refusing service.", aCircuit.firstname, aCircuit.lastname);
191 return false;
192 }
193 m_log.DebugFormat("[GATEKEEPER SERVICE]: Identity verified for {0} {1} @ {2}", aCircuit.firstname, aCircuit.lastname, authURL);
194
195 //
196 // Check for impersonations
197 //
198 UserAccount account = null;
199 if (m_UserAccountService != null)
200 {
201 // Check to see if we have a local user with that UUID
202 account = m_UserAccountService.GetUserAccount(m_ScopeID, aCircuit.AgentID);
203 if (account != null)
204 {
205 // Make sure this is the user coming home, and not a foreign user with same UUID as a local user
206 if (m_UserAgentService != null)
207 {
208 if (!m_UserAgentService.AgentIsComingHome(aCircuit.SessionID, m_ExternalName))
209 {
210 // Can't do, sorry
211 reason = "Unauthorized";
212 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agent {0} {1} has same ID as local user. Refusing service.",
213 aCircuit.firstname, aCircuit.lastname);
214 return false;
215
216 }
217 }
218 }
219 }
220 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
221
222 // May want to authorize
223
224 //
225 // Login the presence
226 //
227 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID))
228 {
229 reason = "Unable to login presence";
230 m_log.InfoFormat("[GATEKEEPER SERVICE]: Presence login failed for foreign agent {0} {1}. Refusing service.",
231 aCircuit.firstname, aCircuit.lastname);
232 return false;
233 }
234 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
235
236 //
237 // Get the region
238 //
239 destination = m_GridService.GetRegionByUUID(m_ScopeID, destination.RegionID);
240 if (destination == null)
241 {
242 reason = "Destination region not found";
243 return false;
244 }
245 m_log.DebugFormat("[GATEKEEPER SERVICE]: destination ok: {0}", destination.RegionName);
246
247 //
248 // Adjust the visible name
249 //
250 if (account != null)
251 {
252 aCircuit.firstname = account.FirstName;
253 aCircuit.lastname = account.LastName;
254 }
255 if (account == null && !aCircuit.lastname.StartsWith("@"))
256 {
257 aCircuit.firstname = aCircuit.firstname + "." + aCircuit.lastname;
258 aCircuit.lastname = "@" + aCircuit.ServiceURLs["HomeURI"].ToString();
259 }
260
261 //
262 // Finally launch the agent at the destination
263 //
264 return m_SimulationService.CreateAgent(destination, aCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason);
265 }
266
267 protected bool Authenticate(AgentCircuitData aCircuit)
268 {
269 if (!CheckAddress(aCircuit.ServiceSessionID))
270 return false;
271
272 string userURL = string.Empty;
273 if (aCircuit.ServiceURLs.ContainsKey("HomeURI"))
274 userURL = aCircuit.ServiceURLs["HomeURI"].ToString();
275
276 if (userURL == string.Empty)
277 {
278 m_log.DebugFormat("[GATEKEEPER SERVICE]: Agent did not provide an authentication server URL");
279 return false;
280 }
281
282 Object[] args = new Object[] { userURL };
283 IUserAgentService userAgentService = new UserAgentServiceConnector(userURL); //ServerUtils.LoadPlugin<IUserAgentService>(m_AuthDll, args);
284 if (userAgentService != null)
285 {
286 try
287 {
288 return userAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID);
289 }
290 catch
291 {
292 m_log.DebugFormat("[GATEKEEPER SERVICE]: Unable to contact authentication service at {0}", userURL);
293 return false;
294 }
295 }
296
297 return false;
298 }
299
300 // Check that the service token was generated for *this* grid.
301 // If it wasn't then that's a fake agent.
302 protected bool CheckAddress(string serviceToken)
303 {
304 string[] parts = serviceToken.Split(new char[] { ';' });
305 if (parts.Length < 2)
306 return false;
307
308 string addressee = parts[0];
309 m_log.DebugFormat("[GATEKEEPER SERVICE]: Verifying {0} against {1}", addressee, m_ExternalName);
310 return (addressee == m_ExternalName);
311 }
312
313 #endregion
314
315
316 #region Misc
317
318
319 #endregion
320 }
321}
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
new file mode 100644
index 0000000..26f211b
--- /dev/null
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -0,0 +1,244 @@
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
28using System;
29using System.Collections.Generic;
30using System.Net;
31using System.Reflection;
32
33using OpenSim.Framework;
34using OpenSim.Services.Connectors.Hypergrid;
35using OpenSim.Services.Interfaces;
36using GridRegion = OpenSim.Services.Interfaces.GridRegion;
37using OpenSim.Server.Base;
38
39using OpenMetaverse;
40using log4net;
41using Nini.Config;
42
43namespace OpenSim.Services.HypergridService
44{
45 /// <summary>
46 /// This service is for HG1.5 only, to make up for the fact that clients don't
47 /// keep any private information in themselves, and that their 'home service'
48 /// needs to do it for them.
49 /// Once we have better clients, this shouldn't be needed.
50 /// </summary>
51 public class UserAgentService : IUserAgentService
52 {
53 private static readonly ILog m_log =
54 LogManager.GetLogger(
55 MethodBase.GetCurrentMethod().DeclaringType);
56
57 // This will need to go into a DB table
58 static Dictionary<UUID, TravelingAgentInfo> m_TravelingAgents = new Dictionary<UUID, TravelingAgentInfo>();
59
60 static bool m_Initialized = false;
61
62 protected static IPresenceService m_PresenceService;
63 protected static IGridService m_GridService;
64 protected static GatekeeperServiceConnector m_GatekeeperConnector;
65
66 public UserAgentService(IConfigSource config)
67 {
68 if (!m_Initialized)
69 {
70 m_log.DebugFormat("[HOME USERS SECURITY]: Starting...");
71
72 IConfig serverConfig = config.Configs["UserAgentService"];
73 if (serverConfig == null)
74 throw new Exception(String.Format("No section UserAgentService in config file"));
75
76 string gridService = serverConfig.GetString("GridService", String.Empty);
77 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
78
79 if (gridService == string.Empty || presenceService == string.Empty)
80 throw new Exception(String.Format("Incomplete specifications, UserAgent Service cannot function."));
81
82 Object[] args = new Object[] { config };
83 m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
84 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
85 m_GatekeeperConnector = new GatekeeperServiceConnector();
86
87 m_Initialized = true;
88 }
89 }
90
91 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
92 {
93 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY;
94
95 m_log.DebugFormat("[USER AGENT SERVICE]: Request to get home region of user {0}", userID);
96
97 GridRegion home = null;
98 PresenceInfo[] presences = m_PresenceService.GetAgents(new string[] { userID.ToString() });
99 if (presences != null && presences.Length > 0)
100 {
101 UUID homeID = presences[0].HomeRegionID;
102 if (homeID != UUID.Zero)
103 {
104 home = m_GridService.GetRegionByUUID(UUID.Zero, homeID);
105 position = presences[0].HomePosition;
106 lookAt = presences[0].HomeLookAt;
107 }
108 if (home == null)
109 {
110 List<GridRegion> defs = m_GridService.GetDefaultRegions(UUID.Zero);
111 if (defs != null && defs.Count > 0)
112 home = defs[0];
113 }
114 }
115
116 return home;
117 }
118
119 public bool LoginAgentToGrid(AgentCircuitData agentCircuit, GridRegion gatekeeper, GridRegion finalDestination, out string reason)
120 {
121 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} to grid {2}",
122 agentCircuit.firstname, agentCircuit.lastname, gatekeeper.ExternalHostName +":"+ gatekeeper.HttpPort);
123
124 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination
125 GridRegion region = new GridRegion(gatekeeper);
126 region.RegionName = finalDestination.RegionName;
127 region.RegionID = finalDestination.RegionID;
128 region.RegionLocX = finalDestination.RegionLocX;
129 region.RegionLocY = finalDestination.RegionLocY;
130
131 // Generate a new service session
132 agentCircuit.ServiceSessionID = "http://" + region.ExternalHostName + ":" + region.HttpPort + ";" + UUID.Random();
133 TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region);
134
135 bool success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason);
136
137 if (!success)
138 {
139 m_log.DebugFormat("[USER AGENT SERVICE]: Unable to login user {0} {1} to grid {2}, reason: {3}",
140 agentCircuit.firstname, agentCircuit.lastname, region.ExternalHostName + ":" + region.HttpPort, reason);
141
142 // restore the old travel info
143 lock (m_TravelingAgents)
144 m_TravelingAgents[agentCircuit.SessionID] = old;
145
146 return false;
147 }
148
149 return true;
150 }
151
152 TravelingAgentInfo UpdateTravelInfo(AgentCircuitData agentCircuit, GridRegion region)
153 {
154 TravelingAgentInfo travel = new TravelingAgentInfo();
155 TravelingAgentInfo old = null;
156 lock (m_TravelingAgents)
157 {
158 if (m_TravelingAgents.ContainsKey(agentCircuit.SessionID))
159 {
160 old = m_TravelingAgents[agentCircuit.SessionID];
161 }
162
163 m_TravelingAgents[agentCircuit.SessionID] = travel;
164 }
165 travel.UserID = agentCircuit.AgentID;
166 travel.GridExternalName = region.ExternalHostName + ":" + region.HttpPort;
167 travel.ServiceToken = agentCircuit.ServiceSessionID;
168 if (old != null)
169 travel.ClientToken = old.ClientToken;
170
171 return old;
172 }
173
174 public void LogoutAgent(UUID userID, UUID sessionID)
175 {
176 m_log.DebugFormat("[USER AGENT SERVICE]: User {0} logged out", userID);
177
178 lock (m_TravelingAgents)
179 {
180 List<UUID> travels = new List<UUID>();
181 foreach (KeyValuePair<UUID, TravelingAgentInfo> kvp in m_TravelingAgents)
182 if (kvp.Value == null) // do some clean up
183 travels.Add(kvp.Key);
184 else if (kvp.Value.UserID == userID)
185 travels.Add(kvp.Key);
186 foreach (UUID session in travels)
187 m_TravelingAgents.Remove(session);
188 }
189 }
190
191 // We need to prevent foreign users with the same UUID as a local user
192 public bool AgentIsComingHome(UUID sessionID, string thisGridExternalName)
193 {
194 if (!m_TravelingAgents.ContainsKey(sessionID))
195 return false;
196
197 TravelingAgentInfo travel = m_TravelingAgents[sessionID];
198 return travel.GridExternalName == thisGridExternalName;
199 }
200
201 public bool VerifyClient(UUID sessionID, string token)
202 {
203 return true;
204
205 // Commenting this for now until I understand better what part of a sender's
206 // info stays unchanged throughout a session
207 //
208 //if (m_TravelingAgents.ContainsKey(sessionID))
209 //{
210 // // Aquiles heel. Must trust the first grid upon login
211 // if (m_TravelingAgents[sessionID].ClientToken == string.Empty)
212 // {
213 // m_TravelingAgents[sessionID].ClientToken = token;
214 // return true;
215 // }
216 // return m_TravelingAgents[sessionID].ClientToken == token;
217 //}
218 //return false;
219 }
220
221 public bool VerifyAgent(UUID sessionID, string token)
222 {
223 if (m_TravelingAgents.ContainsKey(sessionID))
224 {
225 m_log.DebugFormat("[USER AGENT SERVICE]: Verifying agent token {0} against {1}", token, m_TravelingAgents[sessionID].ServiceToken);
226 return m_TravelingAgents[sessionID].ServiceToken == token;
227 }
228
229 m_log.DebugFormat("[USER AGENT SERVICE]: Token verification for session {0}: no such session", sessionID);
230
231 return false;
232 }
233
234 }
235
236 class TravelingAgentInfo
237 {
238 public UUID UserID;
239 public string GridExternalName = string.Empty;
240 public string ServiceToken = string.Empty;
241 public string ClientToken = string.Empty;
242 }
243
244}