A link demand differs from a regular permission demand in that the run-time demands permissions only from the immediate caller and does not perform a full stack walk. Link demands are performed at JIT compilation time and can only be specified declaratively .
Carefully consider before using a link demand because it is easy to introduce security vulnerabilities if you use them. If you do use link demands, consider the following issues:
Luring attacks
Performance and link demands
Calling methods with link demands
Mixing class and method level link demands
Interfaces and link demands
Structures and link demands
Virtual methods and link demands
If you protect code with a link demand, it is vulnerable to luring attacks, where malicious code gains access to the resource or operation exposed by your code through a trusted intermediary as shown in Figure 8.5.
In figure 8.5, methods in assembly X, which access a secure resource, are protected with a link demand for a specific public key (using a StrongNameIdentityPermission ). Assemblies A, B, and C are signed with the private key that corresponds to the public key that assembly X trusts, and so these assemblies can call assembly X. Assemblies A, B, and C are subject to a luring attack if they do not check their callers for specific evidence before making calls to assembly X. For example, assembly D that is not signed with the same private key cannot call assembly X directly. It could, however, access assembly X through the trusted assembly A, if A does not check its callers , either with another link demand or through a full demand.
Only use link demands in an assembly when you trust the assembly's callers not to expose its functionality further (for example, when the caller is an application, not a library) or when you know it is safe just to verify the immediate caller's identity with an identity permission demand.
Compared to other Web application performance issues such as network latency and database access, the cost of a stack walk is small. Do not use link demands purely for performance reasons. Full demands provide a much greater degree of security.
If you call a link demand protected method, only your code will be checked by the link demand. In this situation, you should make sure your code takes adequate measures to authorize its callers, for example, by demanding a permission.
Method level link demands override class level link demands. For example, in the following code fragment, the link demand for FileIOPermission must be repeated on the method declaration or the EnvironmentPermission link demand replaces the class level FileIOPermission demand.
[FileIOPermission(SecurityAction.LinkDemand, Unrestricted=true)] public sealed class SomeClass { // The unrestricted FileIOPermission link demand must be restated at the // method level, if the method is decorated with another link demand. // Failure to do so means that (in this example) that the // EnvironmentPermission link demand would override the class level // FileIOPermission link demand [FileIOPermission(SecurityAction.LinkDemand, Unrestricted=true)] [EnvironmentPermission(SecurityAction.LinkDemand, Read="PATH")] public void SomeMethod() { } }
If your class implements an interface and one of the method implementations has a link demand, make sure that the method declaration on the interface definition has the same link demand. Otherwise, the caller simply has to call your method through the interface to bypass the link demand. An example is shown below.
public interface IMyInterface { // The link demand shown on the method implementation below // should be repeated here void Method1(); } public class MyImplementation : IMyInterface { // The method implementation has a link demand but the interface does not [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.ControlPrincipal)] public void Method1() { } }
With the following code, the caller is subject to the link demand:
MyImplementation t = new MyImplementation(); t.Method1();
With the following code, the caller is not subject to the link demand:
IMyInterface i = new MyImplementation(); i.Method1();
Link demands do not prevent the construction of structures by untrusted callers. This is because default constructors are not automatically generated for structures. Therefore, the structure level link demand only applies if you use an explicit constructor.
For example:
[SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.ControlPrincipal)] public struct SomeStruct { // This explicit constructor is protected by the link demand public SomeStruct(int i) { field = i; } private int field; }
The following two lines of code both result in a new structure with the field initialized to zero. However, only the first line that uses the explicit constructor is subject to a link demand.
SomeStruct s = new SomeStruct(0); SomeStruct s = new SomeStruct();
The second line is not subject to a link demand because a default constructor is not generated. If this were a class instead of a structure, the compiler would generate a default constructor annotated with the specified link demand.
If you use link demand to protect a method override in a derived class, make sure you also put it on the corresponding virtual base class method. Otherwise, if the JIT compiler sees a reference to the base class type where no link demand is present, no link demand is performed.