@@ -47,84 +47,83 @@ internal static void SetSslOptions(EasyRequest easy, ClientCertificateOption cli
4747 CancellationToken . None , TaskContinuationOptions . ExecuteSynchronously , TaskScheduler . Default ) ;
4848 }
4949
50- // Register the callback with libcurl. We need to register even if there's no user-provided
51- // server callback and even if there are no client certificates, because we support verifying
52- // server certificates against more than those known to OpenSSL.
53- if ( CurlSslVersionDescription . IndexOf ( "openssl/1.0" , StringComparison . OrdinalIgnoreCase ) != - 1 )
50+ // Configure the options. Our best support is when targeting OpenSSL/1.0. For other backends,
51+ // we fall back to a minimal amount of support, and may throw a PNSE based on the options requested.
52+ if ( CurlSslVersionDescription . IndexOf ( Interop . Http . OpenSsl10Description , StringComparison . OrdinalIgnoreCase ) != - 1 )
5453 {
55- CURLcode answer = easy . SetSslCtxCallback ( s_sslCtxCallback , userPointer ) ;
56- switch ( answer )
57- {
58- case CURLcode . CURLE_OK :
59- // We successfully registered. If we'll be invoking a user-provided callback to verify the server
60- // certificate as part of that, disable libcurl's verification of the host name. The user's callback
61- // needs to be given the opportunity to examine the cert, and our logic will determine whether
62- // the host name matches and will inform the callback of that.
63- if ( easy . _handler . ServerCertificateValidationCallback != null )
64- {
65- easy . SetCurlOption ( Interop . Http . CURLoption . CURLOPT_SSL_VERIFYHOST , 0 ) ; // don't verify the peer cert's hostname
66- // We don't change the SSL_VERIFYPEER setting, as setting it to 0 will cause
67- // SSL and libcurl to ignore the result of the server callback.
68- }
54+ // Register the callback with libcurl. We need to register even if there's no user-provided
55+ // server callback and even if there are no client certificates, because we support verifying
56+ // server certificates against more than those known to OpenSSL.
57+ SetSslOptionsForSupportedBackend ( easy , certProvider , userPointer ) ;
58+ }
59+ else
60+ {
61+ // Newer versions of OpenSSL, and other non-OpenSSL backends, do not currently support callbacks.
62+ // That means we'll throw a PNSE if a callback is required.
63+ SetSslOptionsForUnsupportedBackend ( easy , certProvider ) ;
64+ }
65+ }
6966
70- // The allowed SSL protocols will be set in the configuration callback.
71- break ;
72-
73- case CURLcode . CURLE_UNKNOWN_OPTION : // Curl 7.38 and prior
74- case CURLcode . CURLE_NOT_BUILT_IN : // Curl 7.39 and later
75- // It's ok if we failed to register the callback if all of the defaults are in play
76- // with relation to handling of certificates. But if that's not the case, failing to
77- // register the callback will result in those options not being factored in, which is
78- // a significant enough error that we need to fail.
79- EventSourceTrace ( "CURLOPT_SSL_CTX_FUNCTION not supported: {0}" , answer , easy : easy ) ;
80- if ( certProvider != null ||
81- easy . _handler . ServerCertificateValidationCallback != null ||
82- easy . _handler . CheckCertificateRevocationList )
83- {
84- throw new PlatformNotSupportedException (
85- SR . Format ( SR . net_http_unix_invalid_certcallback_option , CurlVersionDescription , CurlSslVersionDescription ) ) ;
86- }
67+ private static void SetSslOptionsForSupportedBackend ( EasyRequest easy , ClientCertificateProvider certProvider , IntPtr userPointer )
68+ {
69+ CURLcode answer = easy . SetSslCtxCallback ( s_sslCtxCallback , userPointer ) ;
70+ switch ( answer )
71+ {
72+ case CURLcode . CURLE_OK :
73+ // We successfully registered. If we'll be invoking a user-provided callback to verify the server
74+ // certificate as part of that, disable libcurl's verification of the host name; we need to get
75+ // the callback from libcurl even if the host name doesn't match, so we take on the responsibility
76+ // of doing the host name match in the callback prior to invoking the user's delegate.
77+ if ( easy . _handler . ServerCertificateValidationCallback != null )
78+ {
79+ easy . SetCurlOption ( Interop . Http . CURLoption . CURLOPT_SSL_VERIFYHOST , 0 ) ;
80+ // But don't change the CURLOPT_SSL_VERIFYPEER setting, as setting it to 0 will
81+ // cause SSL and libcurl to ignore the result of the server callback.
82+ }
8783
88- // Since there won't be a callback to configure the allowed SSL protocols, configure them here .
89- SetSslVersion ( easy ) ;
84+ // The allowed SSL protocols will be set in the configuration callback .
85+ break ;
9086
91- break ;
87+ case CURLcode . CURLE_UNKNOWN_OPTION : // Curl 7.38 and prior
88+ case CURLcode . CURLE_NOT_BUILT_IN : // Curl 7.39 and later
89+ EventSourceTrace ( "CURLOPT_SSL_CTX_FUNCTION not supported: {0}" , answer , easy : easy ) ;
90+ SetSslOptionsForUnsupportedBackend ( easy , certProvider ) ;
91+ break ;
9292
93- default :
94- ThrowIfCURLEError ( answer ) ;
95- break ;
96- }
93+ default :
94+ ThrowIfCURLEError ( answer ) ;
95+ break ;
9796 }
98- else
97+ }
98+
99+ private static void SetSslOptionsForUnsupportedBackend ( EasyRequest easy , ClientCertificateProvider certProvider )
100+ {
101+ if ( certProvider != null )
99102 {
100- // For newer versions of openssl throw PNSE, if default not used.
101- if ( certProvider != null )
102- {
103- throw new PlatformNotSupportedException (
104- SR . Format (
105- SR . net_http_libcurl_clientcerts_notsupported ,
106- CurlVersionDescription , CurlSslVersionDescription ) ) ;
107- }
103+ throw new PlatformNotSupportedException ( SR . Format ( SR . net_http_libcurl_clientcerts_notsupported , CurlVersionDescription , CurlSslVersionDescription ) ) ;
104+ }
105+
106+ if ( easy . _handler . CheckCertificateRevocationList )
107+ {
108+ throw new PlatformNotSupportedException ( SR . Format ( SR . net_http_libcurl_revocation_notsupported , CurlVersionDescription , CurlSslVersionDescription ) ) ;
109+ }
108110
109- if ( easy . _handler . ServerCertificateValidationCallback != null )
111+ if ( easy . _handler . ServerCertificateValidationCallback != null )
112+ {
113+ if ( easy . ServerCertificateValidationCallbackAcceptsAll )
110114 {
111- throw new PlatformNotSupportedException (
112- SR . Format (
113- SR . net_http_libcurl_callback_notsupported ,
114- CurlVersionDescription , CurlSslVersionDescription ) ) ;
115+ EventSourceTrace ( "Warning: Disabling peer and host verification per {0}" , nameof ( HttpClientHandler . DangerousAcceptAnyServerCertificateValidator ) , easy : easy ) ;
116+ easy . SetCurlOption ( Interop . Http . CURLoption . CURLOPT_SSL_VERIFYPEER , 0 ) ;
117+ easy . SetCurlOption ( Interop . Http . CURLoption . CURLOPT_SSL_VERIFYHOST , 0 ) ;
115118 }
116-
117- if ( easy . _handler . CheckCertificateRevocationList )
119+ else
118120 {
119- throw new PlatformNotSupportedException (
120- SR . Format (
121- SR . net_http_libcurl_revocation_notsupported ,
122- CurlVersionDescription , CurlSslVersionDescription ) ) ;
121+ throw new PlatformNotSupportedException ( SR . Format ( SR . net_http_libcurl_callback_notsupported , CurlVersionDescription , CurlSslVersionDescription ) ) ;
123122 }
124-
125- // In case of defaults configure the allowed SSL protocols.
126- SetSslVersion ( easy ) ;
127123 }
124+
125+ // In case of defaults configure the allowed SSL protocols.
126+ SetSslVersion ( easy ) ;
128127 }
129128
130129 private static void SetSslVersion ( EasyRequest easy , IntPtr sslCtx = default ( IntPtr ) )
0 commit comments