Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...

Weblog

Mono Security Manager Part II - Using Code Identity Permissions

Yesterday I showed a sample which demanded a resource permission, UnmanagedCode in order to call Environment.Exit. Today I'll do something very similar with an identity permission.

If you have read Keith's article then you have seen the difference between the resource (e.g. file, registry, sockets...) and the identity (e.g. url, hash, zone...) permissions - aptly named *IdentityPermission. If not the previous examples should be enough to give you an idea ;-)

The following sample is based on the most commonly used identity permission, at least in source code, the StrongNameIdentityPermission. This identity permission allows you to control access based on the presence (or absence) of a digital signature on the assembly (or assemblies [1]).

As a first step, we need to create a new key pair for this sample. This key pair will let us sign our sample assembly later.

> sn -k identity.snk Mono StrongName - version 1.1.4.0 StrongName utility for signing assemblies Copyright 2002, 2003 Motus Technologies. Copyright 2004-2005 Novell. BSD licensed. A new strong name keypair has been generated in identity.snk

Next we need to extract the public key from the identity.snk file so we can include it in our application source code.

> sn -tp identity.snk Mono StrongName - version 1.1.4.0 StrongName utility for signing assemblies Copyright 2002, 2003 Motus Technologies. Copyright 2004-2005 Novell. BSD licensed. Public Key: 0024000004800000940000000602000000240000525341310004000011000000e93f54e8ace78c 04da3c4d57f0fad017ddc95d0213af383927fd143f7cac6acc17277b55864a5c9ffb1b1887c6e5 bbfb4a78c6fa10934c48aa815949e5279e17d3cb50f10779aa4bc75f58cb4acfbcd03037638d1d 32c4fd70a2e1a891d8c0046d3121705cfcd226f8fb8bc1965c7597c3ddc31d7f01aedfe800b8b1 5d344280 Public Key Token: 68cd852287e11fbb

Now the source code...

using System; using System.Security; using System.Security.Permissions; using System.Security.Principal; using System.Threading; public class Program { // substitute your own public key [StrongNameIdentityPermission (SecurityAction.Demand, PublicKey="00240000048...")] public void Execute () { Console.WriteLine ("Ok"); } static void Main () { Console.WriteLine ("Security is {0}", SecurityManager.SecurityEnabled ? "ON" : "OFF"); try { new Program ().Execute (); } catch (SecurityException) { Console.WriteLine ("Can't execute - assembly isn't strongnamed!"); } } }

Note: You need to replace the incomplete PublicKey property with the one you generated with the sn tool.

The sample will only allows [2] the Execute method to be executed if the assembly has the corresponding public key.

Note that I didn't said "if the assembly is signed"! This isn't the identity permission job to check if the identity is valid (or not). Identities are supplied by the runtime as evidences to evaluate the security policies - so it is the runtime job to ensure the evidence are valid before supplying them. This also means that no cryptographic operation (e.g. signature verification) are required each time a StrongNameIdentityPermission is being checked.

Now we compile this sample without signing the resulting assembly. We can then execute the sample with and without the security manager.

> mcs identity.cs > mono identity.exe Security is OFF Ok > mono --security identity.exe Security is ON Can't execute - assembly isn't strongnamed!

So the security manager, if active, does it's job not to execute the Execute method if no public key is present in the assembly.

Now recompile the sample this time signing the resulting assembly and execute the sample (again with and without the security manager).

> mcs identity.cs /keyfile:identity.snk

Note: the /keyfile switch is available for MCS (1.x) and CSC 8.x (fx 2.0). This means that you must add [assembly: AssemblyKeyFileName ("identity.snk")] in the sample's source code for CSC 7.x (fx 1.0/1.1).

> mono identity.exe Security is OFF Ok > mono --security identity.exe Security is ON Ok

In this case the security manager, when active, did a stack walk, because the security action is a Demand, and found out that all assemblies on the stack had the required StrongName to allow execution of the Execute method.

So far it's very much like using resource permissions, but it's not yet over...

[1] Pitfalls

Code Identity Permissions are rarely used with "classic" Demands (as we do in this sample). This is because a stack walk requires all assemblies (on the stack) to succeed the security check. In this case this requires all assemblies to share the same strongname (identity). This may happens if you use a Zone identity but it's unlikely to be true for most others - like StrongNames. The reason this sample works is that only one assembly is present on the stack when the demand is executed by the security manager.

Now that doesn't mean identity permission aren't useful - they just aren't much used with a standard (stack walk) Demand. However they are far more useful when used with LinkDemand, evaluated at JIT time, or with InheritanceDemand, evaluated at load time (both unavailable in Mono 1.1.4 but present in SVN HEAD). Something to blog on later...

[2] Looking forward: Fx 2.0

A very important fact to be aware is that version 2.0 of the .NET framework will be introducing a big change for identity permissions: they will become unrestricted permissions like the resources permissions. Which means that this sample, when executing on 2.0, will work even if the assembly isn't signed!

Why ? Because the application is local, so it is, by default, running at FullTrust. Full trust implies that you have unrestricted access to ressources (in 1.x) and now (in 2.0) that identity permission are unrestricted permissions, unrestricted access to identities.

This means that anyone using identity permissions as a code access control mechanisms for fully trust code (e.g. a plugin system based on strongnames for digital signature and enforced by the runtime/security manager) will loose this feature soon. And yes this also means that any (fully trusted) code can now inherit/override from (InheritanceDemand) or call (LinkDemand) into the class library - so it doesn't just unprotect your code.

Now I may not like it but this isn't as bad as it sounds. There were already ways to fool around such protections. Some (most?) people were putting too much confidence into them (hey! you're still dealing with fully trusted code). Some other (not too serious - even if they don't know it) people were even claiming to have broken .NET security because of this. Conclusion: the code is running at FullTrust so it should be and will now be fully trusted ;-).

Next stop... non-CAS permissions aren't oximorons!


2/22/2005 10:04:00 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.