I am fooling around with StrongNameIdentityPermission
I have two assemblies (both assigned the same .snk file in there AssemblyInfo.cs)
Assembly Namespace
MyApp.Utility.dll MyApp.Utility
MyApp.exe MyApp
MyApp.exe references MyApp.Utility.dll
I have a class MyApp.Utility.Permission with a method prototyped:
public static bool Authorize() |
In my exe I have a main form with a button. . . the click event handler is defined as
private void button1_Click(object sender, System.EventArgs e) { if (MyApp.Utilities.Permission.Authorize()) MessageBox.Show("Permission Granted"); else MessageBox.Show("Permission Denied"); } |
===================
Public Key =
{ 0, 36, 0, 0, 4, 128, 0, 0, 148, 0, 0, 0, 6, 2, 0, 0,
0, 36, 0, 0, 82, 83, 65, 49, 0, 4, 0, 0, 1, 0, 1, 0, 151, 42, 61,
193, 163, 198, 44, 135, 25, 226, 210, 17, 82, 161, 67, 69, 73, 117,
15, 166, 211, 81, 225, 148, 243, 27, 172, 79, 239, 46, 44, 176,
134, 70, 206, 35, 85, 231, 74, 159, 28, 208, 250, 29, 75, 155, 227,
249, 30, 244, 191, 84, 174, 145, 81, 99, 124, 48, 51, 114, 153, 202,
158, 253, 255, 50, 174, 136, 82, 225, 237, 246, 237, 197, 207, 104,
17, 79, 143, 52, 42, 58, 98, 43, 158, 10, 144, 223, 205, 119, 187,
142, 40, 166, 85, 68, 61, 105, 231, 159, 102, 210, 147, 105, 129,
141, 31, 70, 86, 167, 55, 228, 200, 202, 170, 246, 205, 187, 119,
67, 75, 63, 236, 119, 57, 6, 117, 181 }
Name =
MyApp
Version =
1.0.2164.2229
Success
===================
I then went into MyApp.Utility.Permission and redefined it as:
public class Permission { private Permission(){} public static bool Authorize() { try { byte[] key = { 0, 36, 0, 0, 4, 128, 0, 0, 148, 0, 0, 0, 6, 2, 0, 0, 0, 36, 0, 0, 82, 83, 65, 49, 0, 4, 0, 0, 1, 0, 1, 0, 151, 42, 61, 193, 163, 198, 44, 135, 25, 226, 210, 17, 82, 161, 67, 69, 73, 117, 15, 166, 211, 81, 225, 148, 243, 27, 172, 79, 239, 46, 44, 176, 134, 70, 206, 35, 85, 231, 74, 159, 28, 208, 250, 29, 75, 155, 227, 249, 30, 244, 191, 84, 174, 145, 81, 99, 124, 48, 51, 114, 153, 202, 158, 253, 255, 50, 174, 136, 82, 225, 237, 246, 237, 197, 207, 104, 17, 79, 143, 52, 42, 58, 98, 43, 158, 10, 144, 223, 205, 119, 187, 142, 40, 166, 85, 68, 61, 105, 231, 159, 102, 210, 147, 105, 129, 141, 31, 70, 86, 167, 55, 228, 200, 202, 170, 246, 205, 187, 119, 67, 75, 63, 236, 119, 57, 6, 117, 181}; StrongNamePublicKeyBlob blob = new StrongNameIdentityPermission(key); /* Not worried about name and version right now. . . */ StrongNameIdentityPermission sniPerm = new StrongNameIdentityPermission(blob, null,null); sniPerm.Demand(); return true; } catch(Exception e) { System.Diagnostics.Debug.WriteLine(e.Message); return false; } } } |
when I run MyApp.exe Authorize goes to the catch block and writes this to the debug console:
Request for the permission of type System.Security.Permissions.StrongNameIdentityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.
What am I missing
the key is supposed to be the public key of the calling exe, correct

StrongNameIdentityPermission
David McAuley
Kjell Ahlstrom
Mike2006
I found Nicole's comments very helpful in the quest to keep unauthorized code from calling my assemblies.
I have seen msdn sample code (http://msdn2.microsoft.com/en-US/library/system.security.permissions.strongnameidentitypermission(VS.80).aspx) that shows how to programmatically extract the strong name from the calling assembly and compare it to my strong name. I prefer to use authenticode signature over strong names to avoid all the versioning headaches. Does anyone know how to detect the authenticode signature of a calling assembly
Thanks
Tick Tock
Thanks Nicole. After more research I'm discovering the flaws with authenticode in a Remoting architecture. I've been reading about problems with having to hit the CA to check for a revoked certificate: Poor server performance, or security hacks to bypass the CA check. And it implies constant Internet access, which I can't guarantee at all my customer installations. With that in mind I'm putting my attention back on strong names to verify the caller in a Remoting environment.
Has anyone looked into the approach taken by N.T.Gopalakrishnan His article at http://www.dotnetspider.com/kb/Article885.aspx talks about using a Remoting channel sink. It looks solid to me, but if anyone has critiqued it I'd love to hear what you think.
Thanks,
John
Helena Kotas
As with any other similar solution, there's nothing stopping a malicious client from spoofing the call stack data in Mr. Gopalakrishnan's article. There really is no solid way to ensure that your server code is being called by the expected client application.
Rather than trying to enforce the unenforceable, you would be better off assuming that your server is being called by a malicious client and treating all client-sourced data accordingly. In most situations, this will mean making only two changes:
Rob Zare
A Demand call verifies every frame on the call stack. There is .NET Framework code on the call stack at the time of your demand (Windows Forms code for firing the button's click event), and the Framework assemblies are signed with a different strong name key, so the demand fails. This is why one usually sees a LinkDemand used for identity permissions instead of a full Demand. If you want to crawl the entire stack, you'll need to accomodate the possibility of other keys. See http://blogs.msdn.com/eugene_bobukh/archive/2004/03/10/87603.aspx for a sample of this sort of thing.
Also, you may want to keep in mind that even in v. 1.x of the Framework, StrongNameIdentityPermission verifications are quite trivial to bypass by
code with certain "high privilege" CAS permissions. In addition, all code
running with unrestricted CAS permissions (aka "full trust") automatically
passes demands for any identity permission in v. 2.0. Given this, you might
want to consider using some alternate mechanism (e.g.: licensing) for
limiting callers.
Brandon H. Campbell
Jeevanantham
this stuff is all new to me. . .
question:
Isn't this adequate to determine that both assemblies MyApp.exe and MyApp.Utilities.dll were signed with the same snk file:
/* assembly MyApp.Utilities.dll */
public class Permission
{
private static Permission(){}
private static StrongName GetStrongName(Evidence evid)
{
foreach(object o in evid)
if (o is StrongName)
return o as StrongName;
return null;
}
public static bool Authorize(Evidence evid)
{
Assembly asm = typeof(Permission).Assembly;
StrongName snThis = GetStrongName(asm.Evidence);
if (snThis == null) return true;
if (evid == null) return false;
StrongName snCaller = GetStrongName(evid);
if (snCaller == null) return false;
if (snThis.PublicKey.ToString() == snCaller.PublicKey.ToString()) return true;
return false;
}
}
usage:
/*assembly MyApp.exe */
public void DoSecureProc()
{
if !MyApp.Utilities.Permissions.Authorize(this.GetType().Assembly.Evidence))
throw new System.Security.SecurityException("Unauthorized Execution");
/*do process here */
}
Suman Ray
thanks for the info!
I am assuming that this will be adequate as we wouldn't be using it to protect any proprietary info. We are looking at a giving our customers the ability to protect data. It would be up to them to prevent their users from executing 'privileged' code, correct