2013-06-15 5 views
1

У меня возникли проблемы с установкой подключения к базе данных PostgreSQL, которая настроена только для принятия действительного сертификата SSL. Я могу подключиться с помощью pgAdmin III с соответствующим сертификатом и ключом, но я не могу заставить его работать с Npgsql. Когда я пытаюсь открыть соединение с базой данных, я получаю System.IO.IOException: The authentication or decryption has failed. Вот мой код:Ошибки SSL при использовании проверки подлинности Npgsql и SSL

NpgsqlConnectionStringBuilder csb = new NpgsqlConnectionStringBuilder(); 
csb.Database = "database"; 
csb.Host = "psql-server"; 
csb.UserName = "dreamlax"; // must match Common Name of client certificate 
csb.SSL = true; 
csb.SslMode = SslMode.Require; 

NpgsqlConnection conn = new NpgsqlConnection(csb.ConnectionString); 
conn.ProvideClientCertificatesCallback += new ProvideClientCertificatesCallback(Database_ProvideClientCertificatesCallback); 
conn.CertificateSelectionCallback += new CertificateSelectionCallback(Database_CertificateSelectionCallback); 
conn.CertificateValidationCallback += new CertificateValidationCallback(Database_CertificateValidationCallback); 
conn.PrivateKeySelectionCallback += new PrivateKeySelectionCallback(Database_PrivateKeySelectionCallback); 

conn.Open(); //System.IO.IOException: The authentication or decryption has failed 

Обратные вызовы определяются следующим образом:

static void Database_ProvideClientCertificates(X509CertificateCollection clienteCertis) 
{ 
    X509Certificate2 cert = new X509Certificate2("mycert.pfx", "passphrase"); 
    clienteCertis.Add(cert); 
} 

static X509Certificate Database_CertificateSelectionCallback(X509CertificateCollection clientCerts, X509Certificate serverCert, string host, X509CertificateCollection serverRequestedCerts) 
{ 
    return clienteCertis[0]; 
} 

static AsymmetricAlgorithm Database_PrivateKeySelectionCallback(X509Certificate cert, string host) 
{ 
    X509Cerficate2 thisCert = cert as X509Certificate2; 
    if (cert != null) 
     return cert.PrivateKey; 
    else 
     return null; 
} 

static bool MyCertificateValidationCallback(X509Certificate certificate, int[] certificateErrors) 
{ 
    // forego server validation for now 
    return true; 
} 

Я установить контрольные точки, подтверждающие, что каждый обратный вызов был что-то действительное возвращение, но все-таки IOException брошен.

ответ

4

Я исправил эту проблему, изменив источник Npgsql. Вместо использования Mono's Mono.Security.Protocol.Tls.SslClientStream вместо этого я использовал его вместо System.Net.Security.SslStream. Это были шаги, которые я взял:

  1. Изменить NpgsqlClosedState.cs:

    1. Удалите using Mono.Security.Protocol.Tls; директиву и один под ней.
    2. Добавить директиву using System.Net.Security;.
    3. В NpgsqlClosedState.Open() методе, где он говорит if (response == 'S'), изменил его:

      if (response == 'S') 
      { 
          //create empty collection 
          X509CertificateCollection clientCertificates = new X509CertificateCollection(); 
      
          //trigger the callback to fetch some certificates 
          context.DefaultProvideClientCertificatesCallback(clientCertificates); 
      
          // Create SslStream, wrapping around NpgsqlStream 
          SslStream sstream = new SslStream(stream, true, delegate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors) 
          { 
           // Create callback to validate server cert here 
           return true; 
          }); 
          sstream.AuthenticateAsClient(context.Host, clientCertificates, System.Security.Authentication.SslProtocols.Default, false); 
          stream = sstream; 
      } 
      
  2. Изменить NpgsqlConnection.cs, удалите using Mono... директивы. Это вызовет ряд ошибок в отношении отсутствующих типов, в частности, они будут касаться 3 наборов делегатов/событийных комбо, которые используют типы Mono. Ошибки всегда появляются в группах по три, потому что эти обратные вызовы связаны с классом Mono SslClientStream. Удалите каждую группу из трех и замените ее одним делегатом/событием ValidateServerCertificate. Это единственное событие должно использоваться в конструкторе для класса SslStream, который использовался в шаге 1.3 выше.

  3. Изменения в NpgsqlConnection.cs будут вызывать больше ошибок в других файлах NpgsqlConnector.cs, NpgsqlConnectorPool.cs и т.д., но исправить это то же самое, заменить обратные вызовы 3 Моно на основе с новым ValidateServerCertificate.

После того, как все это сделано, Npgsql можно использовать без компонентов Mono и с (для меня) с проверкой подлинности SSL-сертификата.

Мой запрос на тягу на github можно найти here.

+0

Благодарим вас за отзыв! Не могли бы вы создать запрос на растяжение с вашим патчем? http://git.npgsql.org Это было бы очень полезно для тех, кто получает ошибки при использовании Npgsql и SSL. Заранее спасибо. –

+0

@FranciscoJunior: Привет, я создал запрос на pull. Я новичок в git, поэтому не уверен, правильно ли я это сделал. – dreamlax

Смежные вопросы