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
- CellCreator.cs
- WpfGeneratedKnownTypes.cs
- UniqueConstraint.cs
- SymmetricAlgorithm.cs
- RtfNavigator.cs
- ImmComposition.cs
- TimeSpanValidatorAttribute.cs
- AffineTransform3D.cs
- CodeNamespaceImportCollection.cs
- Context.cs
- WebHttpSecurityElement.cs
- DictionaryEntry.cs
- ListViewEditEventArgs.cs
- VoiceSynthesis.cs
- CommandDevice.cs
- _SpnDictionary.cs
- TemplateBaseAction.cs
- MsmqActivation.cs
- GuidConverter.cs
- DebugTraceHelper.cs
- Screen.cs
- WorkBatch.cs
- MemberMemberBinding.cs
- ValidatorCollection.cs
- MatrixTransform.cs
- HashAlgorithm.cs
- ContactManager.cs
- PropertySourceInfo.cs
- HiddenField.cs
- SHA384Cng.cs
- ChtmlSelectionListAdapter.cs
- sqlmetadatafactory.cs
- SmtpClient.cs
- ListItemCollection.cs
- SchemaNames.cs
- SqlProcedureAttribute.cs
- DerivedKeySecurityToken.cs
- DirectoryLocalQuery.cs
- CultureInfoConverter.cs
- StorageInfo.cs
- HMACSHA512.cs
- BitmapEffectDrawingContextState.cs
- SystemBrushes.cs
- SocketAddress.cs
- CommentEmitter.cs
- SqlDataReaderSmi.cs
- AccessDataSourceView.cs
- FormsAuthenticationEventArgs.cs
- ResetableIterator.cs
- Membership.cs
- DocumentXmlWriter.cs
- DecoderReplacementFallback.cs
- DateTimePicker.cs
- VideoDrawing.cs
- PageAsyncTaskManager.cs
- ConfigurationLocation.cs
- MissingMemberException.cs
- EdmItemCollection.cs
- WindowsRegion.cs
- ReservationCollection.cs
- Utils.cs
- OleCmdHelper.cs
- ArraySegment.cs
- SessionStateUtil.cs
- TemplateControlCodeDomTreeGenerator.cs
- ProofTokenCryptoHandle.cs
- EnumType.cs
- SafeNativeMethodsOther.cs
- DefaultEventAttribute.cs
- PropertyEmitterBase.cs
- AssemblyBuilderData.cs
- EntityContainerRelationshipSetEnd.cs
- ModuleConfigurationInfo.cs
- ThaiBuddhistCalendar.cs
- WebPartConnectionsDisconnectVerb.cs
- SpellerInterop.cs
- ResourceDescriptionAttribute.cs
- AutoGeneratedField.cs
- TextServicesContext.cs
- SqlRowUpdatingEvent.cs
- GridLength.cs
- NotifyInputEventArgs.cs
- SafeRightsManagementSessionHandle.cs
- Rotation3DKeyFrameCollection.cs
- AttributeCollection.cs
- InfoCardTrace.cs
- XmlSchemaInclude.cs
- ClientSettingsSection.cs
- DiscriminatorMap.cs
- EventEntry.cs
- DataSysAttribute.cs
- AssemblyUtil.cs
- NonClientArea.cs
- HtmlShimManager.cs
- PropertyKey.cs
- MetadataItemSerializer.cs
- RuntimeWrappedException.cs
- DecimalAnimation.cs
- ProtocolsConfigurationHandler.cs
- Label.cs