namespace com.hitrust.Security.Certificates
|
|
{
|
|
using com.hitrust.Security;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
|
|
public class CertificateChain
|
|
{
|
|
private com.hitrust.Security.Certificates.Certificate m_Certificate;
|
|
private IntPtr m_Handle;
|
|
|
|
public CertificateChain(com.hitrust.Security.Certificates.Certificate cert) : this(cert, null)
|
|
{
|
|
}
|
|
|
|
public CertificateChain(com.hitrust.Security.Certificates.Certificate cert, CertificateStore additional) : this(cert, additional, CertificateChainOptions.Default)
|
|
{
|
|
}
|
|
|
|
public CertificateChain(com.hitrust.Security.Certificates.Certificate cert, CertificateStore additional, CertificateChainOptions options)
|
|
{
|
|
if (cert == null)
|
|
{
|
|
throw new ArgumentNullException();
|
|
}
|
|
IntPtr hAdditionalStore = (additional == null) ? IntPtr.Zero : additional.Handle;
|
|
ChainParameters pChainPara = new ChainParameters {
|
|
cbSize = Marshal.SizeOf(typeof(ChainParameters)),
|
|
RequestedUsagecUsageIdentifier = 0,
|
|
RequestedUsagedwType = 0,
|
|
RequestedUsagergpszUsageIdentifier = IntPtr.Zero
|
|
};
|
|
if (SspiProvider.CertGetCertificateChain(IntPtr.Zero, cert.Handle, IntPtr.Zero, hAdditionalStore, ref pChainPara, (int) options, IntPtr.Zero, ref this.m_Handle) == 0)
|
|
{
|
|
throw new CertificateException("Unable to find the certificate chain.");
|
|
}
|
|
this.m_Certificate = cert;
|
|
}
|
|
|
|
public virtual IAsyncResult BeginVerifyChain(string server, AuthType type, VerificationFlags flags, AsyncCallback callback, object asyncState)
|
|
{
|
|
CertificateVerificationResult state = new CertificateVerificationResult(this, server, type, flags, callback, asyncState);
|
|
if (!ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartVerification), state))
|
|
{
|
|
throw new CertificateException("Could not schedule the certificate chain for verification.");
|
|
}
|
|
return state;
|
|
}
|
|
|
|
public virtual CertificateStatus EndVerifyChain(IAsyncResult ar)
|
|
{
|
|
CertificateVerificationResult result;
|
|
if (ar == null)
|
|
{
|
|
throw new ArgumentNullException();
|
|
}
|
|
try
|
|
{
|
|
result = (CertificateVerificationResult) ar;
|
|
}
|
|
catch
|
|
{
|
|
throw new ArgumentException();
|
|
}
|
|
if (result.Chain != this)
|
|
{
|
|
throw new ArgumentException();
|
|
}
|
|
if (result.HasEnded)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
if (result.ThrowException != null)
|
|
{
|
|
throw result.ThrowException;
|
|
}
|
|
result.HasEnded = true;
|
|
return result.Status;
|
|
}
|
|
|
|
~CertificateChain()
|
|
{
|
|
if (this.m_Handle != IntPtr.Zero)
|
|
{
|
|
SspiProvider.CertFreeCertificateChain(this.m_Handle);
|
|
this.m_Handle = IntPtr.Zero;
|
|
}
|
|
}
|
|
|
|
public virtual com.hitrust.Security.Certificates.Certificate[] GetCertificates()
|
|
{
|
|
ArrayList list = new ArrayList();
|
|
IntPtr handle = ((com.hitrust.Security.Certificates.Certificate) this.Certificate.Clone()).Handle;
|
|
CertificateStoreCollection store = this.Certificate.Store as CertificateStoreCollection;
|
|
if (store != null)
|
|
{
|
|
store = new CertificateStoreCollection(store);
|
|
}
|
|
else
|
|
{
|
|
store = new CertificateStoreCollection(new CertificateStore[0]);
|
|
store.AddStore(new CertificateStore(this.Certificate.m_Context.hCertStore, true));
|
|
}
|
|
store.AddStore(new CertificateStore("Root"));
|
|
IntPtr hCertStore = store.Handle;
|
|
while (handle != IntPtr.Zero)
|
|
{
|
|
list.Add(new com.hitrust.Security.Certificates.Certificate(handle, true));
|
|
int pdwFlags = 0;
|
|
handle = SspiProvider.CertGetIssuerCertificateFromStore(hCertStore, handle, IntPtr.Zero, ref pdwFlags);
|
|
}
|
|
return (com.hitrust.Security.Certificates.Certificate[]) list.ToArray(typeof(com.hitrust.Security.Certificates.Certificate));
|
|
}
|
|
|
|
protected void StartVerification(object state)
|
|
{
|
|
if (state != null)
|
|
{
|
|
CertificateVerificationResult result;
|
|
CertificateStatus status;
|
|
try
|
|
{
|
|
result = (CertificateVerificationResult) state;
|
|
}
|
|
catch
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
status = this.VerifyChain(result.Server, result.Type, result.Flags);
|
|
}
|
|
catch (CertificateException exception)
|
|
{
|
|
result.VerificationCompleted(exception, CertificateStatus.OtherError);
|
|
return;
|
|
}
|
|
catch (Exception exception2)
|
|
{
|
|
result.VerificationCompleted(new CertificateException("Could not verify the certificate chain.", exception2), CertificateStatus.OtherError);
|
|
return;
|
|
}
|
|
result.VerificationCompleted(null, status);
|
|
}
|
|
}
|
|
|
|
public virtual CertificateStatus VerifyChain(string server, AuthType type)
|
|
{
|
|
return this.VerifyChain(server, type, VerificationFlags.None);
|
|
}
|
|
|
|
public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags)
|
|
{
|
|
CertificateStatus otherError;
|
|
IntPtr zero = IntPtr.Zero;
|
|
IntPtr ptr = IntPtr.Zero;
|
|
try
|
|
{
|
|
if (server == null)
|
|
{
|
|
zero = IntPtr.Zero;
|
|
}
|
|
else
|
|
{
|
|
zero = Marshal.StringToHGlobalUni(server);
|
|
}
|
|
SslPolicyParameters structure = new SslPolicyParameters {
|
|
cbSize = Marshal.SizeOf(typeof(SslPolicyParameters)),
|
|
dwAuthType = (int) type,
|
|
pwszServerName = zero,
|
|
fdwChecks = (int) flags
|
|
};
|
|
ptr = Marshal.AllocHGlobal(structure.cbSize);
|
|
Marshal.StructureToPtr(structure, ptr, false);
|
|
ChainPolicyParameters pPolicyPara = new ChainPolicyParameters {
|
|
cbSize = Marshal.SizeOf(typeof(ChainPolicyParameters)),
|
|
dwFlags = (int) flags,
|
|
pvExtraPolicyPara = ptr
|
|
};
|
|
ChainPolicyStatus pPolicyStatus = new ChainPolicyStatus {
|
|
cbSize = Marshal.SizeOf(typeof(ChainPolicyStatus))
|
|
};
|
|
if (SspiProvider.CertVerifyCertificateChainPolicy(new IntPtr(4), this.m_Handle, ref pPolicyPara, ref pPolicyStatus) == 0)
|
|
{
|
|
throw new CertificateException("Unable to verify the certificate.");
|
|
}
|
|
if (Enum.IsDefined(typeof(CertificateStatus), pPolicyStatus.dwError))
|
|
{
|
|
return (CertificateStatus) pPolicyStatus.dwError;
|
|
}
|
|
otherError = CertificateStatus.OtherError;
|
|
}
|
|
finally
|
|
{
|
|
if (ptr != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(ptr);
|
|
}
|
|
if (zero != IntPtr.Zero)
|
|
{
|
|
Marshal.FreeHGlobal(zero);
|
|
}
|
|
}
|
|
return otherError;
|
|
}
|
|
|
|
public virtual CertificateStatus VerifyChain(string server, AuthType type, VerificationFlags flags, byte[] crl)
|
|
{
|
|
CertificateStatus status = this.VerifyChain(server, type, flags);
|
|
if ((status != CertificateStatus.ValidCertificate) || (crl == null))
|
|
{
|
|
return status;
|
|
}
|
|
try
|
|
{
|
|
if (!this.m_Certificate.VerifyRevocation(crl))
|
|
{
|
|
return CertificateStatus.Revoked;
|
|
}
|
|
return status;
|
|
}
|
|
catch
|
|
{
|
|
return CertificateStatus.RevocationFailure;
|
|
}
|
|
}
|
|
|
|
protected com.hitrust.Security.Certificates.Certificate Certificate
|
|
{
|
|
get
|
|
{
|
|
return this.m_Certificate;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|