partial mantis 8219; on creating or updating items (animationsets, wearables) that reference assets, and user does not have permissions on those, abort and warn, instead of silent invalition of the references to those assets, creating a broken item

0.9.0-post-fixes
UbitUmarov 2017-07-28 17:36:40 +01:00
parent 324bda8ab9
commit 21b71ff1d8
3 changed files with 99 additions and 58 deletions

View File

@ -31,7 +31,8 @@ using OpenMetaverse;
namespace OpenSim.Framework
{
public delegate bool AnimationSetValidator(UUID animID);
// public delegate bool AnimationSetValidator(UUID animID);
public delegate uint AnimationSetValidator(UUID animID);
public class AnimationSet
{
@ -141,7 +142,7 @@ namespace OpenSim.Framework
assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key);
return System.Text.Encoding.ASCII.GetBytes(assetData);
}
/*
public bool Validate(AnimationSetValidator val)
{
if (m_parseError)
@ -164,5 +165,22 @@ namespace OpenSim.Framework
return allOk;
}
*/
public uint Validate(AnimationSetValidator val)
{
if (m_parseError)
return 0;
uint ret = 0x7fffffff;
uint t;
foreach (KeyValuePair<string, KeyValuePair<string, UUID>> kvp in m_animations)
{
t = val(kvp.Value.Value);
if (t == 0)
return 0;
ret &= t;
}
return ret;
}
}
}

View File

