Example #1
0
        /// <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;
        }
Example #2
0
        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;
        }
Example #3
0
        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);
        }