X509LogoTypeExtension.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / X509LogoTypeExtension.cs / 1 / X509LogoTypeExtension.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.IO; 
    using System.Text; 
    using System.Diagnostics;
    using System.Collections.Generic; 
    using System.Security.Cryptography;
    using System.Runtime.InteropServices;
    using System.Security.Cryptography.X509Certificates;
    using System.Globalization; 
    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace;
 
    // 
    // Summary:
    // Extension supporting the encoding and decoding of the X509 
    // logotype extension (1.3.6.1.5.5.7.1.12) specified by RFC 3709.
    //    { iso(1) identified-organization(3) dod(6) internet(1)
    //      security(5) mechanisms(5) pkix(7) id-pe(1) 12 }
    // 
    internal sealed class X509LogoTypeExtension : X509Extension
    { 
        List  m_logos = new List(); 
        bool            m_decodePathComplete;
 
        const string szOID_LOGO_TYPES   = "1.3.6.1.5.5.7.1.12";
        const byte OctetStringTag       = 0x04;
        const byte ObjectIdentifierTag  = 0x06;
        const byte StringTag            = 0x16; 
        const byte SequenceTag          = 0x30;
        const byte DirectTag            = 0xa0; 
        const byte IndirectTag          = 0xa1; 
        const byte AudioLogoTypeDataTag = 0xa1;
 
        public List Logos
        {
            get
            { 
                IDT.DebugAssert( m_decodePathComplete, "Extension must be decoded before accessing this property" );
                return m_logos; 
            } 
        }
 
        public void TryDecodeExtension()
        {
            try
            { 
                DecodeExtension();
            } 
#pragma warning disable 56500       // do not catch non-recoverable exceptions 

            catch ( Exception e ) 
            {
                if( IDT.IsFatal( e ) )
                {
                    InfoCardService.Crash( e ); 
                }
                // 
                // All other exceptions, including LogoValidationExceptions should be recoverable 
                //
                IDT.TraceDebug( "X509LogoClient: Error found decoding extension:\n{0}", e.Message ); 
                IDT.TraceAndLogException( e );
            }
#pragma warning restore 56500       // do not catch non-recoverable exceptions
 
            //
            // Indicates that we've at least tried decoding the extension. 
            // After this is set, the Logos property can be safely accessed. 
            //
            m_decodePathComplete = true; 

        }

 
        //
        // Summary: 
        // Constructs the extension using the rawdata from the certificate 
        //
        public X509LogoTypeExtension( byte[] rawData ) 
            : base( szOID_LOGO_TYPES, rawData, false )
        {}

        public static X509LogoTypeExtension FromCertificate( X509Certificate2 certificate ) 
        {
            if( null == certificate.Extensions || null == certificate.Extensions[ szOID_LOGO_TYPES ] ) 
            { 
                return null;
            } 

            return new X509LogoTypeExtension( certificate.Extensions[ szOID_LOGO_TYPES ].RawData );
        }
 
        //
        // Summary: 
        // Gets the byte information from an AsnEncodedData object. 
        // and resets the decoded flag.
        // 
        // Parameters:
        // asnEncodedData - raw ASN.1 data.
        //
        public override void CopyFrom( AsnEncodedData asnEncodedData ) 
        {
            base.CopyFrom( asnEncodedData ); 
 
            //
            // This is not a critical extension 
            //
            base.Critical = false;

            // 
            // We've not decoded this yet, so cannot access the Logos property.
            // Set a flag for this. 
            // 
            m_decodePathComplete = false;
        } 

        //
        // Summary:
        // Builds a string containing human readable and hexadecimal representations 
        // of the extension information.
        // 
        // Returns: 
        // A string with the following shape
        // X509 Logotype Extension( 1.3.6.1.5.5.7.1.12 ) 
        //    30 81 be a1 5d a0 5b 30   0..�]�[0
        //    59 30 57 30 55 16 09 69   Y0W0U..i
        //    6d 61 67 65 2f 67 69 66   mage/gif
        //    30 21 30 1f 30 07 06 05   0!0.0... 
        //    2b 0e 03 02 1a 04 14 8f   ........
        //    e5 d3 1a 86 ac 8d 8e 6b   �O.....k 
        //    ... 
        //    d3 1a 86 ac 8d 8e 6b c3   O.....kA
        //    cf 80 6a d4 48 18 2c 7b   I.jOH.,{ 
        //    19 2e 30 25 16 23 68 74   ..0%.#ht
        //    74 70 3a 2f 2f 6c 6f 67   tp://log
        //    6f 2e 76 65 72 69 73 69   o.verisi
        //    67 6e 2e 63 6f 6d 2f 76   gn.com/v 
        //    73 6c 6f 67 6f 2e 67 69   slogo.gi
        //    66                        f 
        // 
        //    LogoType:       Issuer
        //    MediaType:      image/gif 
        //    Location(s):    http://logo.verisign.com/vslogo.gif
        //
        //    Hash(es)
        // 
        //    Name:   sha1
        //    Oid:    1.3.14.3.2.26 
        //    Bytes: 
        //    8f e5 d3 1a 86 ac 8d 8e   .�O.....
        //    6b c3 cf 80 6a d4 48 18   kAI.jOH. 
        //    2c 7b 19 2e               ,{..
        //
        public override string ToString()
        { 
#if DEBUG
            StringBuilder sb = new StringBuilder(); 
            sb.AppendFormat( "X509 Logotype Extension( {0} )\n", szOID_LOGO_TYPES ); 

            sb.Append( Asn1Utilities.ToHexDump( RawData ) ); 
            sb.Append( '\n' );

            foreach( X509Logo logo in Logos )
            { 
                sb.Append( logo.ToString() );
                sb.Append( "\n" ); 
            } 

            return sb.ToString(); 
#else
            return base.ToString();
#endif
        } 

        // 
        // Summary: 
        // Takes the populated members and writes them out to the RawData member.
        // 
        private void DecodeExtension()
        {
            BinaryReader br = new InfoCardBinaryReader( new MemoryStream( RawData ) );
            ASCIIEncoding ascii = new ASCIIEncoding(); 

            // 
            // Read LogoTypeExtn sequence tag 
            //
            // LogotypeExtn ::= SEQUENCE { 
            //       communityLogos  [0] EXPLICIT SEQUENCE OF LogotypeInfo OPTIONAL,
            //       issuerLogo      [1] EXPLICIT LogotypeInfo OPTIONAL,
            //       subjectLogo     [2] EXPLICIT LogotypeInfo OPTIONAL,
            //       otherLogos      [3] EXPLICIT SEQUENCE OF OtherLogotypeInfo OPTIONAL } 
            //
            VerifyByte( br.ReadByte(), SequenceTag ); 
            ReadAsnByteLength( br ); 

            while( !ReachedEndPosition( br.BaseStream.Position, br.BaseStream.Length ) ) 
            {
                bool isImage;
                string mediaType;
                Dictionary hashes = new Dictionary(); 
                List fileLocations = new List();
                bool isDirect; 
 
                //
                // Read Logo Type 
                //
                X509LogoType logoType = (X509LogoType) br.ReadByte();

                long logoTypeStartPosition = br.BaseStream.Position; 
                long logoTypeLength = ReadAsnByteLength( br );
                long logoTypeEndPosition = br.BaseStream.Position + logoTypeLength; 
 
                IDT.TraceDebug( "X509LogoClient: Logo parsing details: start={0},length={1},end={2}",
                        logoTypeStartPosition, logoTypeLength, logoTypeEndPosition ); 

                if( X509LogoType.Subject != logoType && X509LogoType.Issuer != logoType )
                {
                    // 
                    // See 39977, need to process logo extensions that have Other/Community logos
                    // Current code simply throws. 
                    // 
                    throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoUnsupportedType ) ) );
 
                    // OtherLogotypeInfo ::= SEQUENCE {
                    //      logotypeType    OBJECT IDENTIFIER,
                    //      info            LogotypeInfo }
                    // 
                    // otherLogoOid = ReadObjectIdentifier( br );
                } 
 
                //
                // Read Direct/Indirect 
                //
                // LogotypeInfo ::= CHOICE {
                //      direct          [0] LogotypeData,
                //      indirect        [1] LogotypeReference } 
                //
                byte b = br.ReadByte(); 
                VerifyByte( b, new byte[] { DirectTag, IndirectTag } ); 
                isDirect = ( DirectTag == b );
                ReadAsnByteLength( br ); 

                if( IndirectTag == b )
                {
                    // 
                    // See 39977, process logo extensions that use an indirect references to logos.
                    // Current code simply throws. 
                    // 
                    throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoUnsupportedIndirectReferences ) ) );
 
                    // Process InDirect to get a LogoTypeData structure
                    //
                    // LogotypeReference ::= SEQUENCE {
                    //      refStructHash   SEQUENCE SIZE (1..MAX) OF HashAlgAndValue, 
                    //      refStructURI    SEQUENCE SIZE (1..MAX) OF IA5String }
                    // 
                    // 
                    // Replace the existing byte[], stream and BinaryReader with
                    // new LogotypeData structure for further processing 
                    //
                }

                // 
                // Read LogotypeData Sequence Tag
                // 
                // LogotypeData ::= SEQUENCE { 
                //      image           SEQUENCE OF LogotypeImage OPTIONAL,
                //      audio           [1] SEQUENCE OF LogotypeAudio OPTIONAL } 
                //
                VerifyByte( br.ReadByte(), SequenceTag );
                ReadAsnByteLength( br );
 
                //
                // Read LogoType Image/Audio Sequence Tag 
                // The only difference between audio and image 
                // is that AudioLogoTypeDataTag (which is 0xa1) is stuck in before the sequence tag (0x30)
                // 
                b = br.ReadByte();
                if( AudioLogoTypeDataTag == b )
                {
                    isImage = false; 
                    IDT.TraceAndLogException( new LogoValidationException( SR.GetString( SR.LogoUnsupportedAudio )  ) );
 
                    // 
                    // A [1] indicates audio context
                    // Process LogoTypeAudio Sequence Tag 
                    //
                    VerifyByte( br.ReadByte(), SequenceTag );
                }
                else 
                {
                    isImage = true; 
                    VerifyByte( b, SequenceTag ); 
                }
 
                ReadAsnByteLength( br );

                //
                // Process the content LogotypeDetails (imageDetails or audioDetails) 
                //
                // LogotypeImage ::= SEQUENCE { 
                //   imageDetails    LogotypeDetails, 
                //   imageInfo       LogotypeImageInfo OPTIONAL }
                // 
                // LogotypeAudio ::= SEQUENCE {
                //   audioDetails    LogotypeDetails,
                //   audioInfo       LogotypeAudioInfo OPTIONAL }
                // 
                VerifyByte( br.ReadByte(), SequenceTag );
                ReadAsnByteLength( br ); 
 
                //
                // LogotypeDetails ::= SEQUENCE { 
                //          mediaType       IA5String, -- MIME media type name and optional
                //                                     -- parameters
                //          logotypeHash    SEQUENCE SIZE (1..MAX) OF HashAlgAndValue,
                //          logotypeURI     SEQUENCE SIZE (1..MAX) OF IA5String } 
                //
                VerifyByte( br.ReadByte(), StringTag ); 
                Int32 length = ReadAsnByteLength( br ); 

                // 
                // Read the media type using the ASCII encoding
                //
                mediaType = ascii.GetString( br.ReadBytes( (int) length ) );
 
                //
                // Read the Hash Algorithm and Value 
                // 
                // HashAlgAndValue ::= SEQUENCE {
                //      hashAlg         AlgorithmIdentifier, 
                //      hashValue       OCTET STRING }
                //

                // 
                // Read the sequence for logotypeHash field
                // 
                VerifyByte( br.ReadByte(), SequenceTag ); 

                // 
                // Length of LogoTypeHash
                //

                length = ReadAsnByteLength( br ); 

                // 
                // Make sure to take the stream position after processing the length 
                //
                long logoTypeHashEnd = br.BaseStream.Position + length; 

                while( !ReachedEndPosition( br.BaseStream.Position, logoTypeHashEnd ) )
                {
                    // 
                    // Read the sequence for each item in the collection of HashAlgAndValue(s)
                    // 
                    VerifyByte( br.ReadByte(), SequenceTag ); 

                    // 
                    // Length of HashAlgAndValue:
                    //

                    length = ReadAsnByteLength( br ); 

                    // 
                    // Read the sequence for the Algorithm 
                    //
                    // 
                    //  AlgorithmIdentifier  ::=  SEQUENCE  {
                    //  algorithm               OBJECT IDENTIFIER,
                    //  parameters              ANY DEFINED BY algorithm OPTIONAL  }
                    // 

 
                    VerifyByte( br.ReadByte(), SequenceTag ); 

                    // 
                    // Length of AlgorithmIdentifier
                    //

                    length = ReadAsnByteLength( br ); 

                    long algorithmIdentifierEnd = br.BaseStream.Position + length; 
                    Oid oid = ReadObjectIdentifier( br ); 

                    // 
                    // If there are parameters, ignore them.
                    //

                    br.BaseStream.Position = algorithmIdentifierEnd; 

                    // 
                    // Read the Hash Value 
                    //
 
                    VerifyByte( br.ReadByte(), OctetStringTag );
                    length = ReadAsnByteLength( br );
                    byte[] hashvalue = br.ReadBytes( length );
 
                    //
                    // Add the hash algorithm and value to the collection 
                    // 
                    hashes[ oid ] = hashvalue;
                } 

                //
                // Read the collection logoTypeUri (image/audio file locations)
                // 
                // logotypeURI     SEQUENCE SIZE (1..MAX) OF IA5String }
                // 
                VerifyByte( br.ReadByte(), SequenceTag ); 
                length = ReadAsnByteLength( br );
                long logoTypeUriEnd = br.BaseStream.Position + length; 

                while( !ReachedEndPosition( br.BaseStream.Position, logoTypeUriEnd ) )
                {
                    VerifyByte( br.ReadByte(), StringTag ); 
                    length = ReadAsnByteLength( br );
 
                    // 
                    // Read the Uri using the ASCII encoding
                    // 
                    fileLocations.Add( ascii.GetString( br.ReadBytes( (int) length ) ) );
                }

                // 
                // There may be a LogotypeImageInfo structure. This data is not used so skip over it.
                // 
                if( br.BaseStream.Position != logoTypeEndPosition ) 
                {
                    IDT.TraceDebug( "X509LogoClient: Found LogotypeImageInfo at position {0}. This information is not parsed. Moving to next logo in the extension", br.BaseStream.Position ); 
                    br.BaseStream.Position = logoTypeEndPosition;
                }

