[pgsqlclient-checkins] SF.net SVN: pgsqlclient: [19] pgsqlclient/source
Status: Inactive
Brought to you by:
carlosga_fb
From: <car...@us...> - 2006-03-13 15:33:40
|
Revision: 19 Author: carlosga_fb Date: 2006-03-13 07:33:13 -0800 (Mon, 13 Mar 2006) ViewCVS: http://svn.sourceforge.net/pgsqlclient/?rev=19&view=rev Log Message: ----------- Changes on the Secure Socket Layer implementation for better handling of Server Certificates. Implementation of Server Certificate Validation Callback and Client Certificate Selection Callback Modified Paths: -------------- pgsqlclient/source/PostgreSql.Data.PostgreSqlClient.suo pgsqlclient/source/SecureSocketLayer/Net/Security/LocalCertificateSelectionCallback.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/ISecureFactory.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/IX509ChainValidator.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/SecureSession.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/X509ChainValidator.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Ssl/Client/SslClientFactory.cs pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Tls/Client/TlsClientFactory.cs pgsqlclient/source/SecureSocketLayer/Net/Security/RemoteCertificateValidationCallback.cs pgsqlclient/source/SecureSocketLayer/Net/Security/SslStream.cs pgsqlclient/source/SecureSocketLayer/SecureSocketLayer.csproj.user pgsqlclient/source/SecureSocketLayerTest/Program.cs Modified: pgsqlclient/source/PostgreSql.Data.PostgreSqlClient.suo =================================================================== (Binary files differ) Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/LocalCertificateSelectionCallback.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/LocalCertificateSelectionCallback.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/LocalCertificateSelectionCallback.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -32,8 +32,8 @@ public delegate X509Certificate LocalCertificateSelectionCallback( object sender, string targetHost, - X509CertificateCollection localCertificates, - X509Certificate localCertificate, + X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers); } Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/ISecureFactory.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/ISecureFactory.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/ISecureFactory.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -25,6 +25,8 @@ #if NET_2_0 using System; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; namespace SecureSocketLayer.Net.Security.Providers.Common { @@ -48,7 +50,7 @@ IRecordEncryptor CreateRecordEncryptor(SecureSession session); IRecordDecryptor CreateRecordDecryptor(SecureSession session); IRecordMACManager CreateMACManager(SecureSession session); - IX509ChainValidator CreateX509ChainValidator(); + IX509ChainValidator CreateX509ChainValidator(X509Chain chain, ExchangeAlgorithmType exchangeAlgorithmType); #endregion } Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/IX509ChainValidator.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/IX509ChainValidator.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/IX509ChainValidator.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -33,7 +33,7 @@ { #region \xB7 Methods \xB7 - SslPolicyErrors Validate(X509CertificateCollection certificates, CipherSuite cipherSuite, string targetHost); + SslPolicyErrors Validate(X509CertificateCollection certificates, string targetHost); #endregion } Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/SecureSession.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/SecureSession.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/SecureSession.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -36,23 +36,23 @@ { #region \xB7 Callback Fields \xB7 - private RemoteCertificateValidationCallback serverCertValidation; - private LocalCertificateSelectionCallback clientCertSelection; + private RemoteCertificateValidationCallback userCertificateValidationCallback; + private LocalCertificateSelectionCallback userCertificateSelectionCallback; #endregion #region \xB7 Callback Properties \xB7 - public RemoteCertificateValidationCallback ServerCertValidation + public RemoteCertificateValidationCallback UserCertificateValidationCallback { - get { return this.serverCertValidation; } - set { this.serverCertValidation = value; } + get { return this.userCertificateValidationCallback; } + set { this.userCertificateValidationCallback = value; } } - public LocalCertificateSelectionCallback ClientCertSelection + public LocalCertificateSelectionCallback UserCertificateSelectionCallback { - get { return this.clientCertSelection; } - set { this.clientCertSelection = value; } + get { return this.userCertificateSelectionCallback; } + set { this.userCertificateSelectionCallback = value; } } #endregion @@ -81,7 +81,8 @@ private Stream outputStream; private X509CertificateCollection remoteCertificates; private X509CertificateCollection localCertificates; - private X509Certificate clientCertificate; + private X509Certificate clientCertificate; + private X509Chain remoteCertificateChain; private RSAParameters rsaParameters; private MemoryStreamEx handshakeMessages; @@ -503,33 +504,60 @@ private void RemoteCertificateReceived(X509Certificate certificate) { + if (this.remoteCertificateChain == null) + { + this.remoteCertificateChain = new X509Chain(); + + try + { + this.remoteCertificateChain.Build(new X509Certificate2(certificate)); + } + catch + { + this.remoteCertificateChain.Reset(); + } + } + this.RemoteCertificates.Add(certificate); } private void ReceivedRemoteCertificateChain() { - IX509ChainValidator validator = this.secureFactory.CreateX509ChainValidator(); + SslPolicyErrors errors = SslPolicyErrors.None; - SslPolicyErrors errors = validator.Validate(this.RemoteCertificates, this.CipherSuite, this.TargetHost); + if (this.remoteCertificateChain.ChainElements.Count > 0) + { + IX509ChainValidator validator = this.secureFactory.CreateX509ChainValidator( + this.remoteCertificateChain, + this.CipherSuite.ExchangeAlgorithmType); -#warning Build the X509Chain + errors |= validator.Validate(this.RemoteCertificates, this.TargetHost); + } + else + { + errors |= SslPolicyErrors.RemoteCertificateChainErrors; + } - if (!this.ServerCertValidation(this, this.RemoteCertificates[0], null, errors)) - { - throw new SecureException("Invalid certificate received form server."); - } + if (this.UserCertificateValidationCallback != null) + { + if (!this.UserCertificateValidationCallback(this, this.RemoteCertificates[0], this.remoteCertificateChain, errors)) + { + throw new SecureException("The remote certificate is invalid according to the validation procedure."); + } + } + else + { + if (errors != SslPolicyErrors.None) + { + throw new SecureException("The remote certificate is invalid according to the validation procedure."); + } + } } private void ClientCertificateSelected(X509Certificate certificate) - { - this.clientCertificate = certificate; - - this.clientCertificate = this.ClientCertSelection( - this, - this.TargetHost, - this.LocalCertificates, - this.ClientCertificate, - null); + { + this.clientCertificate = this.UserCertificateSelectionCallback( + this, this.TargetHost, this.LocalCertificates, this.RemoteCertificates[0], null); if (this.clientCertificate == null) { Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/X509ChainValidator.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/X509ChainValidator.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Common/X509ChainValidator.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -33,18 +33,27 @@ namespace SecureSocketLayer.Net.Security.Providers.Common { internal sealed class X509ChainValidator : IX509ChainValidator - { - #region \xB7 Constructors \xB7 + { + #region \xB7 Fields \xB7 - public X509ChainValidator() + private X509Chain certificateChain; + private ExchangeAlgorithmType exchangeAlgorithmType; + + #endregion + + #region \xB7 Constructors \xB7 + + public X509ChainValidator(X509Chain certificateChain, ExchangeAlgorithmType exchangeAlgorithmType) { + this.certificateChain = certificateChain; + this.exchangeAlgorithmType = exchangeAlgorithmType; } #endregion #region \xB7 IX509ChainValidator Methods \xB7 - public SslPolicyErrors Validate(X509CertificateCollection certificates, CipherSuite cipherSuite, string targetHost) + public SslPolicyErrors Validate(X509CertificateCollection certificates, string targetHost) { SslPolicyErrors errors = SslPolicyErrors.None; @@ -54,7 +63,7 @@ // SSL specific check - not all certificates can be // used to server-side SSL some rules applies after // all ;-) - if (!this.CheckCertificateUsage(leaf, cipherSuite)) + if (!this.CheckCertificateUsage(leaf)) { // WinError.h CERT_E_PURPOSE 0x800B0106 errors |= SslPolicyErrors.RemoteCertificateChainErrors; @@ -68,36 +77,6 @@ errors |= SslPolicyErrors.RemoteCertificateNameMismatch; } - // Note: building and verifying a chain can take much time - // so we do it last(letting simple things fails first) - - // Note: In TLS the certificates MUST be in order(and - // optionally include the root certificate) so we're not - // building the chain using LoadCertificate(it's faster) - - // Note: IIS doesn't seem to send the whole certificate chain - // but only the server certificate :- ( it's assuming that you - // already have this chain installed on your computer. duh! - // http://groups.google.ca/groups?q=IIS+server+certificate+chain&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=85058s%24avd%241%40nnrp1.deja.com&rnum=3 - - X509Chain certificateChain = new X509Chain(); - - bool result = false; - - try - { - certificateChain.Build(leaf); - } - catch (Exception) - { - result = false; - } - - if (!result) - { - errors |= SslPolicyErrors.RemoteCertificateChainErrors; - } - return errors; } @@ -107,7 +86,7 @@ // Note: this method only works for RSA certificates // DH certificates requires some changes - does anyone use one ? - private bool CheckCertificateUsage(X509Certificate2 cert, CipherSuite cipherSuite) + private bool CheckCertificateUsage(X509Certificate2 cert) { // certificate extensions are required for this // we "must" accept older certificates without proofs @@ -118,7 +97,7 @@ X509KeyUsageFlags ku = X509KeyUsageFlags.None; - switch (cipherSuite.ExchangeAlgorithmType) + switch (this.exchangeAlgorithmType) { case ExchangeAlgorithmType.RsaSign: ku = X509KeyUsageFlags.DigitalSignature; Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Ssl/Client/SslClientFactory.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Ssl/Client/SslClientFactory.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Ssl/Client/SslClientFactory.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -25,9 +25,10 @@ #if NET_2_0 using System; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; using SecureSocketLayer.Net.Security.Providers.Common; using SecureSocketLayer.Net.Security.Providers.Common.Client; -using System.Security.Authentication; namespace SecureSocketLayer.Net.Security.Providers.Ssl.Client { @@ -120,9 +121,9 @@ return new SslClientRecordMACManager(session); } - public IX509ChainValidator CreateX509ChainValidator() + public IX509ChainValidator CreateX509ChainValidator(X509Chain cerficateChain, ExchangeAlgorithmType exchangeAlgorithmType) { - return new X509ChainValidator(); + return new X509ChainValidator(cerficateChain, exchangeAlgorithmType); } #endregion Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Tls/Client/TlsClientFactory.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Tls/Client/TlsClientFactory.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/Providers/Tls/Client/TlsClientFactory.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -25,9 +25,10 @@ #if NET_2_0 using System; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; using SecureSocketLayer.Net.Security.Providers.Common; using SecureSocketLayer.Net.Security.Providers.Common.Client; -using System.Security.Authentication; namespace SecureSocketLayer.Net.Security.Providers.Tls.Client { @@ -120,9 +121,9 @@ return new TlsClientRecordMACManager(session); } - public IX509ChainValidator CreateX509ChainValidator() + public IX509ChainValidator CreateX509ChainValidator(X509Chain cerficateChain, ExchangeAlgorithmType exchangeAlgorithmType) { - return new X509ChainValidator(); + return new X509ChainValidator(cerficateChain, exchangeAlgorithmType); } #endregion Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/RemoteCertificateValidationCallback.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/RemoteCertificateValidationCallback.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/RemoteCertificateValidationCallback.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -30,10 +30,7 @@ namespace SecureSocketLayer.Net.Security { public delegate bool RemoteCertificateValidationCallback( - object sender, - X509Certificate certificate, - System.Security.Cryptography.X509Certificates.X509Chain chain, - SslPolicyErrors sslPolicyErrors); + object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors); } #endif Modified: pgsqlclient/source/SecureSocketLayer/Net/Security/SslStream.cs =================================================================== --- pgsqlclient/source/SecureSocketLayer/Net/Security/SslStream.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/Net/Security/SslStream.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -38,8 +38,8 @@ { #region · Callback Fields · - private RemoteCertificateValidationCallback certValidationCallback; - private LocalCertificateSelectionCallback certSelectionCallback; + private RemoteCertificateValidationCallback userCertificateValidationCallback; + private LocalCertificateSelectionCallback userCertificateSelectionCallback; #endregion @@ -51,7 +51,7 @@ private object read; private object write; private bool disposed; - private object negotiate; + private object syncObject; #endregion @@ -289,12 +289,19 @@ { } - public SslStream(Stream innerStream, bool leaveStreamOpen, RemoteCertificateValidationCallback certValidationCallback) - : this(innerStream, leaveStreamOpen, certValidationCallback, null) + public SslStream( + Stream innerStream, + bool leaveStreamOpen, + RemoteCertificateValidationCallback userCertificateValidationCallback) + : this(innerStream, leaveStreamOpen, userCertificateValidationCallback, null) { } - public SslStream(Stream innerStream, bool leaveStreamOpen, RemoteCertificateValidationCallback certValidationCallback, LocalCertificateSelectionCallback certSelectionCallback) + public SslStream( + Stream innerStream, + bool leaveStreamOpen, + RemoteCertificateValidationCallback userCertificateValidationCallback, + LocalCertificateSelectionCallback userCertificateSelectionCallback) : base(innerStream, leaveStreamOpen) { if (innerStream == null) @@ -307,11 +314,13 @@ throw new ArgumentNullException("stream is not both readable and writable."); } - this.innerStream = innerStream; - this.certValidationCallback = certValidationCallback; - this.certSelectionCallback = certSelectionCallback; - this.read = new object(); - this.write = new object(); + this.userCertificateValidationCallback = userCertificateValidationCallback; + this.userCertificateSelectionCallback = userCertificateSelectionCallback; + + this.innerStream = innerStream; + this.read = new object(); + this.write = new object(); + this.syncObject = new object(); } #endregion @@ -330,9 +339,11 @@ // Note: Async code may have problem if they can't ensure that // the Negotiate phase isn't done during a read operation. // System.Net.HttpWebRequest protects itself from that problem - lock (this.negotiate) + lock (this.syncObject) { this.session = new SecureSession(this.innerStream); + this.session.UserCertificateValidationCallback = this.userCertificateValidationCallback; + this.session.UserCertificateSelectionCallback = this.userCertificateSelectionCallback; this.session.AuthenticateAsClient( targetHost, clientCertificates, @@ -359,7 +370,7 @@ // Note: Async code may have problem if they can't ensure that // the Negotiate phase isn't done during a read operation. // System.Net.HttpWebRequest protects itself from that problem - lock (this.negotiate) + lock (this.syncObject) { this.session = new SecureSession(this.innerStream); this.session.AuthenticateAsServer( @@ -669,26 +680,6 @@ } #endregion - - #region · Event Handlers · - - private bool ServerCertificateValidation( - X509Certificate certificate, - int[] certificateErrors) - { - throw new NotImplementedException(); - } - - private X509Certificate ClientCertificateSelection( - X509CertificateCollection clientCertificates, - X509Certificate serverCertificate, - string targetHost, - X509CertificateCollection serverRequestedCertificates) - { - throw new NotImplementedException(); - } - - #endregion } } Modified: pgsqlclient/source/SecureSocketLayer/SecureSocketLayer.csproj.user =================================================================== --- pgsqlclient/source/SecureSocketLayer/SecureSocketLayer.csproj.user 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayer/SecureSocketLayer.csproj.user 2006-03-13 15:33:13 UTC (rev 19) @@ -12,6 +12,6 @@ <ApplicationRevision>0</ApplicationRevision> <FallbackCulture>en-US</FallbackCulture> <VerifyUploadedFiles>false</VerifyUploadedFiles> - <ProjectView>ShowAllFiles</ProjectView> + <ProjectView>ProjectFiles</ProjectView> </PropertyGroup> </Project> \ No newline at end of file Modified: pgsqlclient/source/SecureSocketLayerTest/Program.cs =================================================================== --- pgsqlclient/source/SecureSocketLayerTest/Program.cs 2006-03-13 13:25:41 UTC (rev 18) +++ pgsqlclient/source/SecureSocketLayerTest/Program.cs 2006-03-13 15:33:13 UTC (rev 19) @@ -1,8 +1,7 @@ using System; using System.Net; using System.Net.Sockets; -using System.Net.Security; -using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; namespace SecureSocketsLayer.Test { @@ -10,19 +9,62 @@ { static void Main(string[] args) { + try + { + // MicrosoftSslStreamTest(); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + + try + { + CustomSslStreamTest(); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + } + + static void MicrosoftSslStreamTest() + { IPAddress hostadd = Dns.GetHostEntry("localhost").AddressList[0]; IPEndPoint endPoint = new IPEndPoint(hostadd, 4433); - Socket socket = new Socket( - AddressFamily.InterNetwork, - SocketType.Stream, - ProtocolType.Tcp); + Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); socket.Connect(endPoint); - SslStream ssl = new SslStream(new NetworkStream(socket, true)); + System.Net.Security.SslStream ssl = new System.Net.Security.SslStream(new NetworkStream(socket, true)); ssl.AuthenticateAsClient("localhost"); ssl.Close(); } + + static void CustomSslStreamTest() + { + IPAddress hostadd = Dns.GetHostEntry("localhost").AddressList[0]; + IPEndPoint endPoint = new IPEndPoint(hostadd, 4433); + + Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + socket.Connect(endPoint); + + SecureSocketLayer.Net.Security.RemoteCertificateValidationCallback serverCallback = new SecureSocketLayer.Net.Security.RemoteCertificateValidationCallback(CertificateValidation); + + SecureSocketLayer.Net.Security.SslStream ssl = new SecureSocketLayer.Net.Security.SslStream(new NetworkStream(socket, true), false, serverCallback); + ssl.AuthenticateAsClient("localhost"); + ssl.Close(); + } + + static bool CertificateValidation( + object sender, + X509Certificate certificate, + X509Chain chain, + SecureSocketLayer.Net.Security.SslPolicyErrors sslPolicyErrors) + { + return true; + } } } \ No newline at end of file This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |