private void validateCertificates(X509CertificateCollection certificates)
        {
            ServerContext    context     = (ServerContext)this.Context;
            AlertDescription description = AlertDescription.BadCertificate;

            SSCX.X509Certificate client = null;
            int[] certificateErrors     = null;

            // note: certificate may be null is no certificate is sent
            // (e.g. optional mutual authentication)
            if (certificates.Count > 0)
            {
                X509Certificate leaf = certificates[0];

                ArrayList errors = new ArrayList();

                // SSL specific check - not all certificates can be
                // used to server-side SSL some rules applies after
                // all ;-)
                if (!checkCertificateUsage(leaf))
                {
                    // WinError.h CERT_E_PURPOSE 0x800B0106
                    errors.Add((int)-2146762490);
                }

                X509Chain verify;
                // was a chain supplied ? if so use it, if not
                if (certificates.Count > 1)
                {
                    // if so use it (and don't build our own)
                    X509CertificateCollection chain = new X509CertificateCollection(certificates);
                    chain.Remove(leaf);
                    verify = new X509Chain(chain);
                }
                else
                {
                    // if not, then let's build our own (based on what's available in the stores)
                    verify = new X509Chain();
                }

                bool result = false;

                try
                {
                    result = verify.Build(leaf);
                }
                catch (Exception)
                {
                    result = false;
                }

                if (!result)
                {
                    switch (verify.Status)
                    {
                    case X509ChainStatusFlags.InvalidBasicConstraints:
                        // WinError.h TRUST_E_BASIC_CONSTRAINTS 0x80096019
                        errors.Add((int)-2146869223);
                        break;

                    case X509ChainStatusFlags.NotSignatureValid:
                        // WinError.h TRUST_E_BAD_DIGEST 0x80096010
                        errors.Add((int)-2146869232);
                        break;

                    case X509ChainStatusFlags.NotTimeNested:
                        // WinError.h CERT_E_VALIDITYPERIODNESTING 0x800B0102
                        errors.Add((int)-2146762494);
                        break;

                    case X509ChainStatusFlags.NotTimeValid:
                        // WinError.h CERT_E_EXPIRED 0x800B0101
                        description = AlertDescription.CertificateExpired;
                        errors.Add((int)-2146762495);
                        break;

                    case X509ChainStatusFlags.PartialChain:
                        // WinError.h CERT_E_CHAINING 0x800B010A
                        description = AlertDescription.UnknownCA;
                        errors.Add((int)-2146762486);
                        break;

                    case X509ChainStatusFlags.UntrustedRoot:
                        // WinError.h CERT_E_UNTRUSTEDROOT 0x800B0109
                        description = AlertDescription.UnknownCA;
                        errors.Add((int)-2146762487);
                        break;

                    default:
                        // unknown error
                        description = AlertDescription.CertificateUnknown;
                        errors.Add((int)verify.Status);
                        break;
                    }
                }
                client            = new SSCX.X509Certificate(leaf.RawData);
                certificateErrors = (int[])errors.ToArray(typeof(int));
            }
            else
            {
                certificateErrors = new int[0];
            }

            SSCX.X509CertificateCollection certCollection = new SSCX.X509CertificateCollection();
            foreach (X509Certificate certificate in certificates)
            {
                certCollection.Add(new SSCX.X509Certificate(certificate.RawData));
            }
            if (!context.SslStream.RaiseClientCertificateValidation(client, certificateErrors))
            {
                throw new TlsException(
                          description,
                          "Invalid certificate received from client.");
            }

            this.Context.ClientSettings.ClientCertificate = client;
        }
Beispiel #2
0
        private void validateCertificates(X509CertificateCollection certificates)
        {
            ClientContext    context     = (ClientContext)this.Context;
            AlertDescription description = AlertDescription.BadCertificate;

#if NET_2_0
            if (context.SslStream.HaveRemoteValidation2Callback)
            {
                ValidationResult res = context.SslStream.RaiseServerCertificateValidation2(certificates);
                if (res.Trusted)
                {
                    return;
                }

                long error = res.ErrorCode;
                switch (error)
                {
                case 0x800B0101:
                    description = AlertDescription.CertificateExpired;
                    break;

                case 0x800B010A:
                    description = AlertDescription.UnknownCA;
                    break;

                case 0x800B0109:
                    description = AlertDescription.UnknownCA;
                    break;

                default:
                    description = AlertDescription.CertificateUnknown;
                    break;
                }
                string err = String.Format("0x{0:x}", error);
                throw new TlsException(description, "Invalid certificate received from server. Error code: " + err);
            }
#endif
            // the leaf is the web server certificate
            X509Certificate          leaf = certificates [0];
            X509Cert.X509Certificate cert = new X509Cert.X509Certificate(leaf.RawData);

            ArrayList errors = new ArrayList();

            // SSL specific check - not all certificates can be
            // used to server-side SSL some rules applies after
            // all ;-)
            if (!checkCertificateUsage(leaf))
            {
                // WinError.h CERT_E_PURPOSE 0x800B0106
                errors.Add((int)-2146762490);
            }

            // SSL specific check - does the certificate match
            // the host ?
            if (!checkServerIdentity(leaf))
            {
                // WinError.h CERT_E_CN_NO_MATCH 0x800B010F
                errors.Add((int)-2146762481);
            }

            // Note: building and verifying a chain can take much time
            // so we do it last (letting simple things fails first)

            // Note: In TLS the certificates MUST be in order (and
            // optionally include the root certificate) so we're not
            // building the chain using LoadCertificate (it's faster)

            // Note: IIS doesn't seem to send the whole certificate chain
            // but only the server certificate :-( it's assuming that you
            // already have this chain installed on your computer. duh!
            // http://groups.google.ca/groups?q=IIS+server+certificate+chain&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=85058s%24avd%241%40nnrp1.deja.com&rnum=3

            // we must remove the leaf certificate from the chain
            X509CertificateCollection chain = new X509CertificateCollection(certificates);
            chain.Remove(leaf);
            X509Chain verify = new X509Chain(chain);

            bool result = false;

            try
            {
                result = verify.Build(leaf);
            }
            catch (Exception)
            {
                result = false;
            }

            if (!result)
            {
                switch (verify.Status)
                {
                case X509ChainStatusFlags.InvalidBasicConstraints:
                    // WinError.h TRUST_E_BASIC_CONSTRAINTS 0x80096019
                    errors.Add((int)-2146869223);
                    break;

                case X509ChainStatusFlags.NotSignatureValid:
                    // WinError.h TRUST_E_BAD_DIGEST 0x80096010
                    errors.Add((int)-2146869232);
                    break;

                case X509ChainStatusFlags.NotTimeNested:
                    // WinError.h CERT_E_VALIDITYPERIODNESTING 0x800B0102
                    errors.Add((int)-2146762494);
                    break;

                case X509ChainStatusFlags.NotTimeValid:
                    // WinError.h CERT_E_EXPIRED 0x800B0101
                    description = AlertDescription.CertificateExpired;
                    errors.Add((int)-2146762495);
                    break;

                case X509ChainStatusFlags.PartialChain:
                    // WinError.h CERT_E_CHAINING 0x800B010A
                    description = AlertDescription.UnknownCA;
                    errors.Add((int)-2146762486);
                    break;

                case X509ChainStatusFlags.UntrustedRoot:
                    // WinError.h CERT_E_UNTRUSTEDROOT 0x800B0109
                    description = AlertDescription.UnknownCA;
                    errors.Add((int)-2146762487);
                    break;

                default:
                    // unknown error
                    description = AlertDescription.CertificateUnknown;
                    errors.Add((int)verify.Status);
                    break;
                }
            }

            int[] certificateErrors = (int[])errors.ToArray(typeof(int));

            if (!context.SslStream.RaiseServerCertificateValidation(
                    cert,
                    certificateErrors))
            {
                throw new TlsException(
                          description,
                          "Invalid certificate received from server.");
            }
        }