SECURITY

Programming .NET Security : Extending the .NET Framework (part 1) - Defining the AuthorMembershipCondition Class

8/4/2012 3:26:30 PM

1. Custom Membership Conditions Explained

To enable Author evidence to drive policy resolution, first you create a custom membership condition class. You can then use the custom membership condition in code groups to test the values of any Author evidence presented by an assembly or application domain. Here are the key requirements of a custom membership condition class:


Implement IMembershipCondition

Membership condition classes must implement the System.Security.Policy.IMembershipCondition interface, which extends both the System.Security.ISecurityPolicyEncodable and System.Security.ISecurityEncodeable interfaces. We summarize the members of each interface in Table 1.


Implement default constructor

Membership condition classes must implement a default (empty) constructor. The runtime uses this constructor when it needs to create a membership condition object from XML contained in the security policy files.


Make serializable

Membership condition classes must be serializable. Because of their simplicity, application of the System.SerializableAttribute is usually sufficient. Those membership condition classes that have more complex serialization requirements must implement the System.Runtime.Serialization.ISerializable interface.

Unless you implement ISerializable, deserialization of an object does not result in the execution of a constructor, and therefore you should not depend on constructor logic to configure or modify the state of the deserialized object.


Table 1. Members of the IMembershipCondition, ISecurityPolicyEncodable, and ISecurityEncodeable interfaces
Member Description
IMembershipCondition interface  
Check Determines whether an Evidence collection contains evidence that satisfies the membership criterion
Copy Returns a copy of the membership condition
Equals Tests a System.Object against the IMembershipCondition object
ToString Returns a System.String representation of the membership condition
ISecurityEncodable interface  
FromXml Reconstructs the IMembershipCondition object's state from a specified SecurityElement
ToXml Creates and returns a SecurityElement containing an XML object model representing the IMembershipCondition object's state
ISecurityPolicyEncodable  
FromXml The same as ISecurityEncodable.ToXml but handles any policy level-specific state
ToXml The same as ISecurityEncodable.FromXml but includes any policy level-specific state

In addition to these requirements. These include:

  • Make membership conditions simple. Membership conditions classes have access to the entire Evidence collection of an assembly or application domain in the Check method, and therefore it is possible to create custom membership conditions that test complex membership criteria spanning multiple items of evidence. You must consider who will use your membership condition class and design it appropriately. Creating membership classes that test multiple or complex sets of data can result in security policy that is difficult for security administrators and users to configure and understand.

  • Make membership conditions lightweight. You should consider the amount of memory used by your membership condition classes as well as avoid lengthy processing tasks, such as network, file, and database access during membership evaluation.

  • Make membership conditions noninheritable. It is safest to mark your membership condition classes as sealed in C# and NotInheritable in Visual Basic .NET so that malicious code cannot subclass them in an attempt to change its behavior and subvert CAS, or confuse security administrators.

  • Override Object.ToString. The security administration tools use ToString to display a message that describes the condition and value that a membership is configured to match against. The use of this information necessitates that the output be concise. For example, "Site = *.oreilly.com" or "Author = Peter."

2. Defining the AuthorMembershipCondition Class

Following the naming pattern used in the .NET class library, we name the membership condition class AuthorMembershipCondition. The AuthorMembershipCondition class is relatively simple; however, there is still a fair amount of code involved because we have to implement the eight members defined in the IMembershipCondition interface. We will break the AuthorMembershipCondition class into manageable sections for explanation.

