Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / Selectors / X509CertificateChain.cs / 1 / X509CertificateChain.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.IdentityModel.Selectors { using System.IdentityModel.Tokens; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; // Most of codes are copied from \ndp\fx\src\security\system\security\cryptography\x509\X509Chain.cs class X509CertificateChain { public const uint DefaultChainPolicyOID = CAPI.CERT_CHAIN_POLICY_BASE; bool useMachineContext; X509ChainPolicy chainPolicy; uint chainPolicyOID = X509CertificateChain.DefaultChainPolicyOID; public X509CertificateChain() : this(false) { } public X509CertificateChain(bool useMachineContext) { this.useMachineContext = useMachineContext; } public X509CertificateChain(bool useMachineContext, uint chainPolicyOID) { this.useMachineContext = useMachineContext; // One of the condition to pass NT_AUTH is the issuer of the cert must be trusted by NT auth. // Simply add to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseCertificates\NTAuth\Certificates this.chainPolicyOID = chainPolicyOID; } public X509ChainPolicy ChainPolicy { get { if (this.chainPolicy == null) { this.chainPolicy = new X509ChainPolicy(); } return this.chainPolicy; } set { this.chainPolicy = value; } } public X509ChainStatus[] ChainStatus { #pragma warning suppress 56503 // get { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } } // There are 2 steps in chain validation. // 1) BuildChain by calling CAPI.CertGetCertificateChain. The result is // the chain context containing the chain and status. // 2) VerifyChain by calling CAPI.CertVerifyCertificateChainPolicy. // Refer to MB50916, Since Vista out-of-the-box will trust the chain with PeerTrust, // we include the flag to ignore PeerTrust for CAPI.CertVerifyCertificateChainPolicy. public bool Build(X509Certificate2 certificate) { if (certificate == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("certificate"); if (certificate.Handle == IntPtr.Zero) throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("certificate", SR.GetString(SR.ArgumentInvalidCertificate)); SafeCertChainHandle safeCertChainHandle = SafeCertChainHandle.InvalidHandle; X509ChainPolicy chainPolicy = this.ChainPolicy; BuildChain(this.useMachineContext ? new IntPtr(CAPI.HCCE_LOCAL_MACHINE) : new IntPtr(CAPI.HCCE_CURRENT_USER), certificate.Handle, chainPolicy.ExtraStore, chainPolicy.ApplicationPolicy, chainPolicy.CertificatePolicy, chainPolicy.RevocationMode, chainPolicy.RevocationFlag, chainPolicy.VerificationTime, chainPolicy.UrlRetrievalTimeout, out safeCertChainHandle); // Verify the chain using the specified policy. CAPI.CERT_CHAIN_POLICY_PARA PolicyPara = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA))); CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS))); // Ignore peertrust. Peer trust caused the chain to succeed out-of-the-box in Vista. // This new flag is only available in Vista. PolicyPara.dwFlags = (uint)chainPolicy.VerificationFlags | CAPI.CERT_CHAIN_POLICY_IGNORE_PEER_TRUST_FLAG; if (!CAPI.CertVerifyCertificateChainPolicy(new IntPtr(this.chainPolicyOID), safeCertChainHandle, ref PolicyPara, ref PolicyStatus)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } if (PolicyStatus.dwError != CAPI.S_OK) { int error = (int)PolicyStatus.dwError; throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.X509ChainBuildFail, SecurityUtils.GetCertificateId(certificate), new CryptographicException(error).Message))); } return true; } static unsafe void BuildChain(IntPtr hChainEngine, IntPtr pCertContext, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout, out SafeCertChainHandle ppChainContext) { SafeCertStoreHandle hCertStore = ExportToMemoryStore(extraStore, pCertContext); CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.CERT_CHAIN_PARA(); ChainPara.cbSize = (uint)Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_PARA)); // Application policy SafeHGlobalHandle applicationPolicyHandle = SafeHGlobalHandle.InvalidHandle; SafeHGlobalHandle certificatePolicyHandle = SafeHGlobalHandle.InvalidHandle; try { if (applicationPolicy != null && applicationPolicy.Count > 0) { ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND; ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)applicationPolicy.Count; applicationPolicyHandle = CopyOidsToUnmanagedMemory(applicationPolicy); ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle(); } // Certificate policy if (certificatePolicy != null && certificatePolicy.Count > 0) { ChainPara.RequestedIssuancePolicy.dwType = CAPI.USAGE_MATCH_TYPE_AND; ChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint)certificatePolicy.Count; certificatePolicyHandle = CopyOidsToUnmanagedMemory(certificatePolicy); ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle(); } ChainPara.dwUrlRetrievalTimeout = (uint)timeout.Milliseconds; FILETIME ft = new FILETIME(); *((long*)&ft) = verificationTime.ToFileTime(); uint flags = MapRevocationFlags(revocationMode, revocationFlag); // Build the chain. if (!CAPI.CertGetCertificateChain(hChainEngine, pCertContext, ref ft, hCertStore, ref ChainPara, flags, IntPtr.Zero, out ppChainContext)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } finally { if (applicationPolicyHandle != null) applicationPolicyHandle.Dispose(); if (certificatePolicyHandle != null) certificatePolicyHandle.Dispose(); hCertStore.Close(); } } static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection, IntPtr pCertContext) { CAPI.CERT_CONTEXT certContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(pCertContext, typeof(CAPI.CERT_CONTEXT)); // No extra store nor intermediate certificates if ((collection == null || collection.Count <= 0) && certContext.hCertStore == IntPtr.Zero) { return SafeCertStoreHandle.InvalidHandle; } // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. SafeCertStoreHandle certStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (certStoreHandle == null || certStoreHandle.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // // Add extra store if (collection != null && collection.Count > 0) { foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } // Add intermediates if (certContext.hCertStore != IntPtr.Zero) { X509Store store = new X509Store(certContext.hCertStore); X509Certificate2Collection intermediates = null; try { intermediates = store.Certificates; foreach (X509Certificate2 x509 in intermediates) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } finally { SecurityUtils.ResetAllCertificates(intermediates); store.Close(); } } return certStoreHandle; } static SafeHGlobalHandle CopyOidsToUnmanagedMemory(OidCollection oids) { SafeHGlobalHandle safeAllocHandle = SafeHGlobalHandle.InvalidHandle; if (oids == null || oids.Count == 0) return safeAllocHandle; int ptrSize = oids.Count * Marshal.SizeOf(typeof(IntPtr)); int oidSize = 0; foreach (Oid oid in oids) { oidSize += (oid.Value.Length + 1); } safeAllocHandle = SafeHGlobalHandle.AllocHGlobal(ptrSize + oidSize); IntPtr pOid = new IntPtr((long)safeAllocHandle.DangerousGetHandle() + ptrSize); for (int index = 0; index < oids.Count; index++) { Marshal.WriteIntPtr(new IntPtr((long)safeAllocHandle.DangerousGetHandle() + index * Marshal.SizeOf(typeof(IntPtr))), pOid); byte[] ansiOid = Encoding.ASCII.GetBytes(oids[index].Value); Marshal.Copy(ansiOid, 0, pOid, ansiOid.Length); pOid = new IntPtr((long)pOid + oids[index].Value.Length + 1); } return safeAllocHandle; } static uint MapRevocationFlags(X509RevocationMode revocationMode, X509RevocationFlag revocationFlag) { uint dwFlags = 0; if (revocationMode == X509RevocationMode.NoCheck) return dwFlags; if (revocationMode == X509RevocationMode.Offline) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; if (revocationFlag == X509RevocationFlag.EndCertificateOnly) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_END_CERT; else if (revocationFlag == X509RevocationFlag.EntireChain) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN; else dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; return dwFlags; } } } // 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
- EventLogQuery.cs
- MatrixCamera.cs
- EmptyStringExpandableObjectConverter.cs
- ListBox.cs
- ComponentEditorForm.cs
- GCHandleCookieTable.cs
- ConfigurationManagerInternalFactory.cs
- SplitterPanel.cs
- OdbcConnection.cs
- GridViewDeletedEventArgs.cs
- SystemEvents.cs
- CompModSwitches.cs
- EdmPropertyAttribute.cs
- UnsafeNativeMethods.cs
- AbstractDataSvcMapFileLoader.cs
- PrivilegedConfigurationManager.cs
- DbMetaDataColumnNames.cs
- SdlChannelSink.cs
- ToolStripPanelDesigner.cs
- RegistrySecurity.cs
- OfTypeExpression.cs
- UnsafeNativeMethods.cs
- DBSqlParserColumn.cs
- ConstructorNeedsTagAttribute.cs
- ValidatingPropertiesEventArgs.cs
- WindowsClaimSet.cs
- RsaSecurityToken.cs
- PersonalizableAttribute.cs
- ComboBox.cs
- GlobalizationAssembly.cs
- ReflectionPermission.cs
- AdobeCFFWrapper.cs
- SessionStateContainer.cs
- HyperLinkColumn.cs
- ZipFileInfo.cs
- RepeatButton.cs
- ObjectCache.cs
- BasicExpressionVisitor.cs
- StdValidatorsAndConverters.cs
- DefaultExpression.cs
- BinaryParser.cs
- SqlCommandBuilder.cs
- DropDownList.cs
- AppendHelper.cs
- BindingContext.cs
- UiaCoreApi.cs
- CmsUtils.cs
- FileDetails.cs
- BindingEntityInfo.cs
- ColumnHeader.cs
- FlowNode.cs
- StrokeFIndices.cs
- BufferModeSettings.cs
- BaseDataBoundControl.cs
- SapiAttributeParser.cs
- BamlLocalizabilityResolver.cs
- ListViewDeleteEventArgs.cs
- SecurityTokenException.cs
- ContentPlaceHolder.cs
- LookupNode.cs
- SafeRightsManagementHandle.cs
- PropertyKey.cs
- OrderablePartitioner.cs
- OutputCacheSection.cs
- RTLAwareMessageBox.cs
- IndividualDeviceConfig.cs
- ParameterModifier.cs
- WebBrowsableAttribute.cs
- SmtpReplyReader.cs
- CompositeScriptReference.cs
- NativeMethods.cs
- ProviderConnectionPoint.cs
- MetadataArtifactLoaderCompositeFile.cs
- InternalSafeNativeMethods.cs
- WebContentFormatHelper.cs
- XamlFilter.cs
- SplineKeyFrames.cs
- ConfigurationCollectionAttribute.cs
- Double.cs
- SQLInt32.cs
- ControlCollection.cs
- SqlTriggerAttribute.cs
- EmptyElement.cs
- RoleGroup.cs
- PriorityBindingExpression.cs
- Token.cs
- MatrixCamera.cs
- path.cs
- CodeMemberField.cs
- WebPartTransformerAttribute.cs
- XMLUtil.cs
- MorphHelpers.cs
- AddingNewEventArgs.cs
- InputGestureCollection.cs
- UserInitiatedNavigationPermission.cs
- DragSelectionMessageFilter.cs
- PointAnimationUsingPath.cs
- CheckBoxDesigner.cs
- OleDbRowUpdatedEvent.cs
- TemplateManager.cs