Summary: PermCalc a useful utility. Code Access Security is powerful. How do you know what permissions your code needs? This utility can help.
A Review of Minimal Permissions
The PermCalc Utility, an essential tool
In other blogs (APTC and LinkDemand) I have written about how certain aspects of the .NET Framework can be used to address situations in which managed code would not execute or in most cases not even load. How do you know however what permissions a caller must have and for that matter what permissions your code must have in order to execute without throwing a security exception?
Visual Studio 2005 shipped with a command line utility called permcalc. It allows you to determine the minimal permissions that a caller will have to possess in order to use successfully the publicly exposed members of classes in your assemblies.
Using the utility is very straightforward. Basic reference information can be found here. There are a number of switches that you can set to refine the tool. One of the more valuable ones is the –Under switch that alters the default algorithm so that necessary minimums, when they cannot be exactly determined, are under estimated rather than over estimated. This helps ensure you code and your callers run with least permissions.
The result of running this utility is an xml file that can be used to create a custom permission configuration file.
It can be very enlightening to look at the permissions necessary to execute your code and the resources that are being used by the members of classes you invoke in referenced assemblies. In a future blog I’ll address creating such a file.
Here is a sample of the output for a dll that uses SharePoint classes to add a document to a doclib(note also the constructors, default and overloaded and the permissions associated with invoking them. You’ll see a Demand which you might recall forces a stack walk. LinkDemands, discussed in an earlier blog, also are displayed if present.
Spend some time with this utility. Then remember it when you are getting Security exceptions. It can make life much easier.
<Method Sig="instance bool AddDocumentToList(struct Guid , struct Guid , class Hashtable , string , class Stream )">
<Demand>
<PermissionSet version="1" class="System.Security.PermissionSet">
<IPermission version="1" class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" />
<IPermission version="1" class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" PathDiscovery="*AllFiles*" />
</PermissionSet>
</Demand>
</Method>
<Method Sig="instance void .ctor()" />
</Type>
<Type Name="Locator">
<Method Sig="instance void .ctor()">
<Demand>
<PermissionSet version="1" class="System.Security.PermissionSet">
<IPermission version="1" class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" />
<IPermission version="1" class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" PathDiscovery="*AllFiles*" />
<IPermission version="1" class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="MemberAccess" />
<IPermission version="1" class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="ControlEvidence" />
<IPermission version="1" class="System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" />
</PermissionSet>
</Demand>
</Method>
<Method Sig="instance void .ctor(struct Guid , struct Guid )">
<Demand>
<PermissionSet version="1" class="System.Security.PermissionSet">
<IPermission version="1" class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" />
<IPermission version="1" class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" PathDiscovery="*AllFiles*" />
<IPermission version="1" class="System.Security.Permissions.ReflectionPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="MemberAccess" />
<IPermission version="1" class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Flags="ControlEvidence" />
<IPermission version="1" class="System.Security.Permissions.KeyContainerPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" Unrestricted="true" />
</PermissionSet>
</Demand>
</Method>