Seeking alternative to AppDomain.CreateDomain(string, evidence) due to obsolete CAS policy
I am working through the Microsoft .Net Framework--Application Development Foundation Training Kit book Chapter 8 Lesson 2: Configuring Application Domains
ShowWinIni being the assembly name for the program I want to execute
object[] hostEvidence = { new Zone(SecurityZone.MyComputer) };
Evidence e = new Evidence(hostEvidence, null);
// Create an AppDomain.
AppDomain d = AppDomain.CreateDomain("New Domain", e);
// Run the assembly
d.ExecuteAssemblyByName("ShowWinIni");
When I execute:
AppDomain d = AppDomain.CreateDomain("New Domain", e);
I get the following message: "This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information."
I 开发者_运维技巧can execute the assembly fine when I create an AppDomain without an Evidence object.
Of course, I visited http://go.microsoft.com/fwlink/?LinkID=155570 but I am still confused as to how to create an application domain with specified privileges.
The next most helpful site I found was http://msdn.microsoft.com/en-us/library/bb763046.aspx but my StrongName object computes to NULL.
StrongName fullTrustAssembly =
typeof(Program).Assembly.Evidence.GetHostEvidence<StrongName>();
Program being the name of the class implementing all this code.
Thanks in advance for your advice and tips!
I found a way to make the original code example work without having to enable NetFX40_LegacySecurityPolicy.
EvidenceBase[] hostEvidence = { new Zone(SecurityZone.MyComputer) };
Evidence e = new Evidence(hostEvidence, null);
AppDomain d = AppDomain.CreateDomain("New Domain", e);
d.ExecuteAssemblyByName("ShowWinIni");
This will not work if you change the SecurityZone to Internet, it will try to use the obsoleted CAS security policy resulting in a NotSupportedException. What I want is a SecurityException... meaning that the assembly I want to execute does not have the permissions it needs.
To execute an assembly in an AppDomain with restricted permissions, you need to use sandboxing. The best example of sandboxing I found is here: http://www.simple-talk.com/dotnet/.net-framework/whats-new-in-code-access-security-in-.net-framework-4.0---part-i/
I think that page also explains the changes made to CAS in 4.0 very well!
Many sources, including MSDN, had me convinced I needed to provide a StrongName array when calling:
AppDomain.CreateDomain( string friendlyName,
Evidence securityInfo,
AppDomainSetup info,
PermissionSet grantSet,
params StrongName[] fullTrustAssemblies);
As stated in my original post, I was (and still am) having trouble getting a StrongName object instead of null
. Turns out I didn't even need it!
This is my completed example for sandboxing:
Evidence ev = new Evidence();
ev.AddHostEvidence(new Zone(SecurityZone.Internet));
PermissionSet internetPS = SecurityManager.GetStandardSandbox(ev);
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = Path.GetFullPath(pathToUntrusted);
AppDomain newDomain = AppDomain.CreateDomain("Sandbox Domain", null, adSetup, internetPS);
newDomain.ExecuteAssemblyByName(untrustedAssembly);
pathToUntrusted
= a string representation of the file path to my assembly
untrustedAssembly
= a string representation of the assembly name
After seeking help from colleagues, I got this working.
Apparently the book's exercise was designed to use in .Net's 3.5 framework, while I am using 4.0. After modifying both my project and the ShowWinIni project properties to use the 3.5 framework, everything worked... but I still wanted to make this work with the 4.0 framework.
To address the following message: "This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information."
I created an app.config file and added the following to it:
<configuration>
<runtime>
<NetFx40_LegacySecurityPolicy enabled="true"/>
</runtime>
</configuration>
You can read more about NetFx40_LegacySecurityPolicy at http://msdn.microsoft.com/en-us/library/dd409253.aspx
This ended up making my program an untrusted application, throwing a Security Exception when I tried to debug. To make my application trusty again, I enabled ClickOnce security settings and marked "This is a full trust application" in my project's properties.
At this point, I could debug my program but a Security Exception was now being thrown when I executed this statement:
d.ExecuteAssemblyByName("ShowWinIni");
This statement worked fine before I started trying to include an Evidence object when I created my AppDomain object. Well it turns out there's another method... AppDomain.ExecuteAssemblyByName(string, evidence), you can read about at http://msdn.microsoft.com/en-us/library/5kd4z003.aspx. So I replaced the above code snippet with the following:
d.ExecuteAssemblyByName("ShowWinIni", e);
'e' being my Evidence object created in my original question.
Now I do NOT think this is the best solution. Ideally, I would rather not force my program to use NetFx40_LegacySecurityPolicy and I believe real world apps should not rely on obsoleted methods. I thought this solution was worth posting should anyone be working through the same book as me.
精彩评论