2222using System . Net ;
2323using System . Net . Http ;
2424using System . Threading . Tasks ;
25+ using X509Certificate2 = System . Security . Cryptography . X509Certificates . X509Certificate2 ;
26+
2527using System . Security . Cryptography . X509Certificates ;
28+ using System . Net . Security ;
2629
2730namespace Confluent . SchemaRegistry
2831{
@@ -55,7 +58,7 @@ public class RestService : IRestService
5558 /// </summary>
5659 public RestService ( string schemaRegistryUrl , int timeoutMs ,
5760 IAuthenticationHeaderValueProvider authenticationHeaderValueProvider , List < X509Certificate2 > certificates ,
58- bool enableSslCertificateVerification )
61+ bool enableSslCertificateVerification , X509Certificate2 sslCaCertificate = null )
5962 {
6063 this . authenticationHeaderValueProvider = authenticationHeaderValueProvider ;
6164
@@ -67,7 +70,7 @@ public RestService(string schemaRegistryUrl, int timeoutMs,
6770 HttpClient client ;
6871 if ( certificates . Count > 0 )
6972 {
70- client = new HttpClient ( CreateHandler ( certificates , enableSslCertificateVerification ) )
73+ client = new HttpClient ( CreateHandler ( certificates , enableSslCertificateVerification , sslCaCertificate ) )
7174 {
7275 BaseAddress = new Uri ( uri , UriKind . Absolute ) , Timeout = TimeSpan . FromMilliseconds ( timeoutMs )
7376 } ;
@@ -92,19 +95,54 @@ private static string SanitizeUri(string uri)
9295 }
9396
9497 private static HttpClientHandler CreateHandler ( List < X509Certificate2 > certificates ,
95- bool enableSslCertificateVerification )
98+ bool enableSslCertificateVerification , X509Certificate2 sslCaCertificate )
9699 {
97100 var handler = new HttpClientHandler ( ) ;
98101 handler . ClientCertificateOptions = ClientCertificateOption . Manual ;
99102
103+ certificates . ForEach ( c => handler . ClientCertificates . Add ( c ) ) ;
104+
100105 if ( ! enableSslCertificateVerification )
101106 {
102- handler . ServerCertificateCustomValidationCallback =
103- ( httpRequestMessage , cert , certChain , policyErrors ) => { return true ; } ;
104- }
107+ handler . ServerCertificateCustomValidationCallback = ( _ , __ , ___ , ____ ) => { return true ; } ;
108+ }
109+ else if ( sslCaCertificate != null )
110+ {
111+ handler . ServerCertificateCustomValidationCallback = ( _ , __ , chain , policyErrors ) => {
112+
113+ if ( policyErrors == SslPolicyErrors . None )
114+ {
115+ return true ;
116+ }
117+
118+
119+ //The second element of the chain should be the issuer of the certificate
120+ if ( chain . ChainElements . Count < 2 )
121+ {
122+ return false ;
123+ }
124+ var connectionCertHash = chain . ChainElements [ 1 ] . Certificate . GetCertHash ( ) ;
125+
126+
127+ var expectedCertHash = sslCaCertificate . GetCertHash ( ) ;
105128
106- certificates . ForEach ( c => handler . ClientCertificates . Add ( c ) ) ;
107- return handler ;
129+ if ( connectionCertHash . Length != expectedCertHash . Length )
130+ {
131+ return false ;
132+ }
133+
134+ for ( int i = 0 ; i < connectionCertHash . Length ; i ++ )
135+ {
136+ if ( connectionCertHash [ i ] != expectedCertHash [ i ] )
137+ {
138+ return false ;
139+ }
140+ }
141+ return true ;
142+ } ;
143+ }
144+
145+ return handler ;
108146 }
109147
110148 private RegisteredSchema SanitizeRegisteredSchema ( RegisteredSchema schema )
0 commit comments