1

有効な SSL 証明書のみを受け入れるように構成されている PostgreSQL データベースへの接続を確立できません。適切な証明書とキーを使用して pgAdmin III を使用して接続できますが、Npgsql では動作しません。データベースへの接続を開こうとすると、System.IO.IOException: The authentication or decryption has failed. これが私のコードです:

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

1 に答える 1

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;ディレクティブを追加します。
    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...ます。これにより、不足している型に関する多くのエラーが発生します。特に、Mono 型を使用する 3 セットのデリゲート/イベント コンボに関するものです。これらのコールバックはすべて Mono のSslClientStreamクラスに関連付けられているため、エラーは常に 3 つのグループで表示されます。ValidateServerCertificate3 つの各グループを削除し、1 つのデリゲート/イベントに置き換えます。この単一のイベントは、SslStream上記のステップ 1.3 で使用されたクラスのコンストラクターで使用する必要があります。

  3. への変更によりNpgsqlConnection.cs、他のファイルなどでより多くのエラーが発生しますNpgsqlConnector.csNpgsqlConnectorPool.cs、修正方法は同じです。3 つの Mono ベースのコールバックを新しいValidateServerCertificate.

すべてが完了すると、Npgsql は Mono コンポーネントなしで、(私にとっては) SSL 証明書認証を使用して使用できます。

私の github でのプル リクエストは、こちらにあります

于 2013-06-15T11:47:00.350 に答える