/// <summary> /// Validate certificate method as callback to the socket /// </summary> /// <param name="dwType">Data type pointed to by pCertChain (SSL_CERT_X.509 if X509 certs chain)</param> /// <param name="pvArg">Pointer to application-defined context (passed by the SSLVALIDATECERTHOOK structure)</param> /// <param name="dwChainLen">Number of certificates pointed to by pCertChain (It will always be equal to one)</param> /// <param name="pCertChain">Pointer to the root certificate</param> /// <param name="dwFlags">Will contain SSL_CERT_FLAG_ISSUER_UNKNOWN if the root issuer of the certificate could not be found in the CA database</param> /// <param name="certificate">X509 certificate</param> /// <returns>Result</returns> private int ValidateCertificateInternal(uint dwType, IntPtr pvArg, uint dwChainLen, IntPtr pCertChain, uint dwFlags, out X509Certificate2 certificate) { certificate = null; // check if it is a valid X509 certificate if (dwType != SSL_CERT_X509) return SSL_ERR_BAD_TYPE; // in debug mode accept self-signed certificates #if !DEBUG // check if issuer is unknown if ((dwFlags & SSL_CERT_FLAG_ISSUER_UNKNOWN) != 0) return SSL_ERR_CERT_UNKNOWN; #endif // sslsock.h : pCertChain is a pointer to BLOB structure // - first 4 bytes are the certificate size // - following bytes are the certificate itself // read certificate size int certSize = Marshal.ReadInt32(pCertChain); // pointer to start of certificate data IntPtr pCertData = Marshal.ReadIntPtr(new IntPtr(pCertChain.ToInt32() + sizeof(int))); byte[] certData = new byte[certSize]; // read certificate data bytes for (int i = 0; i < certSize; i++) certData[i] = Marshal.ReadByte(pCertData, (int)i); // create X509 certificate from raw bytes try { certificate = new X509Certificate2(certData); } catch (ArgumentException) { return SSL_ERR_BAD_DATA; } catch (CryptographicException) { return SSL_ERR_BAD_DATA; } // check expiration date if (DateTime.Now > DateTime.Parse(certificate.GetExpirationDateString(), CultureInfo.CurrentCulture)) return SSL_ERR_CERT_EXPIRED; // check the effective date if (DateTime.Now < DateTime.Parse(certificate.GetEffectiveDateString(), CultureInfo.CurrentCulture)) return SSL_ERR_FAILED; // validate the certificate CN with provided host name string host = Marshal.PtrToStringBSTR(pvArg); if (!certificate.GetName().Contains("CN=" + host)) return SSL_ERR_FAILED; return SSL_ERR_OKAY; }
private int ValidateCert(uint dwType, IntPtr pvArg, uint dwChainLen, IntPtr pCertChain, uint dwFlags) { //According to http://msdn.microsoft.com/en-us/library/ms940451.aspx: // //- dwChainLen is always 1 //- Windows CE performs the cert chain validation //- pvArg is the context data we passed into the SO_SSL_SET_VALIDATE_CERT_HOOK call so in our //- case is the host name // //So here we are responsible for validating the dates on the certificate and the CN if (dwType != SSL_CERT_X59) return SSL_ERR_BAD_TYPE; //When in debug mode let self-signed certificates through ... #if !DEBUG if ((dwFlags & SSL_CERT_FLAG_ISSUER_UNKNOWN) != 0) return SSL_ERR_CERT_UNKNOWN; #endif Debug.Assert(dwChainLen == 1); //Note about the note: an unmanaged long is 32 bits, unlike a managed long which is 64. I was missing //this fact when I wrote the comment. So the docs are accurate. //NOTE: The documentation says pCertChain is a pointer to a LPBLOB struct: // // {ulong size, byte* data} // //in reality the size is a 32 bit integer (not 64). int certSize = Marshal.ReadInt32(pCertChain); IntPtr pData = Marshal.ReadIntPtr(new IntPtr(pCertChain.ToInt32() + sizeof(int))); byte[] certData = new byte[certSize]; for (int i = 0; i < certSize; i++) certData[i] = Marshal.ReadByte(pData, (int)i); X509Certificate2 cert; try { cert = new X509Certificate2(certData); } catch (ArgumentException) { return SSL_ERR_BAD_DATA; } catch (CryptographicException) { return SSL_ERR_BAD_DATA; } //Validate the expiration date if (DateTime.Now > DateTime.Parse(cert.GetExpirationDateString(), CultureInfo.CurrentCulture)) return SSL_ERR_CERT_EXPIRED; //Validate the effective date if (DateTime.Now < DateTime.Parse(cert.GetEffectiveDateString(), CultureInfo.CurrentCulture)) return SSL_ERR_FAILED; string certName = cert.GetName(); Debug.WriteLine(certName); //Validate the CN string host = ReadAnsiString(pvArg); if (!certName.Contains("CN=" + host)) return SSL_ERR_FAILED; return SSL_ERR_OKAY; }
public static void SendCertificateToRevocationList(X509Certificate2 cert) { RemoveCert(cert); certificates.Remove(cert); revocationList.Add(cert); string messageToLog = "Certificate " + cert.GetName() + "has been revoked."; logger.WriteToLog(messageToLog, EventLogEntryType.Information); }