2013-06-15 7 views
1

유효한 SSL 인증서 만 수락하도록 구성된 PostgreSQL 데이터베이스에 연결하는 데 문제가 있습니다. 적절한 인증서와 키를 사용하여 pgAdmin III를 사용하여 연결할 수 있지만 Npgsql을 사용하여 작업 할 수 없습니다. 데이터베이스 연결을 열려고하면 System.IO.IOException: The authentication or decryption has failed이 표시됩니다.Npgsql 및 SSL 인증서 인증을 사용할 때 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 

콜백은 다음과 같이 정의된다 : I는 각 콜백이 유효 뭔가를 반환 만, 여전히 예외 : IOException가 슬로우되는 것을 확인 중단 점을 설정

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; 
} 

여기 내 코드입니다.

답변

4

Npgsql 소스를 수정하여이 문제를 해결했습니다. Mono의 Mono.Security.Protocol.Tls.SslClientStream을 사용하는 대신 System.Net.Security.SslStream 대신 사용하도록 변경했습니다.

  1. 수정 NpgsqlClosedState.cs :

    1. using Mono.Security.Protocol.Tls; 지시어와 그 아래 하나를 제거 다음은 내가 수행 한 단계 있었다.
    2. using System.Net.Security; 지시문을 추가하십시오.

      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.csusing Mono... 지시를 제거 : 그것은 if (response == 'S')을 말한다 NpgsqlClosedState.Open() 방법에서는

  3. 가로 변경되었습니다. 이로 인해 누락 된 유형에 대한 여러 가지 오류가 발생하며 특히 Mono 유형을 사용하는 3 세트의 위임/이벤트 조합과 관련됩니다. 이 콜백은 모두 Mono의 SslClientStream 클래스와 연결되어 있기 때문에 오류는 항상 세 그룹으로 표시됩니다. 3 개의 각 그룹을 제거하고 단일 ValidateServerCertificate 대리인/이벤트로 바꿉니다. 이 단일 이벤트는 위의 1.3 단계에서 사용 된 SslStream 클래스의 생성자에서 사용해야합니다. NpgsqlConnection.cs

  4. 변화는 다른 파일 NpgsqlConnector.cs, NpgsqlConnectorPool.cs 등 더 많은 오류를 유발하지만 수정은 동일, 새로운 ValidateServerCertificate로 3 모노 기반의 콜백을 교체합니다.

일단 완료되면 Npgsql을 모노 구성 요소없이 (나에게) 작동하는 SSL 인증서 인증없이 사용할 수 있습니다.

github에 대한 내 요청은 here입니다.

+0

의견을 보내 주셔서 감사합니다. 패치로 풀 요청을 만드시겠습니까? http://git.npgsql.org 이것은 Npgsql과 SSL을 사용할 때 오류를받는 다른 사람들에게 매우 유용 할 것입니다. 미리 감사드립니다. –

+0

@FranciscoJunior : 안녕하세요, 요청을 생성했습니다. 나는 git를 처음 사용하기 때문에 제대로했는지 확신 할 수 없습니다. – dreamlax