Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / InfoCardX509Validator.cs / 1 / InfoCardX509Validator.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- // // Presharp uses the c# pragma mechanism to supress its warnings. // These are not recognised by the base compiler so we need to explictly // disable the following warnings. See http://winweb/cse/Tools/PREsharp/userguide/default.asp // for details. // #pragma warning disable 1634, 1691 // unknown message, unknown pragma namespace Microsoft.InfoCards { using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; //Stream using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; using System.IdentityModel.Tokens; using System.IdentityModel.Selectors; using System.ServiceModel; using System.ServiceModel.Security; using System.ServiceModel.Security.Tokens; using System.Text; using System.Xml; using System.Globalization; using System.Xml.Schema; using System.Net.Security; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; // // Summary: // Implements offline chain trust validation // Really a helper class to InfoCardX509Validator which has two copies of this // class - one for m_useMachineContext = true and another for m_useMachineContext = false. // class InfoCardOfflineChainTrustValidator : X509CertificateValidator { bool m_useMachineContext; // // Summary: Constructor // // Parameters: // useMachineContext - whether to use machine context while validating // public InfoCardOfflineChainTrustValidator( bool useMachineContext ) { m_useMachineContext = useMachineContext; } public override void Validate( X509Certificate2 certificate ) { X509Chain chain; Validate( certificate, null, out chain ); chain = null; } // // Summary: // Implements trust chain validation // // Parameters: // certificate - the certificate to check // chain - chain information from the certificate // supportingCerts - intermediate certs that may be needed for chain building // (if they are not already on the box) // // Remarks - as to why we are doing offline: // XP: we have to be offline for perf reasons, IE7 is same // Vista: The crypto team has made online checking much better. IE7 does online checking. // So we could use WinVerifyTrust (which uses IE settings does Online on Vista and Offline on XP) // However we want a consistent story for STS builders for XP and Vista. We want the CRL technology to advance a bit more before we force STS builders to support online validation. // In addition InfoCard does not support I/O cancellation semantics in the UI currently so we are // not inclined to take the network hit of doing the CRL checking at this time. // public void Validate( X509Certificate2 certificate, X509Certificate2Collection supportingCerts, out X509Chain chain ) { if( null == certificate ) { throw IDT.ThrowHelperArgumentNull( "certificate" ); } chain = new X509Chain( m_useMachineContext ); // // chain.ChainPolicy creates a new X509ChainPolicy if one is not already set. // We cannot have static X509ChainPolicy becuase we need to add different supportingCerts // each time // if( null != supportingCerts ) { chain.ChainPolicy.ExtraStore.AddRange( supportingCerts ); } chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; chain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown | X509VerificationFlags.IgnoreEndRevocationUnknown | X509VerificationFlags.IgnoreRootRevocationUnknown | X509VerificationFlags.IgnoreCtlSignerRevocationUnknown; if( !chain.Build( certificate ) ) { throw IDT.ThrowHelperError( new SecurityTokenValidationException( SR.GetString( SR.X509ChainBuildFail, GetCertificateId( certificate ), GetChainStatusInformation( chain.ChainStatus ) ) ) ); } } internal static string GetCertificateId( X509Certificate2 certificate ) { StringBuilder str = new StringBuilder( 256 ); AppendCertificateIdentityName( str, certificate ); return str.ToString(); } // // Summary: // Concatenate chain status information to return a string // // Parameters: // chainStatus - resulting from a chain.Build // static string GetChainStatusInformation( X509ChainStatus[] chainStatus ) { if( chainStatus != null ) { StringBuilder error = new StringBuilder( 256 ); for( int i = 0; i < chainStatus.Length; ++i ) { // // Exclude CRL offline errors because we ignore those // if( X509ChainStatusFlags.RevocationStatusUnknown != chainStatus[ i ].Status && X509ChainStatusFlags.OfflineRevocation != chainStatus[ i ].Status ) { error.Append( chainStatus[ i ].StatusInformation ); error.Append( " " ); } } return error.ToString(); } return String.Empty; } // // Summary: // Create a displayable name for the certificate // // Parameters: // str - the StringBuilder to populate // certificate - the certificate to check // static void AppendCertificateIdentityName( StringBuilder str, X509Certificate2 certificate ) { string value = certificate.SubjectName.Name; if( String.IsNullOrEmpty( value ) ) { value = certificate.GetNameInfo( X509NameType.DnsName, false ); if( String.IsNullOrEmpty( value ) ) { value = certificate.GetNameInfo( X509NameType.SimpleName, false ); if( String.IsNullOrEmpty( value ) ) { value = certificate.GetNameInfo( X509NameType.EmailName, false ); if( String.IsNullOrEmpty( value ) ) { value = certificate.GetNameInfo( X509NameType.UpnName, false ); } } } } // Same format as X509Identity str.Append( String.IsNullOrEmpty( value ) ? "" : value ); str.Append( "; " ); str.Append( certificate.Thumbprint ); } } // // Summary: Primary class to cater for all our X509 validation needs // Several uses for this class. // a) Need to pass this to Indigo (in InfoCardServiceClientCredentials) // so need to derive from X509CertificateValidator // i) Indigo wrt RemoteTokenFactory // ii) Indigo wrt Browser case // b) Validation of incoming recipient certs // c) Validation of cert during import of managed card // d) Building the chain in HA cert, before calling the native API to determine if root is HA // // Question: // Why can't we just use Indigo's validators in System.IdentityModel.dll? // // Answer: // After discussion with Indigo Security team (that owns the validators in System.IdentityModel.dll) // it was deemed suitable to have a custom validator as we have done so. // // The primary reason is the following: // Indigo's out-of-the-box validators support // a) {chaining up to LM Trusted CA} OR {Peer Trust} // b) {chaining up to CU Trusted CA} OR {Peer Trust} // But CardSpace needs special behavior of // allowing certs {chaining up to LM or CU Trusted CA} OR {Peer Trust}. // // In addition, CardSpace needs additional info from the results of the Validation // that are NOT exposed by Indigo's out-of-the-box validator: // (1) We (CardSpace) need to know if the validation passed via chain building or via peer trust. // This is because we compute a recipient id based on this boolean. // (2) We (CardSpace) need access to the X509Chain that was built by the validator. // This is because we need to pass the chain context to a native function that helps determine // if the cert (representing the relying party) is EV. Without overriding Indigo's validator // our code would have to call chain.Build() separately which is ESSENTIALLY what the validator does. // Therefore having a custom validator for CardSpace would save duplication of effort // effort in building the chain for a given cert. // class InfoCardX509Validator : X509CertificateValidator { static InfoCardOfflineChainTrustValidator s_identityMachineChainTrustValidator = null; static InfoCardOfflineChainTrustValidator s_identityUserChainTrustValidator = null; static X509CertificateValidator s_identityPeerTrustValidator; static X509Certificate2Collection m_supportingCertificates; static InfoCardX509Validator() { s_identityMachineChainTrustValidator = new InfoCardOfflineChainTrustValidator( true ); s_identityUserChainTrustValidator = new InfoCardOfflineChainTrustValidator( false ); s_identityPeerTrustValidator = X509CertificateValidator.PeerTrust; } InfoCardX509Validator( X509Certificate2Collection supportingCerts ) { m_supportingCertificates = supportingCerts; } public static X509CertificateValidator Create( X509Certificate2Collection supportingCerts ) { return ( X509CertificateValidator ) new InfoCardX509Validator( supportingCerts ); } // // Summary: // Called within InfoCard // The InfoCardX509Validator validation passes if either // peer or chain trust validation passes. Chain trust // validation passes either for user context or machine context // // Parameters: // certificate - the certificate to check // chainTrustPassed - out param returning true if chainTrust passed (as opposed to peer trust) // supportingRecipientCerts - intermediate certs that may be needed for chain building // (if they are not already on the box) // public static void ValidateChainOrPeer( X509Certificate2 certificate, X509Certificate2Collection supportingRecipientCerts, out bool chainTrustPassed ) { Validate( certificate, supportingRecipientCerts, out chainTrustPassed ); } // // Summary: // Called by Indigo // SAME behavior as ValidateChainOrPeer, but this matches the abstract function // that we need to override. // // Parameters: // certificate - the certificate to check // public override void Validate( X509Certificate2 certificate ) { bool chainPassed; // // In RemoteTokenFactory we override Indigo's validator with this one // (so that CardSpace can have specialized behavior e.g. offline CRL validation). // This does not have an incoming chain but we would have initialized m_supportingCertificates // in the constructor // Validate( certificate, m_supportingCertificates, out chainPassed ); } // // Summary: // Called from .NET // SAME behavior as ValidateChainOrPeer // // sender: An object that contains state information for this validation. // certificate: The certificate used to authenticate the remote party. // chain: The chain of certificate authorities associated with the remote certificate. // sslPolicyErrors: One or more errors associated with the remote certificate. // // Return Value // A Boolean value that determines whether the specified certificate is accepted for authentication. // // Remarks: // // Even if there are no policy errors in "sslPolicyErrors" [i.e. SslPolicyErrors.None] // we still need to check for revocation, i.e. need another chain build // // // If there are already policy errors but no name errors // (e.g. SslPolicyErrors.RemoteCertificateChainErrors) then we could optimize this function // to just check for peerTrust in that case // // public static bool ValidateChainOrPeerCallback( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors ) { bool chainTrustPassedTemp = false; if( 0 != ( sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch ) || 0 != ( sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable ) ) { return false; } IDT.Assert( ( null != certificate ) && ( null != chain ), "We should have returned false for SslPolicyErrors.RemoteCertificateNotAvailable" ); try { ValidateChainOrPeer( new X509Certificate2( certificate ), chain.ChainPolicy.ExtraStore, out chainTrustPassedTemp ); } catch( SecurityTokenValidationException stve ) { // // Log this case with the best matching resource string we have currently // IDT.TraceAndLogException( new IdentityValidationException( SR.GetString( SR.RecipientCertificateNotValid ), stve ) ); return false; } return true; } // // Summary: // Gate function to Validate* functions // // Parameters: // certificate - the certificate to check // chainTrustPassed - out param returning true if chainTrust passed (as opposed to peer trust) // supportingCerts - intermediate certs that may be needed for chain building // (if they are not already on the box) // private static void Validate( X509Certificate2 certificate, X509Certificate2Collection supportingRecipientCerts, out bool chainTrustPassed ) { chainTrustPassed = false; string chainTrustMessage = String.Empty; try { X509Chain chain; InfoCardX509Validator.ValidateChain( certificate, supportingRecipientCerts, out chain ); chainTrustPassed = true; } catch( SecurityTokenValidationException e ) { chainTrustMessage = e.Message; } if( !chainTrustPassed ) { try { InfoCardX509Validator.ValidatePeer( certificate ); } catch( SecurityTokenValidationException ex ) { throw IDT.ThrowHelperError( new SecurityTokenValidationException( SR.GetString( SR.X509ChainFailAndPeerTrustFail, chainTrustMessage, ex.Message ) ) ); } } else { return; } } // // Summary: // Validates that the given certificate chains to either the machine or user trusted roots. // // Parameters: // certificate - the certificate to check // chain - the chain that is constructed from chain.Build( certificate ) // supportingCerts - intermediate certs that may be needed for chain building // (if they are not already on the box) // public static void ValidateChain( X509Certificate2 certificate, X509Certificate2Collection supportingCerts, out X509Chain chain ) { try { // // First try machine context // s_identityMachineChainTrustValidator.Validate( certificate, supportingCerts, out chain ); } catch( SecurityTokenValidationException ) { // // Then try user context // s_identityUserChainTrustValidator.Validate( certificate, supportingCerts, out chain ); } } // // Summary: // Validates that the given certificate chains to either the machine or user trusted roots. // // Parameters: // certificate - the certificate to check // supportingCerts - intermediate certs that may be needed for chain building // (if they are not already on the box) // public static bool TryValidateChain( X509Certificate2 certificate, X509Certificate2Collection supportingCerts ) { bool isValid = true; try { X509Chain chain; ValidateChain( certificate, supportingCerts, out chain ); } catch( SecurityTokenValidationException ) { isValid = false; } return isValid; } // // Summary: // Validates that the given certificate is conforms to our peer cert policy: // must be in user / trusted people // must not be in user / untrusted certificates // must be within date. // // Parameters: // certificate - the certificate to check // public static void ValidatePeer( X509Certificate2 certificate ) { s_identityPeerTrustValidator.Validate( certificate ); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DBPropSet.cs
- ChainedAsyncResult.cs
- ConfigurationLockCollection.cs
- RSAPKCS1SignatureFormatter.cs
- ParserContext.cs
- SafeArchiveContext.cs
- TreeView.cs
- BinaryConverter.cs
- AuthenticationModuleElement.cs
- MappingModelBuildProvider.cs
- Action.cs
- LeftCellWrapper.cs
- EllipseGeometry.cs
- PtsHost.cs
- TreeNodeCollection.cs
- WebServiceReceive.cs
- InputLanguageCollection.cs
- LambdaCompiler.Logical.cs
- AnonymousIdentificationModule.cs
- _ListenerResponseStream.cs
- ListenerConnectionDemuxer.cs
- DataTableMapping.cs
- HttpCookiesSection.cs
- FolderLevelBuildProviderAppliesToAttribute.cs
- ImportContext.cs
- UntrustedRecipientException.cs
- DefaultObjectMappingItemCollection.cs
- CacheSection.cs
- ActionMessageFilter.cs
- PropertyChangedEventArgs.cs
- SerializationEventsCache.cs
- NativeStructs.cs
- srgsitem.cs
- DefaultPerformanceCounters.cs
- OleDbReferenceCollection.cs
- CompositeFontInfo.cs
- StateMachineHelpers.cs
- PermissionSet.cs
- Substitution.cs
- GAC.cs
- DefaultBinder.cs
- DesignBindingConverter.cs
- BasicBrowserDialog.designer.cs
- PropertyGeneratedEventArgs.cs
- OleDbError.cs
- Int64Storage.cs
- FilterEventArgs.cs
- TimeSpan.cs
- RotateTransform.cs
- CryptoStream.cs
- CodeDelegateCreateExpression.cs
- WebBrowserPermission.cs
- CardSpaceSelector.cs
- AsyncCodeActivityContext.cs
- WebPartUtil.cs
- XmlParserContext.cs
- ReaderWriterLockWrapper.cs
- CompatibleComparer.cs
- Literal.cs
- ListCollectionView.cs
- VectorValueSerializer.cs
- CompilationUtil.cs
- PtsHost.cs
- QueryOperationResponseOfT.cs
- GraphicsState.cs
- QueryConverter.cs
- GetCertificateRequest.cs
- GridViewDeletedEventArgs.cs
- OLEDB_Util.cs
- UrlPath.cs
- JsonDataContract.cs
- CodeSubDirectory.cs
- WebPartConnectionsCloseVerb.cs
- ReachObjectContext.cs
- TextEditor.cs
- ClientRuntimeConfig.cs
- GroupBoxAutomationPeer.cs
- DbgUtil.cs
- SendKeys.cs
- MemberMaps.cs
- DataRecordInternal.cs
- DynamicValueConverter.cs
- unitconverter.cs
- Set.cs
- RsaSecurityKey.cs
- OleStrCAMarshaler.cs
- InvalidDataException.cs
- UriParserTemplates.cs
- InstanceBehavior.cs
- entityreference_tresulttype.cs
- WebBaseEventKeyComparer.cs
- FlowDocumentPage.cs
- XmlReflectionImporter.cs
- Set.cs
- FontStretch.cs
- DataGridCaption.cs
- ConsumerConnectionPointCollection.cs
- PackagePart.cs
- PagesChangedEventArgs.cs
- Bitmap.cs