How to: Request Minimum Permissions by Using the RequestMinimum Flag
The RequestMinimum flag enables you to request a minimum set of permissions that your code requires to execute. By contrast, the RequestRefuse flag enables you to refuse permissions by explicitly specifying which ones your code should not be granted.
You can also use the RequestOptional flag to request permissions. In this case, your application will execute even if it does not receive all the permissions that you requested, and a SecurityException is thrown if your application tries to access a protected resource. If you use this type of request, you must enable your code to catch any exceptions that will be thrown if your code is not granted the optional permissions.
The Test example in the following procedure requests FileIOPermission by using the RequestMinimum flag. The example will not run if it is not granted the requested permission. By default, running the example on your desktop will grant it full trust, and it will always run. To test the RequestMinimum flag, the example must be loaded into a partial-trust zone that does not grant FileIOPermission. The steps in the following procedure create a sandbox for the LocalIntranet zone and a test application that requires FileIOPermission. To demonstrate the use of RequestMinimum, the test application is run in the sandbox. When the application is loaded, an exception is thrown.
To Run an Application in a Sandbox
In Visual Studio, create a console application project.
Copy the code from the Example section into the application file. The code creates a sandbox that runs with the LocalIntranet permission set. The LocalIntranet permission set does not include FileIOPermission.
On the Project menu, click Properties, click the Signing tab, and sign the project with a strong name key.
Add a new console application project named Test to the solution.
Copy the following code into the application file for Test. The code requests FileIOPermission as a minimum requirement. If it cannot be granted, a SecurityException is thrown.
Imports System Imports System.Security.Permissions Imports System.IO <Assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted:=True)> Namespace Test Class Program Shared Sub Main(ByVal args() As String) Console.WriteLine("Test is loaded.") File.Create("test.txt") End Sub 'Main End Class 'Program End Namespace
using System; using System.Security.Permissions; using System.IO; [assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted=true)] namespace Test { class Program { static void Main(string[] args) { Console.WriteLine("Test is loaded."); File.Create("test.txt"); } } }
Run the sandbox application. It will try to load and run the test application. When the application is loaded, an exception is thrown with the following message:
Could not load file or assembly 'Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Failed to grant minimum permission requests. (Exception from HRESULT: 0x80131417)":"Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}.
Remove the RequestMinimum requirement by deleting or commenting the line. The example loads and begins execution, but an exception is thrown with the following message:
Request for the permission of type 'System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
By using the RequestMinimum flag, you can avoid loading the application when it is certain to fail. For more information about how to run applications in a sandbox, see How to: Run Partially Trusted Code in a Sandbox.
Example
The following example creates a sandbox that runs with LocalIntranet permissions.
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Security
Imports System.Security.Permissions
Imports System.Security.Policy
Imports System.Reflection
Imports System.IO
Namespace SimpleSandbox
Class Program
Shared Sub Main(ByVal args() As String)
' Create the permission set to grant to other assemblies.
' In this case we are granting the permissions found in the LocalIntranet zone.
Dim pset As PermissionSet = GetNamedPermissionSet("LocalIntranet")
If pset Is Nothing Then
Return
End If
Dim ads As New AppDomainSetup()
' Identify the folder to use for the sandbox.
Directory.CreateDirectory("C:\Sandbox")
ads.ApplicationBase = "C:\Sandbox"
' Copy the application to be executed to the sandbox.
File.Copy("..\..\..\Test\Bin\Debug\Test.exe", "C:\sandbox\Test.exe", True)
File.Copy("..\..\..\Test\Bin\Debug\Test.pdb", "C:\sandbox\Test.pdb", True)
Dim hostEvidence As New Evidence()
' Create the sandboxed domain.
Dim sandbox As AppDomain = AppDomain.CreateDomain("Sandboxed Domain", hostEvidence, ads, pset, GetStrongName([Assembly].GetExecutingAssembly()))
sandbox.ExecuteAssemblyByName("Test")
End Sub 'Main
Public Shared Function GetStrongName(ByVal [assembly] As [Assembly]) As StrongName
If [assembly] Is Nothing Then
Throw New ArgumentNullException("assembly")
End If
Dim assemblyName As AssemblyName = [assembly].GetName()
Debug.Assert(Not (assemblyName Is Nothing), "Could not get assembly name")
' Get the public key blob.
Dim publicKey As Byte() = assemblyName.GetPublicKey()
If publicKey Is Nothing OrElse publicKey.Length = 0 Then
Throw New InvalidOperationException("Assembly is not strongly named")
End If
Dim keyBlob As New StrongNamePublicKeyBlob(publicKey)
' Return the strong name.
Return New StrongName(keyBlob, assemblyName.Name, assemblyName.Version)
End Function 'GetStrongName
Private Shared Function GetNamedPermissionSet(ByVal name As String) As PermissionSet
Dim policyEnumerator As IEnumerator = SecurityManager.PolicyHierarchy()
' Move through the policy levels to the machine policy level.
While policyEnumerator.MoveNext()
Dim currentLevel As PolicyLevel = CType(policyEnumerator.Current, PolicyLevel)
If currentLevel.Label = "Machine" Then
Dim copy As NamedPermissionSet = currentLevel.GetNamedPermissionSet(name)
Return CType(copy, PermissionSet)
End If
End While
Return Nothing
End Function 'GetNamedPermissionSet
End Class 'Program
End Namespace
using System;
using System.Collections;
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Reflection;
using System.IO;
[assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted=true)]
namespace SimpleSandboxing
{
class Program
{
static void Main(string[] args)
{
// Create the permission set to grant to other assemblies.
// In this case we are granting the permissions found in the LocalIntranet zone.
PermissionSet pset = GetNamedPermissionSet("LocalIntranet");
if (pset == null)
return;
AppDomainSetup ads = new AppDomainSetup();
// Identify the folder to use for the sandbox.
Directory.CreateDirectory("C:\\Sandbox");
ads.ApplicationBase = "C:\\Sandbox";
// Copy the application to be executed to the sandbox.
File.Copy(@"..\..\..\Test\Bin\Debug\Test.exe", "C:\\sandbox\\Test.exe", true);
File.Copy(@"..\..\..\Test\Bin\Debug\Test.pdb", "C:\\sandbox\\Test.pdb", true);
Evidence hostEvidence = new Evidence();
// Create the sandboxed domain.
AppDomain sandbox = AppDomain.CreateDomain(
"Sandboxed Domain",
hostEvidence,
ads,
pset,
GetStrongName(Assembly.GetExecutingAssembly()));
sandbox.ExecuteAssemblyByName("Test");
}
public static StrongName GetStrongName(Assembly assembly)
{
if (assembly == null)
throw new ArgumentNullException("assembly");
AssemblyName assemblyName = assembly.GetName();
Debug.Assert(assemblyName != null, "Could not get assembly name");
// Get the public key blob.
byte[] publicKey = assemblyName.GetPublicKey();
if (publicKey == null || publicKey.Length == 0)
throw new InvalidOperationException("Assembly is not strongly named");
StrongNamePublicKeyBlob keyBlob = new StrongNamePublicKeyBlob(publicKey);
// Return the strong name.
return new StrongName(keyBlob, assemblyName.Name, assemblyName.Version);
}
private static PermissionSet GetNamedPermissionSet(string name)
{
IEnumerator policyEnumerator = SecurityManager.PolicyHierarchy();
// Move through the policy levels to the machine policy level.
while (policyEnumerator.MoveNext())
{
PolicyLevel currentLevel = (PolicyLevel)policyEnumerator.Current;
if (currentLevel.Label == "Machine")
{
NamedPermissionSet copy = currentLevel.GetNamedPermissionSet(name);
return (PermissionSet)copy;
}
}
return null;
}
}
}
See Also
Concepts
Reference
Other Resources
Extending Metadata Using Attributes
Change History
Date |
History |
Reason |
---|---|---|
September 2008 |
Expanded the information. |
Customer feedback. |