//                if( isImage ) 
//                {
                    // 
                    // If the LogotypeImageInfo 
                    //
                    // LogotypeImageInfo ::= SEQUENCE { 
                    //      type            [0] LogotypeImageType DEFAULT color,
                    //      fileSize        INTEGER,  -- In octets
                    //      xSize           INTEGER,  -- Horizontal size in pixels
                    //      ySize           INTEGER,  -- Vertical size in pixels 
                    //      resolution      LogotypeImageResolution OPTIONAL,
                    //      language        [4] IA5String OPTIONAL }  -- RFC 3066 Language Tag 
                    // 

                    // 
                    // LogotypeImageType ::= INTEGER { grayScale(0), color(1) }
                    //

                    // 
                    // LogotypeImageResolution ::= CHOICE {
                    //      numBits         [1] INTEGER,   -- Resolution in bits 
                    //      tableSize       [2] INTEGER }  -- Number of colors or grey tones 
                    //
//                } 
//                else
//                {
                    //
                    // LogotypeAudioInfo ::= SEQUENCE { 
                    //      fileSize        INTEGER,  -- In octets
                    //      playTime        INTEGER,  -- In milliseconds 
                    //      channels        INTEGER,  -- 1=mono, 2=stereo, 4=quad 
                    //      sampleRate      [3] INTEGER OPTIONAL,  -- Samples per second
                    //      language        [4] IA5String OPTIONAL }  -- RFC 3066 Language Tag 
                    //
