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())); }
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); }