aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/Services
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Communications/Services')
-rw-r--r--OpenSim/Framework/Communications/Services/HGInventoryService.cs636
-rw-r--r--OpenSim/Framework/Communications/Services/HGLoginAuthService.cs329
2 files changed, 965 insertions, 0 deletions
diff --git a/OpenSim/Framework/Communications/Services/HGInventoryService.cs b/OpenSim/Framework/Communications/Services/HGInventoryService.cs
new file mode 100644
index 0000000..f0b2259
--- /dev/null
+++ b/OpenSim/Framework/Communications/Services/HGInventoryService.cs
@@ -0,0 +1,636 @@
1/**
2 * Copyright (c) 2008, Contributors. All rights reserved.
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the Organizations nor the names of Individual
14 * Contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
22 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
25 * OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 */
28
29using System;
30using System.Collections;
31using System.Collections.Generic;
32using System.Reflection;
33using log4net;
34using Nini.Config;
35using OpenMetaverse;
36using OpenSim.Data;
37using OpenSim.Framework;
38//using OpenSim.Framework.Communications;
39using OpenSim.Framework.Communications.Cache;
40using Caps = OpenSim.Framework.Communications.Capabilities.Caps;
41using LLSDHelpers = OpenSim.Framework.Communications.Capabilities.LLSDHelpers;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.Interfaces;
44
45using OpenMetaverse.StructuredData;
46
47namespace OpenSim.Framework.Communications.Services
48{
49 public class HGInventoryService
50 {
51 private static readonly ILog m_log
52 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53
54 private InventoryServiceBase m_inventoryService;
55 private UserManagerBase m_userService;
56 IAssetDataPlugin m_assetProvider;
57 IHttpServer httpServer;
58 private string m_thisInventoryUrl = "http://localhost:9000";
59 private string m_thisHostname = "127.0.0.1";
60 private uint m_thisPort = 9000;
61
62
63 public HGInventoryService(InventoryServiceBase invService, IAssetDataPlugin assetService, UserManagerBase userService, IHttpServer httpserver, string url)
64 {
65 m_inventoryService = invService;
66 m_userService = userService;
67 m_thisInventoryUrl = url;
68 if (!m_thisInventoryUrl.EndsWith("/"))
69 m_thisInventoryUrl += "/";
70
71 Uri uri = new Uri(m_thisInventoryUrl);
72 if (uri != null)
73 {
74 m_thisHostname = uri.Host;
75 m_thisPort = (uint)uri.Port;
76 }
77
78 m_assetProvider = assetService;
79 httpServer = httpserver;
80
81 AddHttpHandlers();
82 }
83
84 public virtual void AddHttpHandlers()
85 {
86 httpServer.AddHTTPHandler("/InvCap/", CapHandler);
87 }
88
89 public bool CheckAuthSession(string session_id, string avatar_id)
90 {
91 return true;
92 }
93
94
95 // In truth, this is not called from the outside, for standalones. I'm just making it
96 // a handler already so that this can be reused for the InventoryServer.
97 public string CreateCapUrl(Guid _userid)
98 {
99 UUID userID = new UUID(_userid);
100 UUID random = UUID.Random();
101 string url = m_thisInventoryUrl + random.ToString() + "/";
102 m_log.InfoFormat("[HGStandaloneInvService] Creating Cap URL {0} for user {1}", url, userID.ToString());
103 return url;
104 }
105
106 /// <summary>
107 /// Return a user's entire inventory
108 /// </summary>
109 /// <param name="rawUserID"></param>
110 /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns>
111 public InventoryCollection GetUserInventory(Guid rawUserID)
112 {
113 UUID userID = new UUID(rawUserID);
114
115 m_log.Info("[HGStandaloneInvModule]: Processing request for inventory of " + userID);
116
117 // Uncomment me to simulate a slow responding inventory server
118 //Thread.Sleep(16000);
119
120 InventoryCollection invCollection = new InventoryCollection();
121
122 List<InventoryFolderBase> allFolders = m_inventoryService.GetInventorySkeleton(userID);
123
124 if (null == allFolders)
125 {
126 m_log.WarnFormat("[HGStandaloneInvModule]: No inventory found for user {0}", rawUserID);
127
128 return invCollection;
129 }
130
131 List<InventoryItemBase> allItems = new List<InventoryItemBase>();
132
133 foreach (InventoryFolderBase folder in allFolders)
134 {
135 List<InventoryItemBase> items = m_inventoryService.RequestFolderItems(folder.ID);
136
137 if (items != null)
138 {
139 allItems.InsertRange(0, items);
140 }
141 }
142
143 invCollection.UserID = userID;
144 invCollection.Folders = allFolders;
145 invCollection.Items = allItems;
146
147 // foreach (InventoryFolderBase folder in invCollection.Folders)
148 // {
149 // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back folder {0} {1}", folder.Name, folder.ID);
150 // }
151 //
152 // foreach (InventoryItemBase item in invCollection.Items)
153 // {
154 // m_log.DebugFormat("[GRID AGENT INVENTORY]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder);
155 // }
156
157 m_log.InfoFormat(
158 "[HGStandaloneInvModule]: Sending back inventory response to user {0} containing {1} folders and {2} items",
159 invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count);
160
161 return invCollection;
162 }
163
164 public InventoryCollection FetchDescendants(InventoryFolderBase fb)
165 {
166 m_log.Info("[HGStandaloneInvService]: Processing request for folder " + fb.ID);
167
168 // Uncomment me to simulate a slow responding inventory server
169 //Thread.Sleep(16000);
170
171 InventoryCollection invCollection = new InventoryCollection();
172
173 List<InventoryItemBase> items = m_inventoryService.RequestFolderItems(fb.ID);
174 List<InventoryFolderBase> folders = m_inventoryService.RequestSubFolders(fb.ID);
175
176 invCollection.UserID = fb.Owner;
177 invCollection.Folders = folders;
178 invCollection.Items = items;
179
180 m_log.DebugFormat("[HGStandaloneInvService]: Found {0} items and {1} folders", items.Count, folders.Count);
181
182 return invCollection;
183 }
184
185 public bool RemoveFolder(InventoryFolderBase folder)
186 {
187 m_log.Debug("[HGStandaloneInvService]: Removefolder: Operation not implemented yet.");
188 return false;
189 }
190
191 public InventoryItemBase GetInventoryItem(InventoryItemBase item)
192 {
193 m_log.Info("[HGStandaloneInvService]: Get item " + item.ID);
194
195 item = m_inventoryService.GetInventoryItem(item.ID);
196 if (item == null)
197 m_log.Debug("[HGStandaloneInvService]: null item");
198 return item;
199 }
200
201 public InventoryItemBase AddItem(InventoryItemBase item)
202 {
203 m_log.DebugFormat("[HGStandaloneInvService]: Add item {0} from {1}", item.ID, item.Owner);
204 if (m_inventoryService.AddItem(item))
205 return item;
206 else
207 {
208 item.ID = UUID.Zero;
209 return item;
210 }
211 }
212
213 public InventoryItemBase UpdateItem(InventoryItemBase item)
214 {
215 m_log.DebugFormat("[HGStandaloneInvService]: Update item {0} from {1}", item.ID, item.Owner);
216 InventoryItemBase it = m_inventoryService.GetInventoryItem(item.ID);
217 item.CurrentPermissions = it.CurrentPermissions;
218 item.AssetID = it.AssetID;
219 if (m_inventoryService.UpdateItem(item))
220 return item;
221 else
222 {
223 item.ID = UUID.Zero;
224 return item;
225 }
226 }
227
228 public InventoryItemBase MoveItem(InventoryItemBase newitem)
229 {
230 m_log.DebugFormat("[HGStandaloneInvService]: Move item {0} from {1}", newitem.ID, newitem.Owner);
231 InventoryItemBase Item = m_inventoryService.GetInventoryItem(newitem.ID);
232 if (Item != null)
233 {
234 if (newitem.Name != String.Empty)
235 {
236 Item.Name = newitem.Name;
237 }
238 Item.Folder = newitem.Folder;
239 m_inventoryService.UpdateItem(Item);
240 return Item;
241 }
242 else
243 {
244 m_log.Debug("[HGStandaloneInvService]: Failed to find item " + newitem.ID);
245 newitem.ID = UUID.Zero;
246 return newitem;
247 }
248
249 }
250
251 public InventoryItemBase DeleteItem(InventoryItemBase item)
252 {
253 item = m_inventoryService.GetInventoryItem(item.ID);
254 if (m_inventoryService.DeleteItem(item))
255 return item;
256 else
257 {
258 item.ID = UUID.Zero;
259 return item;
260 }
261 }
262
263 public InventoryItemBase CopyItem(InventoryItemBase olditem)
264 {
265 m_log.DebugFormat("[HGStandaloneInvService]: Copy item {0} from {1}", olditem.ID, olditem.Owner);
266 InventoryItemBase Item = m_inventoryService.GetInventoryItem(olditem.ID); // this is the old item id
267 // BIG HACK here
268 UUID newID = olditem.AssetID;
269 if (Item != null)
270 {
271 if (olditem.Name != String.Empty)
272 {
273 Item.Name = olditem.Name;
274 }
275 Item.ID = newID;
276 Item.Folder = olditem.Folder;
277 Item.Owner = olditem.Owner;
278 // There should be some tests here about the owner, etc but I'm going to ignore that
279 // because I'm not sure it makes any sense
280 // Also I should probably close the asset...
281 m_inventoryService.AddItem(Item);
282 return Item;
283 }
284 else
285 {
286 m_log.Debug("[HGStandaloneInvService]: Failed to find item " + olditem.ID);
287 olditem.ID = UUID.Zero;
288 return olditem;
289 }
290
291 }
292
293 /// <summary>
294 /// Guid to UUID wrapper for same name IInventoryServices method
295 /// </summary>
296 /// <param name="rawUserID"></param>
297 /// <returns></returns>
298 public List<InventoryFolderBase> GetInventorySkeleton(Guid rawUserID)
299 {
300 UUID userID = new UUID(rawUserID);
301 return ((InventoryServiceBase)m_inventoryService).GetInventorySkeleton(userID);
302 }
303
304 public List<InventoryItemBase> GetActiveGestures(Guid rawUserID)
305 {
306 UUID userID = new UUID(rawUserID);
307
308 m_log.InfoFormat("[HGStandaloneInvService]: fetching active gestures for user {0}", userID);
309
310 return ((InventoryServiceBase)m_inventoryService).GetActiveGestures(userID);
311 }
312
313 public AssetBase GetAsset(InventoryItemBase item)
314 {
315 m_log.Info("[HGStandaloneInvService]: Get asset " + item.AssetID + " for item " + item.ID);
316 AssetBase asset = new AssetBase(item.AssetID, "NULL"); // send an asset with no data
317 InventoryItemBase item2 = m_inventoryService.GetInventoryItem(item.ID);
318 if (item2 == null)
319 {
320 m_log.Debug("[HGStandaloneInvService]: null item");
321 return asset;
322 }
323 if (item2.Owner != item.Owner)
324 {
325 m_log.DebugFormat("[HGStandaloneInvService]: client with uuid {0} is trying to get an item of owner {1}", item.Owner, item2.Owner);
326 return asset;
327 }
328
329 // All good, get the asset
330 AssetBase theasset = m_assetProvider.FetchAsset(item.AssetID);
331 m_log.Debug("[HGStandaloneInvService] Found asset " + ((theasset == null)? "NULL" : "Not Null"));
332 if (theasset != null)
333 {
334 asset = theasset;
335 //m_log.Debug(" >> Sending assetID " + item.AssetID);
336 }
337 return asset;
338 }
339
340 public bool PostAsset(AssetBase asset)
341 {
342 m_log.Info("[HGStandaloneInvService]: Post asset " + asset.FullID);
343 m_assetProvider.CreateAsset(asset);
344
345 return true;
346 }
347
348 /// <summary>
349 /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see>
350 /// </summary>
351 public UUID UpdateInventoryItemAsset(UUID userID, UUID itemID, byte[] data)
352 {
353 m_log.Debug("[HGStandaloneInvService]: UpdateInventoryitemAsset for user " + userID + " item " + itemID);
354 InventoryItemBase item = m_inventoryService.GetInventoryItem(itemID);
355
356 if (item != null)
357 {
358 // We're still not dealing with permissions
359 //if ((InventoryType)item.InvType == InventoryType.Notecard)
360 //{
361 // if (!Permissions.CanEditNotecard(itemID, UUID.Zero, userID))
362 // {
363 // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
364 // return UUID.Zero;
365 // }
366
367 // //remoteClient.SendAgentAlertMessage("Notecard saved", false);
368 //}
369 //else if ((InventoryType)item.InvType == InventoryType.LSL)
370 //{
371 // if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
372 // {
373 // //remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
374 // return UUID.Zero;
375 // }
376
377 // //remoteClient.SendAgentAlertMessage("Script saved", false);
378 //}
379
380 AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data);
381 PostAsset(asset);
382
383 item.AssetID = asset.FullID;
384 item.Owner = userID;
385 m_inventoryService.UpdateItem(item);
386
387 return (asset.FullID);
388 }
389 return UUID.Zero;
390 }
391
392 private AssetBase CreateAsset(string name, string description, sbyte assetType, byte[] data)
393 {
394 AssetBase asset = new AssetBase();
395 asset.Name = name;
396 asset.Description = description;
397 asset.Type = assetType;
398 asset.FullID = UUID.Random();
399 asset.Data = (data == null) ? new byte[1] : data;
400
401 return asset;
402 }
403
404 #region Caps
405
406 Dictionary<UUID, Hashtable> invCaps = new Dictionary<UUID, Hashtable>();
407
408 public Hashtable CapHandler(Hashtable request)
409 {
410 m_log.Debug("[CONNECTION DEBUGGING]: InvCapHandler Called");
411
412 m_log.Debug("---------------------------");
413 m_log.Debug(" >> uri=" + request["uri"]);
414 m_log.Debug(" >> content-type=" + request["content-type"]);
415 m_log.Debug(" >> http-method=" + request["http-method"]);
416 m_log.Debug("---------------------------\n");
417
418 // these are requests if the type
419 // http://inventoryserver/InvCap/uuuuuuuu-uuuu-uuuu-uuuu-uuuuuuuuuuuu/kkkkkkkk-kkkk-kkkk-kkkk-kkkkkkkkkkkk/
420
421 Hashtable responsedata = new Hashtable();
422 responsedata["content_type"] = "text/plain";
423
424 UUID userID;
425 string authToken = string.Empty;
426 string authority = string.Empty;
427 if (!GetParams(request, out userID, out authority, out authToken))
428 {
429 m_log.InfoFormat("[HGStandaloneInvService]: Invalid parameters for InvCap message {0}", request["uri"]);
430 responsedata["int_response_code"] = 404;
431 responsedata["str_response_string"] = "Not found";
432
433 return responsedata;
434 }
435
436 // Next, let's parse the verb
437 string method = (string)request["http-method"];
438 if (method.Equals("GET"))
439 {
440 DoInvCapPost(request, responsedata, userID, authToken);
441 return responsedata;
442 }
443 //else if (method.Equals("DELETE"))
444 //{
445 // DoAgentDelete(request, responsedata, agentID, action, regionHandle);
446
447 // return responsedata;
448 //}
449 else
450 {
451 m_log.InfoFormat("[HGStandaloneInvService]: method {0} not supported in agent message", method);
452 responsedata["int_response_code"] = 405;
453 responsedata["str_response_string"] = "Method not allowed";
454
455 return responsedata;
456 }
457
458 }
459
460 public virtual void DoInvCapPost(Hashtable request, Hashtable responsedata, UUID userID, string authToken)
461 {
462
463 // This is the meaning of POST agent
464
465 // Check Auth Token
466 if (!(m_userService is IAuthentication))
467 {
468 m_log.Debug("[HGStandaloneInvService]: UserService is not IAuthentication. Denying access to inventory.");
469 responsedata["int_response_code"] = 501;
470 responsedata["str_response_string"] = "Not implemented";
471 return;
472 }
473
474 bool success = ((IAuthentication)m_userService).VerifyKey(userID, authToken);
475
476 if (success)
477 {
478
479 m_log.DebugFormat("[HGStandaloneInvService]: User has been authorized. Creating service handlers.");
480
481 // Then establish secret service handlers
482
483 Hashtable usercaps = RegisterCaps(userID, authToken);
484
485 responsedata["int_response_code"] = 200;
486 //responsedata["str_response_string"] = "OK";
487 responsedata["str_response_string"] = SerializeHashtable(usercaps);
488 }
489 else
490 {
491 m_log.DebugFormat("[HGStandaloneInvService]: User has is unauthorized. Denying service handlers.");
492 responsedata["int_response_code"] = 403;
493 responsedata["str_response_string"] = "Forbidden";
494 }
495 }
496
497
498 /// <summary>
499 /// Extract the params from a request.
500 /// </summary>
501 public static bool GetParams(Hashtable request, out UUID uuid, out string authority, out string authKey)
502 {
503 uuid = UUID.Zero;
504 authority = string.Empty;
505 authKey = string.Empty;
506
507 string uri = (string)request["uri"];
508 uri = uri.Trim(new char[] { '/' });
509 string[] parts = uri.Split('/');
510 if (parts.Length <= 1)
511 {
512 return false;
513 }
514 else
515 {
516 if (!UUID.TryParse(parts[1], out uuid))
517 return false;
518
519 if (parts.Length >= 3)
520 {
521 authKey = parts[2];
522 return true;
523 }
524 }
525
526 Uri authUri;
527 Hashtable headers = (Hashtable)request["headers"];
528
529 // Authorization keys look like this:
530 // http://orgrid.org:8002/<uuid>
531 if (headers.ContainsKey("authorization"))
532 {
533 if (Uri.TryCreate((string)headers["authorization"], UriKind.Absolute, out authUri))
534 {
535 authority = authUri.Authority;
536 authKey = authUri.PathAndQuery.Trim('/');
537 m_log.DebugFormat("[HGStandaloneInvService]: Got authority {0} and key {1}", authority, authKey);
538 return true;
539 }
540 else
541 m_log.Debug("[HGStandaloneInvService]: Wrong format for Authorization header: " + (string)headers["authorization"]);
542 }
543 else
544 m_log.Debug("[HGStandaloneInvService]: Authorization header not found");
545
546 return false;
547 }
548
549 string SerializeHashtable(Hashtable hash)
550 {
551 string result = string.Empty;
552 foreach (object key in hash.Keys)
553 {
554 result += key.ToString() + "," + hash[key].ToString() + ";";
555 }
556 return result;
557 }
558
559 Hashtable RegisterCaps(UUID userID, string authToken)
560 {
561 lock (invCaps)
562 {
563 if (invCaps.ContainsKey(userID))
564 {
565 // Remove the old ones
566 DeregisterCaps(httpServer, invCaps[userID]);
567 invCaps.Remove(userID);
568 }
569 }
570
571 Caps caps = new Caps(null, httpServer, m_thisHostname, m_thisPort, authToken, userID, false, "Inventory");
572 caps.RegisterInventoryServiceHandlers("/" + authToken + "/InventoryCap/");
573 caps.ItemUpdatedCall = UpdateInventoryItemAsset;
574 Hashtable capsHandlers = caps.CapsHandlers.CapsDetails;
575
576 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<Guid, InventoryCollection>(
577 "POST", AddAndGetCapUrl(authToken, "GetInventory", capsHandlers), GetUserInventory, CheckAuthSession));
578
579 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, InventoryCollection>(
580 "POST", AddAndGetCapUrl(authToken, "FetchDescendants", capsHandlers), FetchDescendants, CheckAuthSession));
581 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
582 "POST", AddAndGetCapUrl(authToken, "NewFolder", capsHandlers), m_inventoryService.AddFolder, CheckAuthSession));
583 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
584 "POST", AddAndGetCapUrl(authToken, "UpdateFolder", capsHandlers), m_inventoryService.UpdateFolder, CheckAuthSession));
585 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
586 "POST", AddAndGetCapUrl(authToken, "MoveFolder", capsHandlers), m_inventoryService.MoveFolder, CheckAuthSession));
587 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
588 "POST", AddAndGetCapUrl(authToken, "PurgeFolder", capsHandlers), m_inventoryService.PurgeFolder, CheckAuthSession));
589 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryFolderBase, bool>(
590 "POST", AddAndGetCapUrl(authToken, "RemoveFolder", capsHandlers), RemoveFolder, CheckAuthSession));
591
592 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
593 "POST", AddAndGetCapUrl(authToken, "GetItem", capsHandlers), GetInventoryItem, CheckAuthSession));
594 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
595 "POST", AddAndGetCapUrl(authToken, "NewItem", capsHandlers), AddItem, CheckAuthSession));
596 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
597 "POST", AddAndGetCapUrl(authToken, "UpdateItem", capsHandlers), UpdateItem, CheckAuthSession));
598 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
599 "POST", AddAndGetCapUrl(authToken, "MoveItem", capsHandlers), MoveItem, CheckAuthSession));
600 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
601 "POST", AddAndGetCapUrl(authToken, "DeleteItem", capsHandlers), DeleteItem, CheckAuthSession));
602 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, InventoryItemBase>(
603 "POST", AddAndGetCapUrl(authToken, "CopyItem", capsHandlers), CopyItem, CheckAuthSession));
604
605 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<InventoryItemBase, AssetBase>(
606 "POST", AddAndGetCapUrl(authToken, "GetAsset", capsHandlers), GetAsset, CheckAuthSession));
607 httpServer.AddStreamHandler(new RestDeserialiseSecureHandler<AssetBase, bool>(
608 "POST", AddAndGetCapUrl(authToken, "PostAsset", capsHandlers), PostAsset, CheckAuthSession));
609
610 lock (invCaps)
611 invCaps.Add(userID, capsHandlers);
612
613 return capsHandlers;
614 }
615
616 string AddAndGetCapUrl(string authToken, string capType, Hashtable caps)
617 {
618 string capUrl = "/" + authToken + "/" + capType + "/";
619
620 m_log.Debug("[HGStandaloneInvService] Adding inventory cap " + capUrl);
621 caps.Add(capType, capUrl);
622 return capUrl;
623 }
624
625 void DeregisterCaps(IHttpServer httpServer, Hashtable caps)
626 {
627 foreach (string capUrl in caps.Values)
628 {
629 m_log.Debug("[HGStandaloneInvService] Removing inventory cap " + capUrl);
630 httpServer.RemoveStreamHandler("POST", capUrl);
631 }
632 }
633
634 #endregion Caps
635 }
636}
diff --git a/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs b/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs
new file mode 100644
index 0000000..37c8846
--- /dev/null
+++ b/OpenSim/Framework/Communications/Services/HGLoginAuthService.cs
@@ -0,0 +1,329 @@
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;
30using System.Collections.Generic;
31using System.Net;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications.Cache;
36using OpenSim.Framework.Communications.Capabilities;
37using OpenSim.Framework.Servers;
38
39using OpenMetaverse;
40
41using log4net;
42using Nini.Config;
43using Nwc.XmlRpc;
44
45namespace OpenSim.Framework.Communications.Services
46{
47 public class HGLoginAuthService : LoginService
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 protected NetworkServersInfo m_serversInfo;
52 protected bool m_authUsers = false;
53
54 /// <summary>
55 /// Used by the login service to make requests to the inventory service.
56 /// </summary>
57 protected IInterServiceInventoryServices m_interServiceInventoryService;
58
59 /// <summary>
60 /// Used to make requests to the local regions.
61 /// </summary>
62 protected ILoginServiceToRegionsConnector m_regionsConnector;
63
64
65 public HGLoginAuthService(
66 UserManagerBase userManager, string welcomeMess,
67 IInterServiceInventoryServices interServiceInventoryService,
68 NetworkServersInfo serversInfo,
69 bool authenticate, LibraryRootFolder libraryRootFolder, ILoginServiceToRegionsConnector regionsConnector)
70 : base(userManager, libraryRootFolder, welcomeMess)
71 {
72 this.m_serversInfo = serversInfo;
73 if (m_serversInfo != null)
74 {
75 m_defaultHomeX = this.m_serversInfo.DefaultHomeLocX;
76 m_defaultHomeY = this.m_serversInfo.DefaultHomeLocY;
77 }
78 m_authUsers = authenticate;
79
80 m_interServiceInventoryService = interServiceInventoryService;
81 m_regionsConnector = regionsConnector;
82 m_inventoryService = interServiceInventoryService;
83 }
84
85 public void SetServersInfo(NetworkServersInfo sinfo)
86 {
87 m_serversInfo = sinfo;
88 }
89
90 public override XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request)
91 {
92 m_log.Info("[HGLOGIN] HGLogin called " + request.MethodName);
93 XmlRpcResponse response = base.XmlRpcLoginMethod(request);
94 Hashtable responseData = (Hashtable)response.Value;
95
96 responseData["grid_service"] = m_serversInfo.GridURL;
97 responseData["grid_service_send_key"] = m_serversInfo.GridSendKey;
98 responseData["inventory_service"] = m_serversInfo.InventoryURL;
99 responseData["asset_service"] = m_serversInfo.AssetURL;
100 responseData["asset_service_send_key"] = m_serversInfo.AssetSendKey;
101 int x = (Int32)responseData["region_x"];
102 int y = (Int32)responseData["region_y"];
103 uint ux = (uint)(x / Constants.RegionSize);
104 uint uy = (uint)(y / Constants.RegionSize);
105 ulong regionHandle = Util.UIntsToLong(ux, uy);
106 responseData["region_handle"] = regionHandle.ToString();
107
108 // Let's remove the seed cap from the login
109 //responseData.Remove("seed_capability");
110
111 // Let's add the appearance
112 UUID userID = UUID.Zero;
113 UUID.TryParse((string)responseData["agent_id"], out userID);
114 AvatarAppearance appearance = m_userManager.GetUserAppearance(userID);
115 if (appearance == null)
116 {
117 m_log.WarnFormat("[INTER]: Appearance not found for {0}. Creating default.", userID);
118 appearance = new AvatarAppearance();
119 }
120
121 responseData["appearance"] = appearance.ToHashTable();
122
123 // Let's also send the auth token
124 UUID token = UUID.Random();
125 responseData["auth_token"] = token.ToString();
126 UserProfileData userProfile = m_userManager.GetUserProfile(userID);
127 if (userProfile != null)
128 {
129 userProfile.WebLoginKey = token;
130 m_userManager.CommitAgent(ref userProfile);
131 }
132
133 return response;
134 }
135
136 public XmlRpcResponse XmlRpcGenerateKeyMethod(XmlRpcRequest request)
137 {
138
139 // Verify the key of who's calling
140 UUID userID = UUID.Zero;
141 UUID authKey = UUID.Zero;
142 UUID.TryParse((string)request.Params[0], out userID);
143 UUID.TryParse((string)request.Params[1], out authKey);
144
145 m_log.InfoFormat("[HGLOGIN] HGGenerateKey called with authToken ", authKey);
146 string newKey = string.Empty;
147
148 if (!(m_userManager is IAuthentication))
149 {
150 m_log.Debug("[HGLOGIN]: UserManager is not IAuthentication service. Returning empty key.");
151 }
152 else
153 {
154 newKey = ((IAuthentication)m_userManager).GetNewKey(m_serversInfo.UserURL, userID, authKey);
155 }
156
157 XmlRpcResponse response = new XmlRpcResponse();
158 response.Value = (string) newKey;
159 return response;
160 }
161
162 public XmlRpcResponse XmlRpcVerifyKeyMethod(XmlRpcRequest request)
163 {
164 foreach (object o in request.Params)
165 {
166 if (o != null)
167 m_log.Debug(" >> Param " + o.ToString());
168 else
169 m_log.Debug(" >> Null");
170 }
171
172 // Verify the key of who's calling
173 UUID userID = UUID.Zero;
174 string authKey = string.Empty;
175 UUID.TryParse((string)request.Params[0], out userID);
176 authKey = (string)request.Params[1];
177
178 m_log.InfoFormat("[HGLOGIN] HGVerifyKey called with key ", authKey);
179 bool success = false;
180
181 if (!(m_userManager is IAuthentication))
182 {
183 m_log.Debug("[HGLOGIN]: UserManager is not IAuthentication service. Denying.");
184 }
185 else
186 {
187 success = ((IAuthentication)m_userManager).VerifyKey(userID, authKey);
188 }
189
190 XmlRpcResponse response = new XmlRpcResponse();
191 response.Value = (string)success.ToString();
192 return response;
193 }
194
195 public override UserProfileData GetTheUser(string firstname, string lastname)
196 {
197 UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname);
198 if (profile != null)
199 {
200 return profile;
201 }
202
203 if (!m_authUsers)
204 {
205 //no current user account so make one
206 m_log.Info("[LOGIN]: No user account found so creating a new one.");
207
208 m_userManager.AddUser(firstname, lastname, "test", "", m_defaultHomeX, m_defaultHomeY);
209
210 return m_userManager.GetUserProfile(firstname, lastname);
211 }
212
213 return null;
214 }
215
216 public override bool AuthenticateUser(UserProfileData profile, string password)
217 {
218 if (!m_authUsers)
219 {
220 //for now we will accept any password in sandbox mode
221 m_log.Info("[LOGIN]: Authorising user (no actual password check)");
222
223 return true;
224 }
225 else
226 {
227 m_log.Info(
228 "[LOGIN]: Authenticating " + profile.FirstName + " " + profile.SurName);
229
230 if (!password.StartsWith("$1$"))
231 password = "$1$" + Util.Md5Hash(password);
232
233 password = password.Remove(0, 3); //remove $1$
234
235 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
236
237 bool loginresult = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
238 || profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
239 return loginresult;
240 }
241 }
242
243 protected override RegionInfo RequestClosestRegion(string region)
244 {
245 return m_regionsConnector.RequestClosestRegion(region);
246 }
247
248 protected override RegionInfo GetRegionInfo(ulong homeRegionHandle)
249 {
250 return m_regionsConnector.RequestNeighbourInfo(homeRegionHandle);
251 }
252
253 protected override RegionInfo GetRegionInfo(UUID homeRegionId)
254 {
255 return m_regionsConnector.RequestNeighbourInfo(homeRegionId);
256 }
257
258
259 /// <summary>
260 /// Not really informing the region. Just filling out the response fields related to the region.
261 /// </summary>
262 /// <param name="sim"></param>
263 /// <param name="user"></param>
264 /// <param name="response"></param>
265 /// <returns>true if the region was successfully contacted, false otherwise</returns>
266 protected override bool PrepareLoginToRegion(RegionInfo regionInfo, UserProfileData user, LoginResponse response)
267 {
268 IPEndPoint endPoint = regionInfo.ExternalEndPoint;
269 response.SimAddress = endPoint.Address.ToString();
270 response.SimPort = (uint)endPoint.Port;
271 response.RegionX = regionInfo.RegionLocX;
272 response.RegionY = regionInfo.RegionLocY;
273 response.SimHttpPort = regionInfo.HttpPort;
274
275 string capsPath = CapsUtil.GetRandomCapsObjectPath();
276 string capsSeedPath = CapsUtil.GetCapsSeedPath(capsPath);
277
278 // Don't use the following! It Fails for logging into any region not on the same port as the http server!
279 // Kept here so it doesn't happen again!
280 // response.SeedCapability = regionInfo.ServerURI + capsSeedPath;
281
282 string seedcap = "http://";
283
284 if (m_serversInfo.HttpUsesSSL)
285 {
286 seedcap = "https://" + m_serversInfo.HttpSSLCN + ":" + regionInfo.HttpPort + capsSeedPath;
287 }
288 else
289 {
290 seedcap = "http://" + regionInfo.ExternalHostName + ":" + regionInfo.HttpPort + capsSeedPath;
291 }
292
293 response.SeedCapability = seedcap;
294
295 // Notify the target of an incoming user
296 m_log.InfoFormat(
297 "[LOGIN]: Telling {0} @ {1},{2} ({3}) to prepare for client connection",
298 regionInfo.RegionName, response.RegionX, response.RegionY, regionInfo.ServerURI);
299
300 // Update agent with target sim
301 user.CurrentAgent.Region = regionInfo.RegionID;
302 user.CurrentAgent.Handle = regionInfo.RegionHandle;
303
304 return true;
305 }
306
307 public override void LogOffUser(UserProfileData theUser, string message)
308 {
309 RegionInfo SimInfo;
310 try
311 {
312 SimInfo = this.m_regionsConnector.RequestNeighbourInfo(theUser.CurrentAgent.Handle);
313
314 if (SimInfo == null)
315 {
316 m_log.Error("[LOCAL LOGIN]: Region user was in isn't currently logged in");
317 return;
318 }
319 }
320 catch (Exception)
321 {
322 m_log.Error("[LOCAL LOGIN]: Unable to look up region to log user off");
323 return;
324 }
325
326 m_regionsConnector.LogOffUserFromGrid(SimInfo.RegionHandle, theUser.ID, theUser.CurrentAgent.SecureSessionID, "Logging you off");
327 }
328 }
329}