From df55e5295fe029a9a7d23f71263cbf72c8921884 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 15 Jul 2010 20:03:08 +0200 Subject: [PATCH 01/12] Fix a few permissions vulnerability. Owners could cause permissions escalation on items contained in prims using a hacked viewer --- .../Framework/Scenes/Scene.Inventory.cs | 35 +++++++++++++++++-- .../Framework/Scenes/SceneObjectPart.cs | 7 ++++ .../Scenes/SceneObjectPartInventory.cs | 10 +++--- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 96a9d9733e..5f41f4ba7d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1339,16 +1339,45 @@ namespace OpenSim.Region.Framework.Scenes { agentTransactions.HandleTaskItemUpdateFromTransaction( remoteClient, part, transactionID, currentItem); - } - if (part.Inventory.UpdateInventoryItem(itemInfo)) - { + if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) remoteClient.SendAgentAlertMessage("Notecard saved", false); else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) remoteClient.SendAgentAlertMessage("Script saved", false); else remoteClient.SendAgentAlertMessage("Item saved", false); + } + // Check if we're allowed to mess with permissions + if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god + { + if (remoteClient.AgentId != part.OwnerID) // Not owner + { + // Friends and group members can't change any perms + itemInfo.BasePermissions = currentItem.BasePermissions; + itemInfo.EveryonePermissions = currentItem.EveryonePermissions; + itemInfo.GroupPermissions = currentItem.GroupPermissions; + itemInfo.NextPermissions = currentItem.NextPermissions; + itemInfo.CurrentPermissions = currentItem.CurrentPermissions; + } + else + { + // Owner can't change base, and can change other + // only up to base + // Base ALWAYS has move + currentItem.BasePermissions |= (uint)PermissionMask.Move; + itemInfo.BasePermissions = currentItem.BasePermissions; + itemInfo.EveryonePermissions &= currentItem.BasePermissions; + itemInfo.GroupPermissions &= currentItem.BasePermissions; + itemInfo.CurrentPermissions &= currentItem.BasePermissions; + itemInfo.NextPermissions &= currentItem.BasePermissions; + // Next ALWAYS has move + itemInfo.NextPermissions |= (uint)PermissionMask.Move; + } + + } + if (part.Inventory.UpdateInventoryItem(itemInfo)) + { part.GetProperties(remoteClient); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 59fd805bb3..6e293127b4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4137,6 +4137,13 @@ namespace OpenSim.Region.Framework.Scenes case 16: _nextOwnerMask = ApplyMask(_nextOwnerMask, set, mask) & baseMask; + // Prevent the client from creating no mod, no copy + // objects + if ((_nextOwnerMask & (uint)PermissionMask.Copy) == 0) + _nextOwnerMask |= (uint)PermissionMask.Transfer; + + _nextOwnerMask |= (uint)PermissionMask.Move; + break; } SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 20d5486b80..0ec15c1fe3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -600,12 +600,12 @@ namespace OpenSim.Region.Framework.Scenes item.GroupID = m_part.GroupID; if (item.AssetID == UUID.Zero) - item.AssetID = it.AssetID; - - lock (m_items) { - m_items[item.ItemID] = item; - m_inventorySerial++; + item.AssetID = m_items[item.ItemID].AssetID; + } + else if ((InventoryType)item.Type == InventoryType.Notecard) + { + ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); } if (fireScriptEvents) From 2eadd984ab7faeed12ef142435da349bd7ed4de0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 15 Jul 2010 20:28:18 +0200 Subject: [PATCH 02/12] prevent hacked viewers from being able to delete arbitrary items from any prim. Allow friends with perms and shared group members to move or copy things out of prims --- .../Framework/Scenes/Scene.Inventory.cs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5f41f4ba7d..8ec3b813e8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -915,6 +915,9 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = part.ParentGroup; if (group != null) { + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + TaskInventoryItem item = group.GetInventoryItem(localID, itemID); if (item == null) return; @@ -1054,9 +1057,21 @@ namespace OpenSim.Region.Framework.Scenes return; } - // Only owner can copy - if (remoteClient.AgentId != taskItem.OwnerID) - return; + TaskInventoryItem item = part.Inventory.GetInventoryItem(itemId); + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + // If the item to be moved is no copy, we need to be able to + // edit the prim. + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + } + else + { + // If the item is copiable, then we just need to have perms + // on it. The delete check is a pure rights check + if (!Permissions.CanDeleteObject(part.UUID, remoteClient.AgentId)) + return; + } MoveTaskInventoryItem(remoteClient, folderId, part, itemId); } From 3d82e79d1ce4de0cd3ccd3d462bbc1426316a616 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 20 Jul 2010 14:45:46 +0200 Subject: [PATCH 03/12] When a god uses mass permission setting, the V bit is cleared from next perms, rendering the item unmoveable for the next owenr. Make god mods conform to the rules, too. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8ec3b813e8..d79a7f121c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1363,6 +1363,9 @@ namespace OpenSim.Region.Framework.Scenes remoteClient.SendAgentAlertMessage("Item saved", false); } + // Base ALWAYS has move + currentItem.BasePermissions |= (uint)PermissionMask.Move; + // Check if we're allowed to mess with permissions if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god { @@ -1379,18 +1382,18 @@ namespace OpenSim.Region.Framework.Scenes { // Owner can't change base, and can change other // only up to base - // Base ALWAYS has move - currentItem.BasePermissions |= (uint)PermissionMask.Move; itemInfo.BasePermissions = currentItem.BasePermissions; itemInfo.EveryonePermissions &= currentItem.BasePermissions; itemInfo.GroupPermissions &= currentItem.BasePermissions; itemInfo.CurrentPermissions &= currentItem.BasePermissions; itemInfo.NextPermissions &= currentItem.BasePermissions; - // Next ALWAYS has move - itemInfo.NextPermissions |= (uint)PermissionMask.Move; } } + + // Next ALWAYS has move + itemInfo.NextPermissions |= (uint)PermissionMask.Move; + if (part.Inventory.UpdateInventoryItem(itemInfo)) { part.GetProperties(remoteClient); From 9c4380feb27c8c029c6942fd31f2ebff302d8134 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 20 Jul 2010 21:38:31 +0100 Subject: [PATCH 04/12] Remove a merge artefact --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 0ec15c1fe3..21c5368326 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -603,10 +603,6 @@ namespace OpenSim.Region.Framework.Scenes { item.AssetID = m_items[item.ItemID].AssetID; } - else if ((InventoryType)item.Type == InventoryType.Notecard) - { - ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); - } if (fireScriptEvents) m_part.TriggerScriptChangedEvent(Changed.INVENTORY); From 8641eb65b140d30a44bf9f4fb47d9cb3fcc77e34 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Tue, 20 Jul 2010 14:28:17 -0700 Subject: [PATCH 05/12] Restore lines that have been removed due to previous merge conflict. --- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 21c5368326..9eb92be505 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -598,10 +598,14 @@ namespace OpenSim.Region.Framework.Scenes // changed since permissions were last set. if (item.GroupPermissions != (uint)PermissionMask.None) item.GroupID = m_part.GroupID; - + if (item.AssetID == UUID.Zero) + item.AssetID = it.AssetID; + + lock (m_items) { - item.AssetID = m_items[item.ItemID].AssetID; + m_items[item.ItemID] = item; + m_inventorySerial++; } if (fireScriptEvents) From 8c631cfaa3af2397d325e9b440ef2b45f287471f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 16:32:55 +0200 Subject: [PATCH 06/12] Allow communicating with blue box dialogs across a region border via a child agent --- .../CoreModules/Avatar/Dialog/DialogModule.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index b5c3176d8e..72fff948ed 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -81,14 +81,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(agentID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendAgentAlertMessage(message, modal); } public void SendAlertToUser(string firstName, string lastName, string message, bool modal) { ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); - if (presence != null && !presence.IsChildAgent) + if (presence != null) presence.ControllingClient.SendAgentAlertMessage(message, modal); } @@ -96,8 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { m_scene.ForEachScenePresence(delegate(ScenePresence presence) { - if (!presence.IsChildAgent) - presence.ControllingClient.SendAlertMessage(message); + presence.ControllingClient.SendAlertMessage(message); }); } @@ -119,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog } ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } @@ -128,7 +127,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); } @@ -149,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarid); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerFirstName, ownerLastName, objectid); } @@ -205,4 +204,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog return result; } } -} \ No newline at end of file +} From 5182b9fcd28cb79ba7853b839fa010310e22aff0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 20 Jul 2010 21:32:13 +0100 Subject: [PATCH 07/12] adjust DialogModule to only send broadcast alerts to root agents --- OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 72fff948ed..2105f3c44b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -96,7 +96,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { m_scene.ForEachScenePresence(delegate(ScenePresence presence) { - presence.ControllingClient.SendAlertMessage(message); + if (!presence.IsChildAgent) + presence.ControllingClient.SendAlertMessage(message); }); } @@ -204,4 +205,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog return result; } } -} +} \ No newline at end of file From 4e537a5a86d86f9de82002d04d4c6b398302a6a1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 17 Jul 2010 07:19:58 +0100 Subject: [PATCH 08/12] Allow Megaregions to start properly after an unclean shutdown --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e2ab643ebd..091fdeb9b7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -136,6 +136,7 @@ namespace OpenSim.Region.Framework.Scenes protected SceneCommunicationService m_sceneGridService; public bool LoginsDisabled = true; + public bool LoadingPrims = false; public new float TimeDilation { @@ -1879,6 +1880,7 @@ namespace OpenSim.Region.Framework.Scenes /// public virtual void LoadPrimsFromStorage(UUID regionID) { + LoadingPrims = true; m_log.Info("[SCENE]: Loading objects from datastore"); List PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID); @@ -1902,6 +1904,7 @@ namespace OpenSim.Region.Framework.Scenes } m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); + LoadingPrims = false; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 1ca390a7c1..17275d0d19 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -294,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) - && !IsAttachmentCheckFull()) + && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims)) { m_scene.CrossPrimGroupIntoNewRegion(val, this, true); } From adba22c29bbb6cf3518857c21a3e7d31c93437a1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 22 Jul 2010 03:01:50 +0100 Subject: [PATCH 09/12] Add sending of the avatar interests and configuration of the profiles module as an OpenSim profile module to Simian grid services. Patch by Dimentox, thank you. Applied with changes. --- .../Connectors/SimianGrid/SimianProfiles.cs | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index fbf4648155..704790ee28 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -88,7 +88,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public void Initialise(IConfigSource source) { - if (Simian.IsSimianEnabled(source, "UserAccountServices", this.Name)) + if (Simian.IsSimianEnabled(source, "UserAccountServices", "SimianUserAccountServiceConnector")) { IConfig gridConfig = source.Configs["UserAccountService"]; if (gridConfig == null) @@ -108,6 +108,23 @@ namespace OpenSim.Services.Connectors.SimianGrid serviceUrl = serviceUrl + '/'; m_serverUrl = serviceUrl; + IConfig profilesConfig = source.Configs["Profiles"]; + if (profilesConfig == null) + { + // Do not run this module by default. + return; + } + else + { + // if profiles aren't enabled, we're not needed. + // if we're not specified as the connector to use, then we're not wanted + if (profilesConfig.GetString("Module", String.Empty) != Name) + { + + return; + } + m_log.InfoFormat("[SIMIAN ACCOUNT CONNECTOR]: Initializing {0}", this.Name); + } } } @@ -135,6 +152,7 @@ namespace OpenSim.Services.Connectors.SimianGrid // Profiles client.OnRequestAvatarProperties += RequestAvatarPropertiesHandler; + client.OnUpdateAvatarProperties += UpdateAvatarPropertiesHandler; client.OnAvatarInterestUpdate += AvatarInterestUpdateHandler; client.OnUserInfoRequest += UserInfoRequestHandler; @@ -302,12 +320,25 @@ namespace OpenSim.Services.Connectors.SimianGrid System.Globalization.CultureInfo.InvariantCulture), charterMember, about["FLAbout"].AsString(), (uint)flags, about["FLImage"].AsUUID(), about["Image"].AsUUID(), about["URL"].AsString(), user["Partner"].AsUUID()); + OSDMap interests = null; + if (user.ContainsKey("LLInterests")) + { + try + { + interests = OSDParser.DeserializeJson(user["LLInterests"].AsString()) as OSDMap; + client.SendAvatarInterestsReply(avatarID, interests["WantMask"].AsUInteger(), interests["WantText"].AsString(), interests["SkillsMask"].AsUInteger(), interests["SkillsText"].AsString(), interests["languages"].AsString()); + } + catch { } + } + + if (about == null) + about = new OSDMap(0); } else { m_log.Warn("[SIMIAN PROFILES]: Failed to fetch profile information for " + client.Name + ", returning default values"); client.SendAvatarProperties(avatarID, String.Empty, "1/1/1970", Utils.EmptyBytes, - String.Empty, (uint)flags, UUID.Zero, UUID.Zero, String.Empty, UUID.Zero); + String.Empty, (uint)flags, UUID.Zero, UUID.Zero, String.Empty, UUID.Zero); } } From 46001809a663a9e08ea530ed1cd2143d016750dc Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 22 Jul 2010 03:04:34 +0100 Subject: [PATCH 10/12] Adding sample configuration to previous patch --- bin/config-include/SimianGrid.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/config-include/SimianGrid.ini b/bin/config-include/SimianGrid.ini index 41deb92db2..65d4ea60df 100644 --- a/bin/config-include/SimianGrid.ini +++ b/bin/config-include/SimianGrid.ini @@ -65,3 +65,6 @@ MessagingModule = GroupsMessagingModule MessagingEnabled = true ServicesConnectorModule = SimianGroupsServicesConnector + +[Profiles] + Module = SimianProfiles From 192781e83be83d0a26a6ea377d9dd07cd76892d8 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 22 Jul 2010 04:00:24 -0700 Subject: [PATCH 11/12] Added ': ' to password prompt. Mantis #4851 --- OpenSim/Framework/Console/ConsoleBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Console/ConsoleBase.cs b/OpenSim/Framework/Console/ConsoleBase.cs index b70d1dbdc6..aab920b09a 100755 --- a/OpenSim/Framework/Console/ConsoleBase.cs +++ b/OpenSim/Framework/Console/ConsoleBase.cs @@ -118,7 +118,7 @@ namespace OpenSim.Framework.Console // (Done with no echo and suitable for passwords) public string PasswdPrompt(string p) { - return ReadLine(p, false, false); + return ReadLine(String.Format("{0}: ", p), false, false); } public virtual string ReadLine(string p, bool isCommand, bool e) From 536699cf43b5c606fdbdbc7c52a1210ca7f614b0 Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 22 Jul 2010 10:56:18 -0700 Subject: [PATCH 12/12] Flipped the flavour on post-fixes to Post_Fixes. --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index c136f5251c..4d23fbb95b 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -30,7 +30,7 @@ namespace OpenSim public class VersionInfo { private const string VERSION_NUMBER = "0.7"; - private const Flavour VERSION_FLAVOUR = Flavour.Release; + private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes; public enum Flavour {