//                }

                if( isImage ) 
                {
                    m_logos.Add( new X509ImageLogo( logoType, mediaType, hashes, fileLocations ) ); 
                } 
//                else
//                { 
//                    m_logos.Add( new X509AudioLogo( logoType, mediaType, hashes, fileLocations ) );
//                }
            }
        } 

 
        // 
        // Summary:
        // Simple method to validate the specified byte is one in a list. 
        // If not it throws an exception.
        //
        // Parameters:
        // input    - byte to be evaluated. 
        // expected - list to check against
        // 
        private void VerifyByte( byte input, byte[] expected ) 
        {
            foreach( byte b in expected ) 
            {
                if( b == input )
                {
                    return; 
                }
            } 
 
            throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoInvalidLogoType ) ) );
        } 

        //
        // Summary:
        // Simple method to validate the specified byte is the value expected. If not it throws 
        // an exception.
        // 
        // Parameters: 
        // input    - byte to be evaluated.
        // expected - byte to check against 
        //
        private void VerifyByte( byte input, byte expected )
        {
            if( input != expected ) 
            {
                throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoInvalidLogoType ) ) ); 
            } 
        }
 
        //
        // Summary:
        // Checks to see if the stream position has reached the end of a section.
        // 
        // Parameters:
        // currentPosition  - position in the stream 
        // endPosition      - end of the section 
        //
        // Remarks: 
        // Throws an LogoValidationException if the current is beyond the end.
        //
        private bool ReachedEndPosition( long currentPosition, long endPosition )
        { 
            if( currentPosition > endPosition )
            { 
                throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoInvalidCertificateLength ) ) ); 
            }
 
            return ( currentPosition == endPosition );
        }

        // 
        // Summary:
        // An ASN.1 length is a single byte union. The most-significant bit 
        // indicates which format the length takes on: 
        //
        // Parameters: 
        // br - BinaryReader to be used to consume the length from
        //
        // Remarks:
        // MSB == 0 --> Then the length is the binary value of the lower 7 bits 
        // of that byte e.g. [7f] --> 127
        // 
        // MSG == 1 --> Then the lower 7 bits of the byte contain the number of bytes that follow this byte 
        // whose binary value comprise the length
        // e.g. [81 9f] --> 159 
        //
        private Int32 ReadAsnByteLength( BinaryReader br )
        {
            byte firstByte = br.ReadByte(); 

            if( 0x00 == ( firstByte & 0x80 ) ) 
            { 
                return (Int32) firstByte;
            } 

            int numberOfBytesInLength = firstByte & 0x7f;

            if( numberOfBytesInLength < 1 || numberOfBytesInLength > 4 ) 
            {
                throw IDT.ThrowHelperError( new LogoValidationException( SR.GetString( SR.LogoInvalidAsnLength ) ) ); 
            } 

            // 
            // The lower 7-bits hold the number of bytes that form the length
            //
            byte[] bytes = br.ReadBytes( firstByte & 0x7f );
 
            Int32 totalLength = 0;
            foreach( byte b in bytes ) 
            { 
                totalLength = b + ( totalLength << 8 );
            } 

            return totalLength;
        }
 
        //
        // Summary: 
        // Constructs an Oid from the an ASN.1 encoded byte stream. 
        //
        // Parameters: 
        // br - BinaryReader to be used to consume the Oid from
        //
        // Remarks:
        // Hierarchical Object Identifier: The first two levels are 
        // encoded into one byte, since the root level has only 3 nodes
        // (40*x + y).  However if x = joint-iso-itu-t(2) then y may be 
        // > 39, so we have to add special-case handling for this. 
        //
        Oid ReadObjectIdentifier( BinaryReader br ) 
        {
            VerifyByte( br.ReadByte(), ObjectIdentifierTag );
            Int32 length = ReadAsnByteLength( br );
            byte[] oidbytes = br.ReadBytes( length ); 

            // 
            // Construct the object identifer as a string in the form 1 3 14 3 2 26 
            //
            StringBuilder sb = new StringBuilder(); 
            sb.AppendFormat( "{0}.{1}.", oidbytes[ 0 ] / 40, oidbytes[ 0 ] % 40 );

            for( int n=1; n

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK