private X509Certificate2 LoadCert(bool ldap, string pemCert)
        {
            try
            {
                const string certStart = "-----BEGIN CERTIFICATE-----";
                const string certEnd   = "-----END CERTIFICATE-----";

                var start = pemCert.IndexOf(certStart) + certStart.Length;
                var end   = pemCert.IndexOf(certEnd, start);

                var certData = Convert.FromBase64String(pemCert.Substring(start, end - start));

                return(new X509Certificate2(certData));
            }
            catch (Exception ex)
            {
                throw SslException.CreateException(ldap, $"The custom certificate could not be loaded: {ex.Message}");
            }
        }
        private Exception GetAppropriateException(bool ldap, X509Chain chain, SslPolicyErrors sslPolicyErrors, bool customCertMismatch)
        {
            var stb = new StringBuilder();

            if (customCertMismatch)
            {
                stb.Append("\r\n✯ The certificate chain does not contain the custom certificate:");
                foreach (var el in chain.ChainElements)
                {
                    stb.Append($"\r\n  → Subject=\"{el.Certificate.Subject}\" (Thumbprint={el.Certificate.Thumbprint}) ");
                }
            }
            if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))
            {
                stb.Append("\r\n✯ The certificate name is mismatched");
            }
            if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNotAvailable))
            {
                stb.Append("\r\n✯ The certificate is unavailable");
            }
            if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) && !customCertMismatch)
            {
                stb.Append("\r\n✯ The certificate chain has errors:");
                foreach (var el in chain.ChainElements)
                {
                    stb.Append($"\r\n  → Subject=\"{el.Certificate.Subject}\" (Thumbprint={el.Certificate.Thumbprint}) ");
                    if (el.ChainElementStatus == null || el.ChainElementStatus.Length == 0)
                    {
                        stb.Append("[OK]");
                    }
                    else
                    {
                        foreach (var status in el.ChainElementStatus)
                        {
                            stb.Append($"[{status.StatusInformation.Trim()}]");
                        }
                    }
                }
            }

            return(SslException.CreateException(ldap, stb.ToString().Trim()));
        }
示例#3
0
        internal static bool DoSslHandshake(SafeSslHandle context, ReadOnlySpan <byte> input, out byte[]?sendBuf, out int sendCount)
        {
            sendBuf   = null;
            sendCount = 0;
            Exception?handshakeException = null;

            if (input.Length > 0)
            {
                if (Ssl.BioWrite(context.InputBio !, ref MemoryMarshal.GetReference(input), input.Length) != input.Length)
                {
                    // Make sure we clear out the error that is stored in the queue
                    throw Crypto.CreateOpenSslCryptographicException();
                }
            }

            int retVal = Ssl.SslDoHandshake(context);

            if (retVal != 1)
            {
                Exception?       innerError;
                Ssl.SslErrorCode error = GetSslError(context, retVal, out innerError);

                if ((retVal != -1) || (error != Ssl.SslErrorCode.SSL_ERROR_WANT_READ))
                {
                    // Handshake failed, but even if the handshake does not need to read, there may be an Alert going out.
                    // To handle that we will fall-through the block below to pull it out, and we will fail after.
                    handshakeException = new SslException(SR.Format(SR.net_ssl_handshake_failed_error, error), innerError);
                    Crypto.ErrClearError();
                }
            }

            sendCount = Crypto.BioCtrlPending(context.OutputBio !);
            if (sendCount > 0)
            {
                sendBuf = new byte[sendCount];

                try
                {
                    sendCount = BioRead(context.OutputBio !, sendBuf, sendCount);
                }
                catch (Exception) when(handshakeException != null)
                {
                    // If we already have handshake exception, ignore any exception from BioRead().
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        // Make sure we clear out the error that is stored in the queue
                        Crypto.ErrClearError();
                        sendBuf   = null;
                        sendCount = 0;
                    }
                }
            }

            if (handshakeException != null)
            {
                throw handshakeException;
            }

            bool stateOk = Ssl.IsSslStateOK(context);

            if (stateOk)
            {
                context.MarkHandshakeCompleted();
            }
            return(stateOk);
        }