private static void SetSslOptionsForSupportedBackend(EasyRequest easy, ClientCertificateProvider certProvider, IntPtr userPointer) { CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer); EventSourceTrace("Callback registration result: {0}", answer, easy: easy); switch (answer) { case CURLcode.CURLE_OK: // We successfully registered. If we'll be invoking a user-provided callback to verify the server // certificate as part of that, disable libcurl's verification of the host name; we need to get // the callback from libcurl even if the host name doesn't match, so we take on the responsibility // of doing the host name match in the callback prior to invoking the user's delegate. if (easy._handler.ServerCertificateCustomValidationCallback != null) { easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSL_VERIFYHOST, 0); // But don't change the CURLOPT_SSL_VERIFYPEER setting, as setting it to 0 will // cause SSL and libcurl to ignore the result of the server callback. } SetSslOptionsForCertificateStore(easy); // The allowed SSL protocols will be set in the configuration callback. break; case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later SetSslOptionsForUnsupportedBackend(easy, certProvider); break; default: ThrowIfCURLEError(answer); break; } }
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption) { // Disable SSLv2/SSLv3, allow TLSv1.* easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSLVERSION, (long)Interop.Http.CurlSslVersion.CURL_SSLVERSION_TLSv1); IntPtr userPointer = IntPtr.Zero; if (clientCertOption == ClientCertificateOption.Automatic) { ClientCertificateProvider certProvider = new ClientCertificateProvider(); userPointer = GCHandle.ToIntPtr(certProvider._gcHandle); easy.Task.ContinueWith((_, state) => ((IDisposable)state).Dispose(), certProvider, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } else { Debug.Assert(clientCertOption == ClientCertificateOption.Manual, "ClientCertificateOption is manual or automatic"); } CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer); switch (answer) { case CURLcode.CURLE_OK: break; // Curl 7.38 and prior case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.39 and later case CURLcode.CURLE_NOT_BUILT_IN: EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported. Platform default HTTPS chain building in use"); if (clientCertOption == ClientCertificateOption.Automatic) { throw new PlatformNotSupportedException(SR.net_http_unix_invalid_client_cert_option); } break; default: ThrowIfCURLEError(answer); break; } }
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption) { // Disable SSLv2/SSLv3, allow TLSv1.* easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSLVERSION, (long)Interop.Http.CurlSslVersion.CURL_SSLVERSION_TLSv1); IntPtr userPointer = IntPtr.Zero; if (clientCertOption == ClientCertificateOption.Automatic) { ClientCertificateProvider certProvider = new ClientCertificateProvider(); userPointer = GCHandle.ToIntPtr(certProvider._gcHandle); easy.Task.ContinueWith((_, state) => ((IDisposable)state).Dispose(), certProvider, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } else { Debug.Assert(clientCertOption == ClientCertificateOption.Manual, "ClientCertificateOption is manual or automatic"); } CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer); switch (answer) { case CURLcode.CURLE_OK: break; // Curl 7.38 and prior case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.39 and later case CURLcode.CURLE_NOT_BUILT_IN: EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported. Platform default HTTPS chain building in use"); if (clientCertOption == ClientCertificateOption.Automatic) { throw new PlatformNotSupportedException(SR.net_http_unix_invalid_client_cert_option); } break; default: ThrowIfCURLEError(answer); break; } }
internal static void SetSslOptions(EasyRequest easy) { CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback); switch (answer) { case CURLcode.CURLE_OK: break; // Curl 7.38 and prior case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.39 and later case CURLcode.CURLE_NOT_BUILT_IN: VerboseTrace("CURLOPT_SSL_CTX_FUNCTION is not supported, platform default https chain building in use"); break; default: ThrowIfCURLEError(answer); break; } }
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption) { Debug.Assert(clientCertOption == ClientCertificateOption.Automatic || clientCertOption == ClientCertificateOption.Manual); // Create a client certificate provider if client certs may be used. X509Certificate2Collection clientCertificates = easy._handler._clientCertificates; ClientCertificateProvider certProvider = clientCertOption == ClientCertificateOption.Automatic ? new ClientCertificateProvider(null) : // automatic clientCertificates?.Count > 0 ? new ClientCertificateProvider(clientCertificates) : // manual with certs null; // manual without certs IntPtr userPointer = IntPtr.Zero; if (certProvider != null) { // The client cert provider needs to be passed through to the callback, and thus // we create a GCHandle to keep it rooted. This handle needs to be cleaned up // when the request has completed, and a simple and pay-for-play way to do that // is by cleaning it up in a continuation off of the request. userPointer = GCHandle.ToIntPtr(certProvider._gcHandle); easy.Task.ContinueWith((_, state) => ((IDisposable)state).Dispose(), certProvider, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } // Register the callback with libcurl. We need to register even if there's no user-provided // server callback and even if there are no client certificates, because we support verifying // server certificates against more than those known to OpenSSL. CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer); switch (answer) { case CURLcode.CURLE_OK: // We successfully registered. If we'll be invoking a user-provided callback to verify the server // certificate as part of that, disable libcurl's verification of the host name. The user's callback // needs to be given the opportunity to examine the cert, and our logic will determine whether // the host name matches and will inform the callback of that. if (easy._handler.ServerCertificateValidationCallback != null) { easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSL_VERIFYHOST, 0); // don't verify the peer cert's hostname // We don't change the SSL_VERIFYPEER setting, as setting it to 0 will cause // SSL and libcurl to ignore the result of the server callback. } // The allowed SSL protocols will be set in the configuration callback. break; case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later // It's ok if we failed to register the callback if all of the defaults are in play // with relation to handling of certificates. But if that's not the case, failing to // register the callback will result in those options not being factored in, which is // a significant enough error that we need to fail. EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported: {0}", answer, easy: easy); if (certProvider != null || easy._handler.ServerCertificateValidationCallback != null || easy._handler.CheckCertificateRevocationList) { throw new PlatformNotSupportedException( SR.Format(SR.net_http_unix_invalid_certcallback_option, CurlVersionDescription, CurlSslVersionDescription)); } // Since there won't be a callback to configure the allowed SSL protocols, configure them here. SetSslVersion(easy); break; default: ThrowIfCURLEError(answer); break; } }
internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption clientCertOption) { Debug.Assert(clientCertOption == ClientCertificateOption.Automatic || clientCertOption == ClientCertificateOption.Manual); // Create a client certificate provider if client certs may be used. X509Certificate2Collection clientCertificates = easy._handler._clientCertificates; ClientCertificateProvider certProvider = clientCertOption == ClientCertificateOption.Automatic ? new ClientCertificateProvider(null) : // automatic clientCertificates?.Count > 0 ? new ClientCertificateProvider(clientCertificates) : // manual with certs null; // manual without certs IntPtr userPointer = IntPtr.Zero; if (certProvider != null) { // The client cert provider needs to be passed through to the callback, and thus // we create a GCHandle to keep it rooted. This handle needs to be cleaned up // when the request has completed, and a simple and pay-for-play way to do that // is by cleaning it up in a continuation off of the request. userPointer = GCHandle.ToIntPtr(certProvider._gcHandle); easy.Task.ContinueWith((_, state) => ((IDisposable)state).Dispose(), certProvider, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default); } // Register the callback with libcurl. We need to register even if there's no user-provided // server callback and even if there are no client certificates, because we support verifying // server certificates against more than those known to OpenSSL. CURLcode answer = easy.SetSslCtxCallback(s_sslCtxCallback, userPointer); switch (answer) { case CURLcode.CURLE_OK: // We successfully registered. If we'll be invoking a user-provided callback to verify the server // certificate as part of that, disable libcurl's verification of the host name. The user's callback // needs to be given the opportunity to examine the cert, and our logic will determine whether // the host name matches and will inform the callback of that. if (easy._handler.ServerCertificateValidationCallback != null) { easy.SetCurlOption(Interop.Http.CURLoption.CURLOPT_SSL_VERIFYHOST, 0); // don't verify the peer cert's hostname // We don't change the SSL_VERIFYPEER setting, as setting it to 0 will cause // SSL and libcurl to ignore the result of the server callback. } // The allowed SSL protocols will be set in the configuration callback. break; case CURLcode.CURLE_UNKNOWN_OPTION: // Curl 7.38 and prior case CURLcode.CURLE_NOT_BUILT_IN: // Curl 7.39 and later // It's ok if we failed to register the callback if all of the defaults are in play // with relation to handling of certificates. But if that's not the case, failing to // register the callback will result in those options not being factored in, which is // a significant enough error that we need to fail. EventSourceTrace("CURLOPT_SSL_CTX_FUNCTION not supported: {0}", answer); if (certProvider != null || easy._handler.ServerCertificateValidationCallback != null || easy._handler.CheckCertificateRevocationList) { throw new PlatformNotSupportedException( SR.Format(SR.net_http_unix_invalid_certcallback_option, CurlVersionDescription, CurlSslVersionDescription)); } // Since there won't be a callback to configure the allowed SSL protocols, configure them here. SetSslVersion(easy); break; default: ThrowIfCURLEError(answer); break; } }