Sunday, January 22, 2006
« Geek Dinner - January 2006 | Main | New Toy - PSP »

There seems to be a lot of confusion floating around out there regarding the StrongNameIdentityPermission...and perhaps with good cause.  Perhaps you've seen (or written) code that resembles the following example which uses the permission declaratively via the StrongNameIdentityPermissionAttribute (SNIPA):

[StrongNameIdentityPermission(SecurityAction.Demand, PublicKey=".....")]
public sealed class TestClass { ... }

One might infer that a demand is placed on the consumer of TestClass such that it must be signed with the specified public key.  In fact, that assumption seemed to hold true in .NET 1.x.  Running within .NET 1.x you could effectively mark your types (or assemblies, constructors, or methods) with this attribute to prevent unknown callers from invoking those methods.  However, this was really just an illusion.  There were oh so many ways around this.  The best it really accomplishes is to present a facade of security (which may very well be worse than no security at all).

I'll be the first to admit that I've used that strategy in the past with smaller project to create a 'family of related applications'.

Basically what it comes down to is this:  In the .NET 1.x timeframe, all Identity permissions (except empty ones) were not considered to be a subset of the Unrestricted PermissionSet.  In essence this forced the various demands (e.g. Demand, LinkDemand, InheritanceDemand, etc) to take effect even if the assembly was running in FullTrust.  Effectively, the StrongNameIdentityPermission would block an application in FullTrust with an invalid public key.  This seemed hunky dory.

Things have changed, however, in the .NET 2.x world.  Hopefully these changes will affect only a small number of applications out there.  FullTrust now really means "Full Trust".  That is, Code Access Security (CAS) is not enforced if the assembly is running under FullTrust - ever.  Once an application, malignant or benign, is running in FullTrust, it can do whatever it darn well pleases.  Also, the various Identity Permissions have become a subset of the Unrestricted PermissionSet - they always pass in FullTrust.

One benefit of this is that performance of FullTrust applications will be increased because no stackwalks need to be executes for Demands.  Demands will automatically pass and LinkDemands are optimized out completely.

These changes are pretty dramatic and simply make apparent what was previously hidden: there is no real protection against FullTrust - though there seemingly was before.  Again, that was just a facade - a misnomer. Therefore, by way of example, if you've tried using the StrongNameIdentityPermission in a .NET 1.x application and seen it block a caller, but tried the same application in .NET 2.x to different results...that's probably the reason.

If you're a developer and marking your assemblies, types, and members with the SNIPA, you're probably seeing your calls pass on through your demands and may have been confused by that behavior.  Well, your applications are undoubtedly running in FullTrust.

You may wonder, then, "What's the purpose of such an attribute?  If it doesn't stop code from running, what's the point?"  Well, as it turns out, it does stop code from calling your code...just not code running in FullTrust.  Any application in the a lesser privileged permission set (such as the internet zone) if not found with the appropriate identity will not be able to execute your code.

So what can you do to prevent types from being publicly available in .NET 2.0?  Again, there's no real protection against FullTrust.

I have some ideas, but I'd like to get your feedback before divulging...
Thoughts?

Sunday, January 22, 2006 11:56:00 AM (Mountain Standard Time, UTC-07:00)  #    Disclaimer  |  Comments [2]  |  Trackback