diff options
-rw-r--r-- | OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs | 103 |
1 files changed, 101 insertions, 2 deletions
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index 6daae29..9042e0d 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs | |||
@@ -27,9 +27,14 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.CodeDom.Compiler; | 29 | using System.CodeDom.Compiler; |
30 | using System.Collections; | ||
30 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.Diagnostics; | ||
31 | using System.IO; | 33 | using System.IO; |
32 | using System.Reflection; | 34 | using System.Reflection; |
35 | using System.Security; | ||
36 | using System.Security.Permissions; | ||
37 | using System.Security.Policy; | ||
33 | using System.Text; | 38 | using System.Text; |
34 | using log4net; | 39 | using log4net; |
35 | using Microsoft.CSharp; | 40 | using Microsoft.CSharp; |
@@ -54,6 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
54 | 59 | ||
55 | private readonly MicroScheduler m_microthreads = new MicroScheduler(); | 60 | private readonly MicroScheduler m_microthreads = new MicroScheduler(); |
56 | 61 | ||
62 | |||
63 | private IConfig m_config; | ||
64 | |||
57 | public void RegisterExtension<T>(T instance) | 65 | public void RegisterExtension<T>(T instance) |
58 | { | 66 | { |
59 | m_extensions[typeof (T)] = instance; | 67 | m_extensions[typeof (T)] = instance; |
@@ -63,6 +71,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
63 | { | 71 | { |
64 | if (source.Configs["MRM"] != null) | 72 | if (source.Configs["MRM"] != null) |
65 | { | 73 | { |
74 | m_config = source.Configs["MRM"]; | ||
75 | |||
66 | if (source.Configs["MRM"].GetBoolean("Enabled", false)) | 76 | if (source.Configs["MRM"].GetBoolean("Enabled", false)) |
67 | { | 77 | { |
68 | m_log.Info("[MRM] Enabling MRM Module"); | 78 | m_log.Info("[MRM] Enabling MRM Module"); |
@@ -112,6 +122,91 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
112 | return script; | 122 | return script; |
113 | } | 123 | } |
114 | 124 | ||
125 | /// <summary> | ||
126 | /// Create an AppDomain that contains policy restricting code to execute | ||
127 | /// with only the permissions granted by a named permission set | ||
128 | /// </summary> | ||
129 | /// <param name="permissionSetName">name of the permission set to restrict to</param> | ||
130 | /// <param name="appDomainName">'friendly' name of the appdomain to be created</param> | ||
131 | /// <exception cref="ArgumentNullException"> | ||
132 | /// if <paramref name="permissionSetName"/> is null | ||
133 | /// </exception> | ||
134 | /// <exception cref="ArgumentOutOfRangeException"> | ||
135 | /// if <paramref name="permissionSetName"/> is empty | ||
136 | /// </exception> | ||
137 | /// <returns>AppDomain with a restricted security policy</returns> | ||
138 | /// <remarks>Substantial portions of this function from: http://blogs.msdn.com/shawnfa/archive/2004/10/25/247379.aspx | ||
139 | /// Valid permissionSetName values are: | ||
140 | /// * FullTrust | ||
141 | /// * SkipVerification | ||
142 | /// * Execution | ||
143 | /// * Nothing | ||
144 | /// * LocalIntranet | ||
145 | /// * Internet | ||
146 | /// * Everything | ||
147 | /// </remarks> | ||
148 | public static AppDomain CreateRestrictedDomain(string permissionSetName, string appDomainName) | ||
149 | { | ||
150 | if (permissionSetName == null) | ||
151 | throw new ArgumentNullException("permissionSetName"); | ||
152 | if (permissionSetName.Length == 0) | ||
153 | throw new ArgumentOutOfRangeException("permissionSetName", permissionSetName, | ||
154 | "Cannot have an empty permission set name"); | ||
155 | |||
156 | // Default to all code getting nothing | ||
157 | PolicyStatement emptyPolicy = new PolicyStatement(new PermissionSet(PermissionState.None)); | ||
158 | UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), emptyPolicy); | ||
159 | |||
160 | bool foundName = false; | ||
161 | PermissionSet setIntersection = new PermissionSet(PermissionState.Unrestricted); | ||
162 | |||
163 | // iterate over each policy level | ||
164 | IEnumerator levelEnumerator = SecurityManager.PolicyHierarchy(); | ||
165 | while (levelEnumerator.MoveNext()) | ||
166 | { | ||
167 | PolicyLevel level = levelEnumerator.Current as PolicyLevel; | ||
168 | |||
169 | // if this level has defined a named permission set with the | ||
170 | // given name, then intersect it with what we've retrieved | ||
171 | // from all the previous levels | ||
172 | if (level != null) | ||
173 | { | ||
174 | PermissionSet levelSet = level.GetNamedPermissionSet(permissionSetName); | ||
175 | if (levelSet != null) | ||
176 | { | ||
177 | foundName = true; | ||
178 | if (setIntersection != null) | ||
179 | setIntersection = setIntersection.Intersect(levelSet); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | // Intersect() can return null for an empty set, so convert that | ||
185 | // to an empty set object. Also return an empty set if we didn't find | ||
186 | // the named permission set we were looking for | ||
187 | if (setIntersection == null || !foundName) | ||
188 | setIntersection = new PermissionSet(PermissionState.None); | ||
189 | else | ||
190 | setIntersection = new NamedPermissionSet(permissionSetName, setIntersection); | ||
191 | |||
192 | // if no named permission sets were found, return an empty set, | ||
193 | // otherwise return the set that was found | ||
194 | PolicyStatement permissions = new PolicyStatement(setIntersection); | ||
195 | policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), permissions)); | ||
196 | |||
197 | // create an AppDomain policy level for the policy tree | ||
198 | PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel(); | ||
199 | appDomainLevel.RootCodeGroup = policyRoot; | ||
200 | |||
201 | // create an AppDomain where this policy will be in effect | ||
202 | string domainName = appDomainName; | ||
203 | AppDomain restrictedDomain = AppDomain.CreateDomain(domainName); | ||
204 | restrictedDomain.SetAppDomainPolicy(appDomainLevel); | ||
205 | |||
206 | return restrictedDomain; | ||
207 | } | ||
208 | |||
209 | |||
115 | void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) | 210 | void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) |
116 | { | 211 | { |
117 | if (script.StartsWith("//MRM:C#")) | 212 | if (script.StartsWith("//MRM:C#")) |
@@ -125,9 +220,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule | |||
125 | 220 | ||
126 | try | 221 | try |
127 | { | 222 | { |
128 | m_log.Info("[MRM] Found C# MRM"); | 223 | m_log.Info("[MRM] Found C# MRM - Starting in AppDomain with " + m_config.GetString("permissionLevel", "Internet") + "-level security."); |
224 | |||
225 | string domainName = UUID.Random().ToString(); | ||
226 | AppDomain target = CreateRestrictedDomain(m_config.GetString("permissionLevel", "Internet"), | ||
227 | domainName); | ||
129 | 228 | ||
130 | MRMBase mmb = (MRMBase)AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap( | 229 | MRMBase mmb = (MRMBase) target.CreateInstanceFromAndUnwrap( |
131 | CompileFromDotNetText(script, itemID.ToString()), | 230 | CompileFromDotNetText(script, itemID.ToString()), |
132 | "OpenSim.MiniModule"); | 231 | "OpenSim.MiniModule"); |
133 | 232 | ||