The class declaration for AuthorMembershipCondition specifies that it is sealed (C#) and NotInheritable (Visual Basic .NET) to stop malicious code from subclassing it in order to subvert CAS. You should also specify the implementation of IMembershipCondition and annotate AuthorMembershipCondition with the System.Serializable attribute—satisfying the two major requirements of membership condition classes.

We define a single private System.String data member named AuthorName, which will contain the name of the author on which an AuthorMembershipCondition object will base its membership test:

# C#

using System;
using System.Security;
using System.Collections;
using System.Reflection;
using System.Security.Policy;

[assembly:AssemblyKeyFile("Keys.snk")]
[assembly:AssemblyVersion("1.0.0.0")]

namespace ORA.DotNetSecurity.Policy {

    [Serializable]
    public sealed class AuthorMembershipCondition : IMembershipCondition {
    
        private string AuthorName = "";


# Visual Basic .NET

Imports System
Imports System.Security
Imports System.Collections
Imports System.Reflection
Imports System.Security.Policy

<assembly:AssemblyKeyFile("Keys.snk")>
<assembly:AssemblyVersion("1.0.0.0")> 
 
Namespace ORA.DotNetSecurity.Policy
 
    <Serializable> _ 
    Public NotInheritable Class AuthorMembershipCondition
         Implements IMembershipCondition
 
        Private AuthorName As String =  ""

					  

We define two constructors for AuthorMembershipCondition. The first is a default (empty) constructor. The runtime uses this constructor to create AuthorMembershipCondition objects before calling the FromXml method to recreate the state of an AuthorMembershipCondition from XML stored in the policy configuration files. The second constructor is for general use and takes a System.String argument containing the name of the author on which the AuthorMembershipCondition should base its membership test:

# C#

        public AuthorMembershipCondition(  ) {        
        
                this.AuthorName = "";
        }
        
        public AuthorMembershipCondition(string author) {
        
            if (VerifyAuthorName(author)) {            
                this.AuthorName = author;
            }
        }


# Visual Basic.NET

        Public  Sub New(  ) 
                Me.AuthorName = ""
        End Sub
 
        Public  Sub New(ByVal author As String) 
            If VerifyAuthorName(author) Then
                Me.AuthorName = author
            End If
        End Sub

					  

We include a Name property to provide controlled access to the private AuthorName data member and the private VerifyAuthorName utility method, which we use in both the Name property and class constructor to validate the author name provided. To simplify AuthorMembershipCondition you check only if the author name is null (C#) or Nothing (Visual Basic .NET)—in which case, you throw a System.ArgumentNullException. In a production-quality membership condition class, it is good practice to verify the condition data more thoroughly and throw a System.ArgumentException if the data is invalid. For example, it would be a good idea to check for invalid characters and limit the size of the name provided:

  # C#

        // Property to get/set the author name
        public string Name {        
        
            get { 
                return AuthorName;
            }
            
            set {        
                if (VerifyAuthorName(value)) {            
                    this.AuthorName = value;
                }
            }
        }        
        
        // Utility method to verify that the author name
        // is not null.
        private bool VerifyAuthorName(string author) {
        
            if (author == null) {        
                throw new ArgumentNullException("author");
            } else {
                return true;
            }
        }


# Visual Basic .NET

        ' Property to get/set the author name
        Public Property Name(  ) As String
                Get 
                Return AuthorName
                End Get
                Set (ByVal Value As String) 
                If VerifyAuthorName(Value) Then
                    Me.AuthorName = Value
                End If
                End Set
        End Property
 
        ' Utility method to verify that the author name
        ' is not null.
        Private Function VerifyAuthorName(ByVal author As String) _
            As Boolean
 
            If author Is Nothing Then
                Throw New ArgumentNullException("author")
            Else 
                Return True
            End If
        End Function

					  

The real work of the AuthorMembershipCondition class takes place in the Check method. The Check method takes an Evidence collection and enumerates the contained evidence objects to determine if any of them are Author objects. If Check finds an Author object, it compares the Author.Name property with its own private AuthorName data member. If the two names match, Check returns true; otherwise, Check returns false.

For simplicity, we have implemented a straightforward case-sensitive string comparison, but you might also consider support for non-case-sensitive comparisons and wildcard matches. The membership condition logic can be arbitrarily complex, but remember that the runtime may call Check many times during policy resolution, and time-consuming membership condition evaluations will affect application performance:

# C#

        // Determines whether the Evidence meets the membership 
        // condition.
        public bool Check( Evidence evidence ) {
        
                // Return false if the Evidence is null
            if (evidence == null) {
                return false;
            }
        
            Author auth = null;
    
            // Enumerate across the host and assembly evidence
            // collections.
            IEnumerator enumerator = evidence.GetEnumerator(  );
            while (enumerator.MoveNext(  ))
            {            
                auth = enumerator.Current as Author;
                
                // If the evidence is of type Author and the 
                // author names match, the evidence meets the
                // membership condition.
                if (auth != null) {        
                    if (auth.Name == this.AuthorName) {
                        return true;
                    }
                }
            }
            return false;
        }


# Visual Basic .NET

        ' Determines whether the Evidence meets the membership 
        ' condition.
        Public Function Check(ByVal evidence As Evidence) As Boolean _
            Implements IMembershipCondition.Check
 
                ' Return false if the Evidence is Nothing
            If evidence Is Nothing Then
                Return False
            End If
 
            Dim auth As Author =  Nothing 
 
            ' Enumerate across the host and assembly evidence
            ' collections.
            Dim enumerator As IEnumerator =  evidence.GetEnumerator(  ) 
            While enumerator.MoveNext(  )

                auth = CType(enumerator.Current, Author)
 
                ' If the evidence is of type Author and the 
                ' author names match, the evidence meets the
                ' membership condition.
                If Not auth Is Nothing Then
                    If auth.Name = Me.AuthorName Then
                        Return True
                    End If
                End If
            End While

            Return False
        End Function

					  

The remaining members of the IMembershipCondition interface are straightforward. The Copy method returns a clone of the current AuthorMembershipCondition object, and the Equals method compares two AuthorMembershipCondition objects for equality based on the value of their private AuthorName data members instead of comparing object references. Because Object also defines an Equals method, you must override it with the one defined in the IMembershipCondition interface. As a result, you must also override the GetHashCode method:

# C#

        // Creates a copy of the membership condition
        public IMembershipCondition Copy(  ) {
        
            return new AuthorMembershipCondition(this.AuthorName);
        }
    
        // Compares an object for equality based on the author's
        // name, not the object reference.
        public override bool Equals(object obj) {
        
            AuthorMembershipCondition that = 
                (obj as AuthorMembershipCondition);
            
            if (that != null) {                  
                if (this.AuthorName == that.AuthorName) {
                    return true;
                }
            }
            return false;
        }

        // We must override GetHashCode because we override 
        // Object.Equals. Returns a hash code based on the 
        // author's name.
        public override int GetHashCode(  ) {
        
            return this.AuthorName.GetHashCode(  );
        }


# Visual Basic .NET

        ' Creates a copy of the membership condition
        Public Function Copy(  ) As IMembershipCondition _
            Implements IMembershipCondition.Copy
 
            Return New AuthorMembershipCondition(Me.AuthorName)
        End Function
 
        ' Compares an object for equality based on the author's
        ' name, not the object reference.
        Public Overloads Function Equals(ByVal obj As Object) As Boolean _
            Implements IMembershipCondition.Equals

            Dim that As AuthorMembershipCondition = _
                CType(obj,AuthorMembershipCondition)
 
            If Not that Is Nothing Then
                If Me.AuthorName = that.AuthorName Then
                    Return True
                End If
            End If
            Return False
        End Function

        ' We must override GetHashCode because we override 
        ' Object.Equals. Returns a hash code based on the 
        ' author's name.
        Public Overrides Function GetHashCode(  ) As Integer
 
            Return Me.AuthorName.GetHashCode(  )
        End Function

					  

All of the standard membership condition classes override Object.ToString to return a simple human-readable representation of the membership condition they define. The administration tools display this information, and it should be relatively concise. For consistency, we take the same approach:

# C#
    
        // Returns a simple string representation of the 
        // membership condition
        public override string ToString(  ) {
        
                return "Author - " + AuthorName;
        }    


# Visual Basic .NET

        ' Returns a simple string representation of the 
        ' membership condition
        Public Overrides Function ToString(  ) As String _
            Implements IMembershipCondition.ToString

                Return "Author - " & AuthorName
        End Function

Both the ISecurityEncodable and ISecurityPolicyEncodable interfaces define a ToXml method that returns a System.Security.SecurityElement containing an XML object model of the AuthorMembershipCondition object. The AuthorMembershipCondition class does not differentiate between different policy levels and therefore implements both methods the same.

Most importantly, the root XML element must be "IMembershipCondition" or the administrative tools will not be able to import the XML describing the custom membership condition. The XML representation of all standard membership condition classes includes a version attribute that represents the XML format used to represent the membership condition. We have taken the same approach, which gives flexibility should future versions of the AuthorMembershipCondition class require a different structure:

# C#

        // Return a SecurityElement containing an XML object
        // model representing the membership condition.
        public SecurityElement ToXml(  ) {
        
            return this.ToXml(null);
        }
    
        // Return a SecurityElement containing an XML object
        // model representing the membership condition. We have 
        // no need to differentiate between policy levels and so 
        // we ignore the "level" argument.
        public SecurityElement ToXml(PolicyLevel level) {
        
            // Create a new "IMembershipCondition" element
            SecurityElement se =
                new SecurityElement("IMembershipCondition");
        
            // Add fully qualified type name for membership condition
            se.AddAttribute(
                "class", 
                this.GetType(  ).AssemblyQualifiedName
            );
        
            // Add an XML version number of "1"
            se.AddAttribute("version", "1");
        
            // Add the author name
            se.AddAttribute("name", AuthorName);
           
            // Return the new SecurityElement
            return se;
        }


# Visual Basic .NET

        ' Return a SecurityElement containing an XML object
        ' model representing the membership condition.
        Public Function ToXml(  ) As SecurityElement _
            Implements ISecurityEncodable.ToXml

            Return Me.ToXml(Nothing)
        End Function
 
        ' Return a SecurityElement containing an XML object
        ' model representing the membership condition. We have 
        ' no need to differentiate between policy levels and so 
        ' we ignore the "level" argument.
        Public Function ToXml(ByVal level As PolicyLevel) _ 
            As SecurityElement Implements ISecurityPolicyEncodable.ToXml
 
            ' Create a new "IMembershipCondition" element
            Dim se As SecurityElement = _
                New SecurityElement("IMembershipCondition")
 
            ' Add fully qualified type name for membership condition
            se.AddAttribute( _
                "class", _
                Me.GetType(  ).AssemblyQualifiedName _
            )
 
            ' Add an XML version number of "1"
            se.AddAttribute("version", "1")
 
            ' Add the author name
            se.AddAttribute("name", AuthorName)
 
            ' Return the new SecurityElement
            Return se
        End Function

					  

The reverse of the ToXml method is FromXml, which takes a SecuirtyElement and reconstructs the object state. As with ToXml, both the ISecurityEncodable and ISecurityPolicyEncodable interfaces define a FromXml method. Again, you implement both methods the same, because you do not need to perform policy level-specific state configuration:

# C#

        // Reconstruct the state of the membership condition 
        // object from the SecurityElement provided. 
        // fromExtract state from a SecurityElement
        public void FromXml(SecurityElement e) {
        
            this.FromXml(e, null);
        }
    
        // Reconstruct the state of the membership condition 
        // object from the SecurityElement provided. We have 
        // no need to differentiate between policy levels and so 
        // we ignore the "level" argument. 
        public void FromXml(SecurityElement e, PolicyLevel level) {
        
            // Ensure we have a SecurityElement to work with
            if (e == null) throw new ArgumentNullException("e");
            
            // Ensure the SecurityElement is an AuthorMembershipCondition
            if (e.Tag != "IMembershipCondition") {
                throw new ArgumentException
                    ("Element must be IMembershipCondition");
            } else {
                // Extract the author name from the SecurityElement
                this.AuthorName = e.Attribute("name");
            }
        }
    }   
}


# Visual Basic .NET              

        ' Reconstruct the state of the membership condition 
        ' object from the SecurityElement provided. 
        ' fromExtract state from a SecurityElement
        Public  Sub FromXml(ByVal e As SecurityElement) _
            Implements ISecurityEncodable.FromXml
 
            Me.FromXml(e, Nothing)
        End Sub

        ' Reconstruct the state of the membership condition 
        ' object from the SecurityElement provided. We have 
        ' no need to differentiate between policy levels and so 
        ' we ignore the "level" argument. 
        Public  Sub FromXml(ByVal e As SecurityElement, _
            ByVal level As PolicyLevel) _
            Implements ISecurityPolicyEncodable.FromXml
 
            ' Ensure we have a SecurityElement to work with
            If e Is Nothing Then
                     Throw New ArgumentNullException("e")
            End If
 
            ' Ensure the SecurityElement is an AuthorMembershipCondition
            If e.Tag <> "IMembershipCondition" Then
                Throw New ArgumentException _
                    ("Element must be IMembershipCondition")
            Else 
                ' Extract the author name from the SecurityElement
                Me.AuthorName = e.Attribute("name")
            End If
        End Sub
    End Class
End Namespace
Other  
 
Video tutorials
- How To Install Windows 8 On VMware Workstation 9

- How To Install Windows 8

- How To Install Windows Server 2012

- How To Disable Windows 8 Metro UI

- How To Change Account Picture In Windows 8

- How To Unlock Administrator Account in Windows 8

- How To Restart, Log Off And Shutdown Windows 8

- How To Login To Skype Using A Microsoft Account

- How To Enable Aero Glass Effect In Windows 8

- How To Disable Windows Update in Windows 8

- How To Disable Windows 8 Metro UI

- How To Add Widgets To Windows 8 Lock Screen
programming4us programming4us
Top 10
Free Mobile And Desktop Apps For Accessing Restricted Websites
MASERATI QUATTROPORTE; DIESEL : Lure of Italian limos
TOYOTA CAMRY 2; 2.5 : Camry now more comely
KIA SORENTO 2.2CRDi : Fuel-sipping slugger
How To Setup, Password Protect & Encrypt Wireless Internet Connection
Emulate And Run iPad Apps On Windows, Mac OS X & Linux With iPadian
Backup & Restore Game Progress From Any Game With SaveGameProgress
Generate A Facebook Timeline Cover Using A Free App
New App for Women ‘Remix’ Offers Fashion Advice & Style Tips
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th