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
- CheckBoxField.cs
- NamedPipeDuplicateContext.cs
- OracleTransaction.cs
- OLEDB_Enum.cs
- BamlVersionHeader.cs
- DPAPIProtectedConfigurationProvider.cs
- ProtocolsSection.cs
- SchemaContext.cs
- DocComment.cs
- DataPointer.cs
- ReaderContextStackData.cs
- ValidationPropertyAttribute.cs
- SqlPersonalizationProvider.cs
- EastAsianLunisolarCalendar.cs
- DictionarySectionHandler.cs
- FormViewUpdatedEventArgs.cs
- InvokeMethodActivityDesigner.cs
- SoapCommonClasses.cs
- BitmapFrame.cs
- ProcessRequestArgs.cs
- GeometryHitTestParameters.cs
- PerformanceCounterPermissionEntry.cs
- ListViewEditEventArgs.cs
- SecurityCriticalDataForSet.cs
- PagerSettings.cs
- Trigger.cs
- ObjectPersistData.cs
- ThicknessAnimation.cs
- DebugView.cs
- ToolStripRenderer.cs
- ACL.cs
- SamlDoNotCacheCondition.cs
- Compilation.cs
- Frame.cs
- TypefaceCollection.cs
- XmlSerializerVersionAttribute.cs
- SchemaTableColumn.cs
- selecteditemcollection.cs
- WindowsStatic.cs
- AssemblyCollection.cs
- NavigateEvent.cs
- ClientProxyGenerator.cs
- SmiContextFactory.cs
- FontDialog.cs
- ToolStripProgressBar.cs
- BitmapEffectCollection.cs
- ProviderIncompatibleException.cs
- MetadataResolver.cs
- assemblycache.cs
- ImageMapEventArgs.cs
- SchemaDeclBase.cs
- FastEncoderStatics.cs
- CommonDialog.cs
- listitem.cs
- DispatcherHooks.cs
- Monitor.cs
- Convert.cs
- BitmapEffectGeneralTransform.cs
- RequestCachingSection.cs
- DataGridViewCellParsingEventArgs.cs
- ValidationSummary.cs
- OneOfConst.cs
- CommonRemoteMemoryBlock.cs
- VirtualizingStackPanel.cs
- WebHostedComPlusServiceHost.cs
- ImageMap.cs
- PtsCache.cs
- safemediahandle.cs
- InvariantComparer.cs
- UserControl.cs
- SessionParameter.cs
- PointUtil.cs
- SharedDp.cs
- ComboBoxRenderer.cs
- Int16Storage.cs
- CodeAccessPermission.cs
- _BasicClient.cs
- Int64AnimationBase.cs
- FloatMinMaxAggregationOperator.cs
- LinkButton.cs
- DocumentPageView.cs
- MethodAccessException.cs
- PersistNameAttribute.cs
- ResourceKey.cs
- _UncName.cs
- CqlBlock.cs
- DocobjHost.cs
- RemotingConfiguration.cs
- DispatchRuntime.cs
- FolderLevelBuildProvider.cs
- COM2PictureConverter.cs
- SpellerStatusTable.cs
- HtmlHead.cs
- DelegateHelpers.Generated.cs
- FormatSettings.cs
- ManipulationCompletedEventArgs.cs
- DataViewSettingCollection.cs
- Flowchart.cs
- SqlDataRecord.cs
- TagPrefixInfo.cs