@ -258,24 +258,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
{
m_uploadState = UploadState.Complete;
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
bool sucess = true;
if (m_createItem)
{
CompleteCreateItem(m_createItemCallback);
sucess = CompleteCreateItem(m_createItemCallback);
}
else if (m_updateItem)
{
CompleteItemUpdate(m_updateItemData);
sucess = CompleteItemUpdate(m_updateItemData);
}
else if (m_updateTaskItem)
{
CompleteTaskItemUpdate(m_updateTaskItemData);
sucess = CompleteTaskItemUpdate(m_updateTaskItemData);
}
else if (m_asset.Local)
{
m_Scene.AssetService.Store(m_asset);
}
ourClient.SendAssetUploadCompleteMessage(m_asset.Type, sucess, m_asset.FullID);
}
m_log.DebugFormat(
@ -411,46 +411,70 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
/// Store the asset for the given item when it has been uploaded.
/// </summary>
/// <param name="item"></param>
private void CompleteItemUpdate(InventoryItemBase item)
private bool CompleteItemUpdate(InventoryItemBase item)
{
// m_log.DebugFormat(
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
// m_asset.FullID, item.Name, ourClient.Name);
ValidateAssets();
m_Scene.AssetService.Store(m_asset);
if (m_asset.FullID != UUID.Zero)
uint perms = ValidateAssets();
if(perms == 0)
{
item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item);
string error = string.Format("Not enought permissions on asset(s) referenced by item '{0}', update failed", item.Name);
ourClient.SendAlertMessage(error);
m_transactions.RemoveXferUploader(m_transactionID);
ourClient.SendBulkUpdateInventory(item); // invalid the change item on viewer cache
}
else
{
m_Scene.AssetService.Store(m_asset);
if (m_asset.FullID != UUID.Zero)
{
item.AssetID = m_asset.FullID;
m_Scene.InventoryService.UpdateItem(item);
}
ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
m_transactions.RemoveXferUploader(m_transactionID);
m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0);
}
ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0);
m_transactions.RemoveXferUploader(m_transactionID);
m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0);
return perms != 0;
}
/// <summary>
/// Store the asset for the given task item when it has been uploaded.
/// </summary>
/// <param name="taskItem"></param>
private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
private bool CompleteTaskItemUpdate(TaskInventoryItem taskItem)
{
// m_log.DebugFormat(
// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
// m_asset.FullID, taskItem.Name, ourClient.Name);
ValidateAssets();
m_Scene.AssetService.Store(m_asset);
if(ValidateAssets() == 0)
{
m_transactions.RemoveXferUploader(m_transactionID);
string error = string.Format("Not enought permissions on asset(s) referenced by task item '{0}', update failed", taskItem.Name);
ourClient.SendAlertMessage(error);
// force old asset to viewers ??
return false;
}
m_Scene.AssetService.Store(m_asset);
m_transactions.RemoveXferUploader(m_transactionID);
return true;
}
private void CompleteCreateItem(uint callbackID)
private bool CompleteCreateItem(uint callbackID)
{
ValidateAssets();
if(ValidateAssets() == 0)
{
m_transactions.RemoveXferUploader(m_transactionID);
string error = string.Format("Not enought permissions on asset(s) referenced by item '{0}', creation failed", m_name);
ourClient.SendAlertMessage(error);
return false;
}
m_Scene.AssetService.Store(m_asset);
InventoryItemBase item = new InventoryItemBase();
@ -480,35 +504,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
ourClient.SendAlertMessage("Unable to create inventory item");
m_transactions.RemoveXferUploader(m_transactionID);
return true;
}
private void ValidateAssets()
private uint ValidateAssets()
{
uint retPerms = 0x7fffffff;
// if(m_Scene.Permissions.BypassPermissions())
// return retPerms;
if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet)
{
AnimationSet animSet = new AnimationSet(m_asset.Data);
bool allOk = animSet.Validate(x => {
int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
retPerms &= animSet.Validate(x => {
const uint required = (uint)(PermissionMask.Transfer | PermissionMask.Copy);
uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x);
// currrent yes/no rule
if ((perms & required) != required)
return false;
return true;
return 0;
return perms;
});
if (!allOk)
m_asset.Data = animSet.ToBytes();
return retPerms;
}
if (m_asset.Type == (sbyte)AssetType.Clothing ||
m_asset.Type == (sbyte)AssetType.Bodypart)
{
const uint texturesfullPermMask = (uint)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
string content = System.Text.Encoding.ASCII.GetString(m_asset.Data);
string[] lines = content.Split(new char[] {'\n'});
List<string> validated = new List<string>();
// on current requiriment of full rigths assume old assets where accepted
Dictionary<int, UUID> allowed = ExtractTexturesFromOldData();
int textures = 0;
@ -518,10 +547,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
try
{
if (line.StartsWith("textures "))
{
textures = Convert.ToInt32(line.Substring(9));
validated.Add(line);
}
else if (textures > 0)
{
string[] parts = line.Split(new char[] {' '});
@ -532,42 +559,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
if (defaultIDs.Contains(tx) || tx == UUID.Zero ||
(allowed.ContainsKey(id) && allowed[id] == tx))
{
validated.Add(parts[0] + " " + tx.ToString());
continue;
}
else
{
int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy);
uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx);
if ((perms & full) != full)
if ((perms & texturesfullPermMask) != texturesfullPermMask)
{
m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId);
validated.Add(parts[0] + " " + UUID.Zero.ToString());
return 0;
}
else
{
validated.Add(line);
retPerms &= perms;
}
}
textures--;
}
else
{
validated.Add(line);
}
}
catch
{
// If it's malformed, skip it
}
}
string final = String.Join("\n", validated.ToArray());
m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final);
}
return retPerms;
}
/* not in use
/// <summary>
/// Get the asset data uploaded in this transfer.
/// </summary>
@ -582,7 +602,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
return null;
}
*/
public void SetOldData(byte[] d)
{
m_oldData = d;

View File

@ -299,15 +299,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet)
{
AnimationSet animSet = new AnimationSet(data);
if (!animSet.Validate(x => {
uint res = animSet.Validate(x => {
const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x);
int required = (int)(PermissionMask.Transfer | PermissionMask.Copy);
// enforce previus perm rule
if ((perms & required) != required)
return false;
return true;
}))
return 0;
return (uint) perms;
});
if(res == 0)
{
data = animSet.ToBytes();
remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false);
return UUID.Zero;
}
}