// // Get certificate_authorities list, according to RFC 5246, Section 7.4.4. // Used only by client SSL code, never returns null. // private string[] GetRequestCertificateAuthorities() { string[] issuers = Array.Empty <string>(); if (IsValidContext) { issuers = CertificateValidationPal.GetRequestCertificateAuthorities(_securityContext); } return(issuers); }
private static SecurityStatusPal HandshakeInternal( SafeFreeCredentials credential, ref SafeDeleteSslContext?context, ReadOnlySpan <byte> inputBuffer, ref byte[]?outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Debug.Assert(!credential.IsInvalid); try { SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context); if ((null == context) || context.IsInvalid) { sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials) !, sslAuthenticationOptions); context = sslContext; if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer) { Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost); } if (sslAuthenticationOptions.CertificateContext == null && sslAuthenticationOptions.CertSelectionDelegate != null) { // certificate was not provided but there is user callback. We can break handshake if server asks for certificate // and we can try to get it based on remote certificate and trusted issuers. Interop.AppleCrypto.SslBreakOnCertRequested(sslContext.SslContext, true); } if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired) { Interop.AppleCrypto.SslSetAcceptClientCert(sslContext.SslContext); } } if (inputBuffer.Length > 0) { sslContext !.Write(inputBuffer); } SafeSslHandle sslHandle = sslContext !.SslContext; SecurityStatusPal status = PerformHandshake(sslHandle); if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { // we should not be here if CertSelectionDelegate is null but better check before dereferencing.. if (sslAuthenticationOptions.CertSelectionDelegate != null) { X509Certificate2?remoteCert = null; try { string[] issuers = CertificateValidationPal.GetRequestCertificateAuthorities(context); remoteCert = CertificateValidationPal.GetRemoteCertificate(context); if (sslAuthenticationOptions.ClientCertificates == null) { sslAuthenticationOptions.ClientCertificates = new X509CertificateCollection(); } X509Certificate2 clientCertificate = (X509Certificate2)sslAuthenticationOptions.CertSelectionDelegate(sslAuthenticationOptions.TargetHost !, sslAuthenticationOptions.ClientCertificates, remoteCert, issuers); if (clientCertificate != null) { SafeDeleteSslContext.SetCertificate(sslContext.SslContext, SslStreamCertificateContext.Create(clientCertificate)); } } finally { remoteCert?.Dispose(); } } // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK. status = PerformHandshake(sslHandle); } outputBuffer = sslContext.ReadPendingWrites(); return(status); } catch (Exception exc) { return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc)); } }