Allowing Partially Trusted Callers

The AllowPartiallyTrustedCallersAttribute (affectionately referred to as APTCA from here on out), is one of the aspects of the security system that most frequently trips people up when they run into it.  Lets look at a typical scenario where I might run into an issue with APTCA, and then we'll be able to understand what it is and what it does.

Lets say I'm writing a class library to be used by many applications.  Following the standard library design guidelines, I've strongly named my library, and put it in the GAC.  So far nobody who's used my library has had any problems.  However, someone in my company is building an application that's being run from a network share, and they're reporting a problem using my library.  Namely, any method that tries to call into my library isn't running, its just failing with a security exception:

Unhandled Exception: System.Security.SecurityException: Security error.
   at Caller.Main()

What's going on here?  By default, strongly named, fully trusted assemblies are given an implicit LinkDemand for FullTrust on every public and protected method of every publicly visible class.  Essentially, any code that someone outside of your assembly could use as an entry point into your code is protected with this demand.

Why do we do this?  One primary reason is to help prevent luring attacks where untrusted code can lure some fully trusted code into doing something dangerous on its behalf.  For instance, as an attacker, you look into my library and notice that in one of my methods I do an Assert for FileIOPermission, read its contents, and send them back to the caller.  You also notice that this method wasn't carefully audited, and that there's a way for you to control which file is read.  Now you can easily lure me into getting the contents of a file that you would not normally have been able to read.

OK, so lets assume that you're a careful developer and are aware of potential security issues.  You've audited all your code that performs security critical actions, and you know for sure that you're not susceptible to any luring attacks.  How can you remove the link demand so that partially trusted code can make use of the functionality you provide?

That's where APTCA comes into play.  APTCA is an attribute that tells the CLR to remove the implicit LinkDemands mentioned above.  Once you're sure your code is safe for untrusted callers to work with, apply APTCA to the assembly, and the LinkDemands will go away.  One important thing to note is that APTCA is only applicable on the assembly level, so you cannot disable these demands on a method-by-method or even  a class-by-class basis; either everything in the assembly is safe for partially trusted code to use, or none of it is.

Well, not exactly.  Since APTCA only removes the implicit LinkDemands,  any demands explicitly placed in your assembly will still be enforced.  This means that even once an assembly has been marked with APTCA, it could still have some types in it that are not usable from partial trust.  A list of types that ship with the .NET Framework, but still fall into that category can be found here.

When would you want to use apply APTCA?  Only if the following conditions all apply:

  1. Your code has been thoroughly audited for security vulnerabilities (perhaps using the MSDN Security Review Checklist)
  2. The code is in compliance with the Secure Coding Guidelines
  3. You specifically want partially trusted callers to use the library.  There's no sense opening up an attack surface if you only care if fully trusted callers can use your code.

It's interesting to note that not all of the framework assemblies are marked with APTCA. For instance, the v1.1 System..Security.dll is not callable from partially trusted code.  A list of assemblies that are callable from partial trust can be found about 2/3 of the way through this article, in the section entitled .NET Framework Assemblies with the AllowPartiallyTrustedCallersAttribute.

One final note about the exception text.  On v1.0 and v1.1, the exception pictured above isn't the most helpful in the world when you're trying to diagnose what went wrong.  With the work that went into increasing the usefulness of SecurityExceptions in Whidbey, we've also changed the error you get when you're failing a LinkDemand due to APTCA.  Instead of "Security error.", you'll now see:

Unhandled Exception: System.Security.SecurityException: That assembly does not allow partially trusted callers.
   at Caller.Main()
The action that failed was:
LinkDemand
The assembly or AppDomain that failed was:
Caller, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
The method that caused the failure was:
Void TestMethod()
The Zone of the assembly that failed was:
MyComputer
The Url of the assembly that failed was:
file:///D:/blog/aptca/Caller.exe

Which is a lot more useful when trying to diagnose the error.

For more information, check out Using Libraries from Partially Trusted Code on MSDN.