HTML clipboardChoosing Imperative or Declarative Security
Declarative security is simpler to implement than imperative security.
Declarative security attributes can be viewed with Permview.exe or mscorcfg.msc,
allowing the callers of code to see what permissions the code requires.
Imperative security is not evident to the callers of code. Because the
permissions requirements are embedded inside the code, you cannot see what is
happening unless coding a demand.
In some cases the choice between declarative and imperative security is obvious
because some security actions can be performed in only one of the two ways. For
example, minimum, optional, and refused permission requests are only available
declaratively.
But how do you choose which approach to use when both approaches provide
equivalent support for the functions you need? If a security action can be
performed both declaratively and imperatively, the decision depends on the
developer's preference. The performance difference between the two is
insignificant, for the most part, however, you can would have to choose
imperative syntax over declarative syntax when you are going to construct the
initial permission state of security in your code with information that is only
available at run time.
A declarative demand is a way of invoking a security check without adding any
statements to your code. You make a declarative demand by placing information at
the class or member level, indicating the permissions you want callers to have.
You can also implement Deny actions declaratively. If you place a declarative
security check at the class level, it applies to each class member, including
methods, properties, and fields. If you place a declarative security check at
the member level, it applies to only that member and overrides any permission
specified at the class level. Declarative demands degrade performance only at
JIT compilation. In fact, the use of declarative demands can actually increase
the performance of an application in which a demand is made many times.
The imperative demand that you place in your code protects all of the remaining
code in the method from which the Demand method is called. The security check is
performed when the Demand method executes; if the security check fails, a
security exception is thrown and the rest of the code in that method or member
is not executed unless the exception is caught and handled. Consider using an
imperative (rather than declarative) demand when information that you need to
specify permission becomes known only at runtime.
Identity Permissions
When an assembly is requested, the CLR searches for evidence of the assembly's
origin. In simple terms, the CLR asks the following questions:
-
From which site does the assembly come?
-
From which URL does the assembly come?
-
From which zone does the assembly come?
-
Who has signed the assembly?
-
What is the strong (public/private key–signed assembly) name of the assembly?
Based on the evidence it collects, the CLR
learns the identity of the assembly and assigns the appropriate identity
permissions. These identity permissions "earn" an assembly its membership to a
code group. Developers and administrators do not have influence over the
identity permissions of an assembly. The CLR just takes a requested assembly,
examines its evidence, and assigns the identity permissions based on that
evidence. To associate a set of identity permissions with a code group, the
administrator must set up security policies.
Some of the identity permission classes in the framework are
-
SiteIdentityPermission, which represents the Web site from which the assembly originated;
-
URLIdentityPermission, which represents the URL from which the assembly originated;
-
ZoneIdentityPermission, which represents the security zone from which the assembly originated. The zone identity is one of the values of the System.Security.SecurityZone enumeration.
-
PublisherIdentityPermission, which represents the Authenticode publisher of the assembly; and
-
StrongNameIdentityPermission, which represents the strong name of the assembly.
Even if identity permissions can be demanded,
they are granted only if an assembly can show evidence of the proper identity.
This also holds true for code access permissions. Identity and code access
permissions are very closely related in that they share the same underlying
concept and derive from the same base class, CodeAccessSecurity.
Link Demands
Link demands, the permissions a caller must have when calling code, can be used
to limit which classes can be linked to your classes. You must set link demands
declaratively because they can be evaluated at JIT compilation time by the
system and performed against the caller of the code. If the caller does not
possess enough permission to satisfy the link demand, the system throws an
exception. The CLR does not perform a stack walk for link demands, so you can
avoid the potential impact on performance.
Link demands can be associated with identity permissions to control who or what
can call your code. For example, you can develop assemblies that can be called
only by other assemblies from a specific publisher.
Listing 22.6 illustrates how you can implement LinkDemand declarative security.
Listing 22.6 -LinkDemand Illustration
'
code to restrict callers
<ZoneIdentityPermission(SecurityAction.LinkDemand, Zone:=SecurityZone.MyComputer)>
_
Public Class test
'some
code
End Class
Inheritance Demands
Inheritance demands are similar to link demands except that they are used to
restrict how entities inherit characteristics at the class level. For example,
you can place inheritance demands declaratively at the class level to ensure
that only code with the specified permission can inherit from your class. You
can place inheritance demands on methods to ensure that any code that overloads
the method has the specified permission to do so.
Listing 22.7 illustrates how you can implement class-level InheritanceDemand
declarative security.
Listing 22.7 -InheritanceDemand Illustration
' code to restrict subclassing
<StrongNameIdentityPermission(SecurityAction.InheritanceDemand, PublicKey:={........})>
public class test2
//
Some code
End
Class
Role-Based Permissions
You know now how the CLR controls the permissions of your code. Now it's time to
explore how you can control the rights of a user.
Every role you have -whether parent or child, shopper or billpayer, developer or
administrator - has certain behaviors and responsibilities associated with it.
Security designers have recognized how useful this concept of role-associated
behaviors can be in IT and have designed a security check that grants
permissions based on roles.
When you write a software system, the design phase usually reveals certain roles
that users play based upon actual workflow. Role-based security allows the
developer to check whether a user is functioning within a certain role when
requesting access to resources.
Unlike identity permissions and code access permissions, role-based permissions
have nothing to do with the rights a piece of code possesses but rather with the
workflow-based permission of a user. The term workflow-based permission implies
a sequence of steps or hierarchical permissions that colleagues require to see a
task through to completion. For example, a bellhop with no permissions takes a
guest's bags to a hotel room designated by a desk clerk with specific
permissions. A housekeeper with very few permissions freshens the room; and at
checkout, the desk manager's more extensive permissions are required to remove
unauthorized charges from the guest's bill and to discount the room rate.
Role-based permissions are not derived from the CodeAccessPermission class, as
identity permissions and code access permissions are. Instead they share the
same base class with the common principal-based (also known as Windows identity)
permissions; both are derived from the PrincipalPermission class. To understand
role-based permissions, we must look at two other classes: Identity and
Principal.
The Identity class represents users in a software or operating system. In
contrast, the Principal class represents the security context (Windows user
group) of a user (Windows identity. Basically, Principal represents all the
roles to which a user is assigned. A PrincipalPermission is the object used to
demand a role from a user. If the user belongs to the necessary Principal class
(i.e., if the user has been assigned the requisite roles), the request succeeds.
PrincipalPermission is therefore an easy way to check role assignments.
We have seen the different security concepts related to a specified software
system. Yet, that software system is embedded in the operating system and the
.NET runtime host, so there must be other permissions that manage your rights to
control the runtime.
Security Permissions
All permissions related to the runtime environment and the controlling of it are
represented through the SecurityPermission class found in the
System.Security.Permissions namespace. With this class, you can request runtime
environment permissions.
The class takes a SecurityPermissionFlag enumeration in its constructor. This
enumeration contains an item called Assertion, which is responsible for trying
to execute the assertion for permission. If an assembly does not possess
Assertion rights, it is not possible to call the Assert method to assert
specific permissions and therefore you cannot disable the stack walk of the code
access permissions.
Treat with extreme caution any permissions represented by SecurityPermission
objects. If you assign rights through this enumeration, be sure you know what
the code does and whether it really needs these rights. If you obtain code over
the Internet or from other uncontrollable sources, never assign it permissions
if you don't know what the code contains.
Exceptions
In
VB.NET, any security violation throws one of three exception types -security,
policy, or verification -which can be caught and handled appropriately by
exception-handling routines. An object is created to represent exceptions as
they occur. All three security-related exceptions that follow inherit from Object.Exception.SystemException.
-
SecurityException is thrown when a security violation is detected, typically at runtime.
-
PolicyException is thrown when policy forbids code to run. This exception, which usually occurs as the code is loading, is thrown when the code requests more permission than the policy will grant or the policy is configured to prohibit running the code.
-
VerificationException can occur either when code that is verifiable does not pass verification rules or when code that is not verifiable is run without SkipVerify permissions enabled for that particular zone, such as the intranet zone. Verification includes memory allocations, proper casting of variables, and type safety. Code can be verified during JIT compilation because it contains nothing but MSIL statements. However, code in which SkipVerify permission is set is omitted.
Conclusion
Hope this
article would have helped you in understanding how to Choosing Security and
Role-Based Permissions in VB.NET.