private static CURLcode SslCtxCallback(IntPtr curl, IntPtr sslCtx, IntPtr userPointer)
{
EasyRequest easy;
if (!TryGetEasyRequest(curl, out easy))
{
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
}
// Configure the SSL protocols allowed.
SslProtocols protocols = easy._handler.SslProtocols;
if (protocols == SslProtocols.None)
{
// If None is selected, let OpenSSL use its defaults, but with SSL2/3 explicitly disabled.
// Since the shim/OpenSSL work on a disabling system, where any protocols for which bits aren't
// set are disabled, we set all of the bits other than those we want disabled.
#pragma warning disable 0618 // the enum values are obsolete
protocols = ~(SslProtocols.Ssl2 | SslProtocols.Ssl3);
#pragma warning restore 0618
}
Interop.Ssl.SetProtocolOptions(sslCtx, protocols);
// Configure the SSL server certificate verification callback.
Interop.Ssl.SslCtxSetCertVerifyCallback(sslCtx, s_sslVerifyCallback, curl);
// If a client certificate provider was provided, also configure the client certificate callback.
if (userPointer != IntPtr.Zero)
{
try
{
// Provider is passed in via a GCHandle. Get the provider, which contains
// the client certificate callback delegate.
GCHandle handle = GCHandle.FromIntPtr(userPointer);
ClientCertificateProvider provider = (ClientCertificateProvider)handle.Target;
if (provider == null)
{
Debug.Fail($"Expected non-null provider in {nameof(SslCtxCallback)}");
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
}
// Register the callback.
Interop.Ssl.SslCtxSetClientCertCallback(sslCtx, provider._callback);
EventSourceTrace("Registered client certificate callback.", easy: easy);
}
catch (Exception e)
{
Debug.Fail($"Exception in {nameof(SslCtxCallback)}", e.ToString());
return CURLcode.CURLE_ABORTED_BY_CALLBACK;
}
}
return CURLcode.CURLE_OK;
}