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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridAutomationPeer.cs
- ReflectPropertyDescriptor.cs
- DetailsViewPagerRow.cs
- XPathDocumentBuilder.cs
- UnauthorizedAccessException.cs
- TokenBasedSetEnumerator.cs
- SQLDateTime.cs
- TargetException.cs
- RTLAwareMessageBox.cs
- XmlSchemaValidationException.cs
- followingsibling.cs
- CultureInfo.cs
- PixelFormatConverter.cs
- DataSourceView.cs
- CompositeScriptReferenceEventArgs.cs
- ScriptingSectionGroup.cs
- MultiView.cs
- GlyphTypeface.cs
- SessionPageStatePersister.cs
- ScaleTransform3D.cs
- ImageSource.cs
- Socket.cs
- ResourceDictionary.cs
- NameValuePermission.cs
- DiscoveryCallbackBehavior.cs
- DeviceSpecificDesigner.cs
- HotSpot.cs
- CultureSpecificCharacterBufferRange.cs
- BeginStoryboard.cs
- Tokenizer.cs
- XmlWrappingWriter.cs
- OdbcConnectionFactory.cs
- SortAction.cs
- Hyperlink.cs
- WindowsSysHeader.cs
- CompositeCollection.cs
- WebPartDisplayModeCancelEventArgs.cs
- SqlBuilder.cs
- HitTestResult.cs
- StateDesignerConnector.cs
- SoapFault.cs
- ResourceSet.cs
- IsolatedStoragePermission.cs
- BufferedReadStream.cs
- DeviceFilterDictionary.cs
- LogicalExpr.cs
- InsufficientExecutionStackException.cs
- MultiTouchSystemGestureLogic.cs
- HGlobalSafeHandle.cs
- XComponentModel.cs
- XdrBuilder.cs
- SettingsAttributeDictionary.cs
- EventToken.cs
- ExpanderAutomationPeer.cs
- MimeFormReflector.cs
- ExtendedProperty.cs
- ScalarType.cs
- WebPartVerbsEventArgs.cs
- FlowDocumentPageViewerAutomationPeer.cs
- MetaForeignKeyColumn.cs
- Suspend.cs
- DataSourceXmlTextReader.cs
- ExpandCollapseProviderWrapper.cs
- ReflectionTypeLoadException.cs
- SequentialActivityDesigner.cs
- OleDbException.cs
- AdornerHitTestResult.cs
- EntityDataSourceDataSelection.cs
- UserControlBuildProvider.cs
- NameValuePair.cs
- FixedSOMPageConstructor.cs
- OutputCacheSection.cs
- MbpInfo.cs
- FrameworkElement.cs
- BamlStream.cs
- CLRBindingWorker.cs
- KeyGestureValueSerializer.cs
- WebBrowserEvent.cs
- ConfigXmlElement.cs
- Model3D.cs
- DebugControllerThread.cs
- BrowserCapabilitiesFactoryBase.cs
- GridLengthConverter.cs
- EncodingInfo.cs
- ResetableIterator.cs
- OleDbDataAdapter.cs
- CommunicationObjectAbortedException.cs
- SettingsPropertyValue.cs
- ConfigurationPropertyCollection.cs
- ResourceSetExpression.cs
- TextAutomationPeer.cs
- SafeBitVector32.cs
- Viewport2DVisual3D.cs
- HyperLinkColumn.cs
- ImageMapEventArgs.cs
- SqlDataSourceQueryEditor.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- categoryentry.cs
- Model3D.cs
- HttpBufferlessInputStream.cs