Yesterday a client of mine had an interesting challenge. He had a
sealed class which he needed to “unseal” due to some changes in his
project. However he needed to control who could inherit the class and
applied a StrongNameIdentityPermissionAttribute with an InheritanceDemand
action to the class. He soon learned that the XmlSerializer cannot
serialize types with declarative security. This is by design in the
.NET framework, since XML serialization is achieved through runtime
generated types for performance reasons. A common workaround is to
apply imperative security in lieu of declarative security. However,
since InheritanceDemand is a load time security assertion, this was not a feasible option for my client.
The solution to the challenge was to recreate the inheritance demand action in the class’ constructor as shown below.
public abstract class InheritanceDemandingClass
{
protected InheritanceDemandingClass()
{
byte[] myPK = typeof(InheritanceDemandingClass).Assembly.GetName().GetPublicKey();
byte[] callingPK = Assembly.GetCallingAssembly().GetName().GetPublicKey ();
if (callingPK==null || myPK.Length!=callingPK.Length)
{
throw new SecurityException("The calling assembly does not have permission to create this type.");
}
for (int i = 0; i < myPK.Length; i++)
{
if (myPK[i]!=callingPK[i])
{
throw new
SecurityException("The calling assembly does not have permission to
create this
type.");
}
}
}
}
The above code compares the calling assembly’s public key with the class’ public key and throws a SecurityException
if the two assemblies aren’t signed with the same key. This simple
solution should be sufficient for most scenarios, as the common usage
for inheritance demands is to ensure that only your types can extend
your types. However the example can easily be extended to support other
keys or public key tokens as well.
There are some differences with
this approach and using declarative security; the type can be reflected
since the security assertion happens at runtime, and you cannot use
permview.exe to see what demands the type makes. If imperative security
was applied you would still have both of these issues.