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
- mediaeventshelper.cs
- ObjectDataSourceFilteringEventArgs.cs
- MultiPropertyDescriptorGridEntry.cs
- PartialCachingControl.cs
- VoiceChangeEventArgs.cs
- Math.cs
- DBParameter.cs
- IUnknownConstantAttribute.cs
- TrustManagerMoreInformation.cs
- sitestring.cs
- XPathExpr.cs
- GeneralTransformGroup.cs
- AbstractSvcMapFileLoader.cs
- Splitter.cs
- Mappings.cs
- Boolean.cs
- XmlStreamStore.cs
- EdmItemError.cs
- NeutralResourcesLanguageAttribute.cs
- XPathEmptyIterator.cs
- TableHeaderCell.cs
- CodeConditionStatement.cs
- Attributes.cs
- Match.cs
- SafeFileMappingHandle.cs
- DecoderBestFitFallback.cs
- FixedHighlight.cs
- ListViewPagedDataSource.cs
- CompatibleComparer.cs
- HttpSysSettings.cs
- TextParagraphCache.cs
- ViewLoader.cs
- TimeSpanStorage.cs
- RefreshPropertiesAttribute.cs
- FeatureSupport.cs
- PropertyEntry.cs
- DataBinder.cs
- WorkflowApplicationAbortedException.cs
- Italic.cs
- FramingEncoders.cs
- SubclassTypeValidator.cs
- PageRouteHandler.cs
- DependencyObjectType.cs
- ArgIterator.cs
- XamlTypeMapperSchemaContext.cs
- DbProviderFactory.cs
- TargetConverter.cs
- EventListenerClientSide.cs
- OleDbConnectionInternal.cs
- KnownIds.cs
- ListViewDeletedEventArgs.cs
- propertytag.cs
- InsufficientMemoryException.cs
- PreviewPrintController.cs
- SectionInformation.cs
- BitmapEffectrendercontext.cs
- CreateInstanceBinder.cs
- XmlSchemaSequence.cs
- RawStylusActions.cs
- TraceEventCache.cs
- HatchBrush.cs
- ToolBarButtonClickEvent.cs
- ChildDocumentBlock.cs
- ToolStripManager.cs
- Int64Storage.cs
- WsatServiceAddress.cs
- Visitor.cs
- SpellerError.cs
- SqlConnectionPoolProviderInfo.cs
- DropDownList.cs
- Range.cs
- DbProviderFactories.cs
- SqlConnectionPoolGroupProviderInfo.cs
- MsmqAppDomainProtocolHandler.cs
- XappLauncher.cs
- DataGridViewColumn.cs
- EventQueueState.cs
- InvokeHandlers.cs
- SqlExpressionNullability.cs
- LineServicesCallbacks.cs
- PolyLineSegment.cs
- IndexingContentUnit.cs
- ControlValuePropertyAttribute.cs
- SqlRetyper.cs
- SystemDiagnosticsSection.cs
- Vector3DCollectionValueSerializer.cs
- UInt16.cs
- ElementHostAutomationPeer.cs
- VirtualizingStackPanel.cs
- AutoResetEvent.cs
- DescendentsWalkerBase.cs
- IssuedTokenClientBehaviorsElement.cs
- ProfessionalColors.cs
- EditorServiceContext.cs
- HostExecutionContextManager.cs
- HistoryEventArgs.cs
- ToolStripGripRenderEventArgs.cs
- UdpDuplexChannel.cs
- Encoder.cs
- DataGridViewCellCollection.cs