diff options
author | Melanie | 2010-12-04 07:06:30 +0100 |
---|---|---|
committer | Melanie | 2010-12-04 07:06:30 +0100 |
commit | 96446adfa4dd91194c6ce6383927cdece8bdda1f (patch) | |
tree | bd0addccfd455ed2e1c2c54f815ae6d6357c72f2 /OpenSim/Region/CoreModules/Agent | |
parent | Simplify updating of agent inventory assets. Make newly created asset IDs (diff) | |
download | opensim-SC-96446adfa4dd91194c6ce6383927cdece8bdda1f.zip opensim-SC-96446adfa4dd91194c6ce6383927cdece8bdda1f.tar.gz opensim-SC-96446adfa4dd91194c6ce6383927cdece8bdda1f.tar.bz2 opensim-SC-96446adfa4dd91194c6ce6383927cdece8bdda1f.tar.xz |
Monitor the UUIDs used to create and update wearable assets. Reject any changed
texture that is not present in the user's inventory full perm.
This will prevent "UUID snatching", a copybot-type of attack that can cause
clothing makers to be forced to destroy and replace legit items in order to
invalidate the copies.
Diffstat (limited to 'OpenSim/Region/CoreModules/Agent')
-rw-r--r-- | OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | 10 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | 115 |
2 files changed, 125 insertions, 0 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index c66a4ea..85e1c99 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | |||
@@ -167,6 +167,16 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
167 | { | 167 | { |
168 | if (XferUploaders.ContainsKey(transactionID)) | 168 | if (XferUploaders.ContainsKey(transactionID)) |
169 | { | 169 | { |
170 | // Here we need to get the old asset to extract the | ||
171 | // texture UUIDs if it's a wearable. | ||
172 | if (item.AssetType == (int)AssetType.Bodypart || | ||
173 | item.AssetType == (int)AssetType.Clothing) | ||
174 | { | ||
175 | AssetBase oldAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); | ||
176 | if (oldAsset != null) | ||
177 | XferUploaders[transactionID].SetOldData(oldAsset.Data); | ||
178 | } | ||
179 | |||
170 | AssetBase asset = GetTransactionAsset(transactionID); | 180 | AssetBase asset = GetTransactionAsset(transactionID); |
171 | 181 | ||
172 | if (asset != null) | 182 | if (asset != null) |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index a7929ba..b8c8c85 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.IO; | 29 | using System.IO; |
30 | using System.Reflection; | 30 | using System.Reflection; |
31 | using System.Collections.Generic; | ||
31 | using log4net; | 32 | using log4net; |
32 | using OpenMetaverse; | 33 | using OpenMetaverse; |
33 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
@@ -38,6 +39,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
38 | { | 39 | { |
39 | public class AssetXferUploader | 40 | public class AssetXferUploader |
40 | { | 41 | { |
42 | // Viewer's notion of the default texture | ||
43 | private UUID defaultID = new UUID("5748decc-f629-461c-9a36-a35a221fe21f"); | ||
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
42 | 45 | ||
43 | private AssetBase m_asset; | 46 | private AssetBase m_asset; |
@@ -55,6 +58,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
55 | private UUID TransactionID = UUID.Zero; | 58 | private UUID TransactionID = UUID.Zero; |
56 | private sbyte type = 0; | 59 | private sbyte type = 0; |
57 | private byte wearableType = 0; | 60 | private byte wearableType = 0; |
61 | private byte[] m_oldData = null; | ||
58 | public ulong XferID; | 62 | public ulong XferID; |
59 | private Scene m_Scene; | 63 | private Scene m_Scene; |
60 | 64 | ||
@@ -219,6 +223,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
219 | 223 | ||
220 | private void DoCreateItem(uint callbackID) | 224 | private void DoCreateItem(uint callbackID) |
221 | { | 225 | { |
226 | ValidateAssets(); | ||
222 | m_Scene.AssetService.Store(m_asset); | 227 | m_Scene.AssetService.Store(m_asset); |
223 | 228 | ||
224 | InventoryItemBase item = new InventoryItemBase(); | 229 | InventoryItemBase item = new InventoryItemBase(); |
@@ -245,6 +250,71 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
245 | ourClient.SendAlertMessage("Unable to create inventory item"); | 250 | ourClient.SendAlertMessage("Unable to create inventory item"); |
246 | } | 251 | } |
247 | 252 | ||
253 | private void ValidateAssets() | ||
254 | { | ||
255 | if (m_asset.Type == (sbyte)AssetType.Clothing || | ||
256 | m_asset.Type == (sbyte)AssetType.Bodypart) | ||
257 | { | ||
258 | string content = System.Text.Encoding.ASCII.GetString(m_asset.Data); | ||
259 | string[] lines = content.Split(new char[] {'\n'}); | ||
260 | |||
261 | List<string> validated = new List<string>(); | ||
262 | |||
263 | Dictionary<int, UUID> allowed = ExtractTexturesFromOldData(); | ||
264 | |||
265 | int textures = 0; | ||
266 | |||
267 | foreach (string line in lines) | ||
268 | { | ||
269 | try | ||
270 | { | ||
271 | if (line.StartsWith("textures ")) | ||
272 | { | ||
273 | textures = Convert.ToInt32(line.Substring(9)); | ||
274 | validated.Add(line); | ||
275 | } | ||
276 | else if (textures > 0) | ||
277 | { | ||
278 | string[] parts = line.Split(new char[] {' '}); | ||
279 | |||
280 | UUID tx = new UUID(parts[1]); | ||
281 | int id = Convert.ToInt32(parts[0]); | ||
282 | |||
283 | if (tx == defaultID || tx == UUID.Zero || | ||
284 | (allowed.ContainsKey(id) && allowed[id] == tx)) | ||
285 | { | ||
286 | validated.Add(parts[0] + " " + tx.ToString()); | ||
287 | } | ||
288 | else | ||
289 | { | ||
290 | int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx); | ||
291 | int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy); | ||
292 | |||
293 | if ((perms & full) != full) | ||
294 | { | ||
295 | m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId); | ||
296 | validated.Add(parts[0] + " " + defaultID.ToString()); | ||
297 | } | ||
298 | } | ||
299 | textures--; | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | validated.Add(line); | ||
304 | } | ||
305 | } | ||
306 | catch | ||
307 | { | ||
308 | // If it's malformed, skip it | ||
309 | } | ||
310 | } | ||
311 | |||
312 | string final = String.Join("\n", validated.ToArray()); | ||
313 | |||
314 | m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final); | ||
315 | } | ||
316 | } | ||
317 | |||
248 | /// <summary> | 318 | /// <summary> |
249 | /// Get the asset data uploaded in this transfer. | 319 | /// Get the asset data uploaded in this transfer. |
250 | /// </summary> | 320 | /// </summary> |
@@ -253,10 +323,55 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
253 | { | 323 | { |
254 | if (m_finished) | 324 | if (m_finished) |
255 | { | 325 | { |
326 | ValidateAssets(); | ||
256 | return m_asset; | 327 | return m_asset; |
257 | } | 328 | } |
258 | 329 | ||
259 | return null; | 330 | return null; |
260 | } | 331 | } |
332 | |||
333 | public void SetOldData(byte[] d) | ||
334 | { | ||
335 | m_oldData = d; | ||
336 | } | ||
337 | |||
338 | private Dictionary<int,UUID> ExtractTexturesFromOldData() | ||
339 | { | ||
340 | Dictionary<int,UUID> result = new Dictionary<int,UUID>(); | ||
341 | if (m_oldData == null) | ||
342 | return result; | ||
343 | |||
344 | string content = System.Text.Encoding.ASCII.GetString(m_oldData); | ||
345 | string[] lines = content.Split(new char[] {'\n'}); | ||
346 | |||
347 | int textures = 0; | ||
348 | |||
349 | foreach (string line in lines) | ||
350 | { | ||
351 | try | ||
352 | { | ||
353 | if (line.StartsWith("textures ")) | ||
354 | { | ||
355 | textures = Convert.ToInt32(line.Substring(9)); | ||
356 | } | ||
357 | else if (textures > 0) | ||
358 | { | ||
359 | string[] parts = line.Split(new char[] {' '}); | ||
360 | |||
361 | UUID tx = new UUID(parts[1]); | ||
362 | int id = Convert.ToInt32(parts[0]); | ||
363 | result[id] = tx; | ||
364 | textures--; | ||
365 | } | ||
366 | } | ||
367 | catch | ||
368 | { | ||
369 | // If it's malformed, skip it | ||
370 | } | ||
371 | } | ||
372 | |||
373 | return result; | ||
374 | } | ||
261 | } | 375 | } |
262 | } | 376 | } |
377 | |||