diff options
author | Benoit Foucher <benoit@zeroc.com> | 2015-04-28 19:27:04 +0200 |
---|---|---|
committer | Benoit Foucher <benoit@zeroc.com> | 2015-04-28 19:27:04 +0200 |
commit | e6e102cc642e78cf9da55645c82f5bfe6eacb76d (patch) | |
tree | ab5861ee9ad2a909fa0dc8f25b1b12e0dd1d6527 /csharp/src | |
parent | Fixed ICE-6443 and other SSL fixes (diff) | |
download | ice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.tar.bz2 ice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.tar.xz ice-e6e102cc642e78cf9da55645c82f5bfe6eacb76d.zip |
Fixed previous commit which was incomplete
Diffstat (limited to 'csharp/src')
-rw-r--r-- | csharp/src/Ice/PropertyNames.cs | 13 | ||||
-rw-r--r-- | csharp/src/Ice/TcpEndpointI.cs | 35 | ||||
-rw-r--r-- | csharp/src/Ice/TcpTransceiver.cs | 38 | ||||
-rw-r--r-- | csharp/src/Ice/WSEndpoint.cs | 15 | ||||
-rw-r--r-- | csharp/src/Ice/WSTransceiver.cs | 21 | ||||
-rw-r--r-- | csharp/src/IceSSL/EndpointI.cs | 38 | ||||
-rw-r--r-- | csharp/src/IceSSL/SSLEngine.cs | 63 | ||||
-rw-r--r-- | csharp/src/IceSSL/TransceiverI.cs | 184 | ||||
-rw-r--r-- | csharp/src/IceSSL/Util.cs | 14 |
9 files changed, 312 insertions, 109 deletions
diff --git a/csharp/src/Ice/PropertyNames.cs b/csharp/src/Ice/PropertyNames.cs index 279d5cb0ff2..cd2190d1f47 100644 --- a/csharp/src/Ice/PropertyNames.cs +++ b/csharp/src/Ice/PropertyNames.cs @@ -6,7 +6,7 @@ // ICE_LICENSE file included in this distribution. // // ********************************************************************** -// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Dec 9 12:08:30 2014 +// Generated by makeprops.py from file ./config/PropertyNames.xml, Tue Apr 28 17:34:50 2015 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -188,6 +188,7 @@ namespace IceInternal new Property(@"^Ice\.Warn\.UnusedProperties$", false, null), new Property(@"^Ice\.CacheMessageBuffers$", false, null), new Property(@"^Ice\.ThreadInterruptSafe$", false, null), + new Property(@"^Ice\.Voip$", false, null), null }; @@ -969,8 +970,9 @@ namespace IceInternal public static Property[] IceSSLProps = { new Property(@"^IceSSL\.Alias$", false, null), - new Property(@"^IceSSL\.CertAuthDir$", false, null), - new Property(@"^IceSSL\.CertAuthFile$", false, null), + new Property(@"^IceSSL\.CAs$", false, null), + new Property(@"^IceSSL\.CertAuthDir$", true, null), + new Property(@"^IceSSL\.CertAuthFile$", true, null), new Property(@"^IceSSL\.CertStore$", false, null), new Property(@"^IceSSL\.CertFile$", false, null), new Property(@"^IceSSL\.CertVerifier$", false, null), @@ -982,10 +984,10 @@ namespace IceInternal new Property(@"^IceSSL\.DHParams$", false, null), new Property(@"^IceSSL\.EntropyDaemon$", false, null), new Property(@"^IceSSL\.FindCert$", false, null), - new Property(@"^IceSSL\.FindCert\.[^\s]+$", false, null), + new Property(@"^IceSSL\.FindCert\.[^\s]+$", true, null), new Property(@"^IceSSL\.ImportCert\.[^\s]+$", true, null), new Property(@"^IceSSL\.InitOpenSSL$", false, null), - new Property(@"^IceSSL\.KeyFile$", false, null), + new Property(@"^IceSSL\.KeyFile$", true, null), new Property(@"^IceSSL\.KeySet$", false, null), new Property(@"^IceSSL\.Keychain$", false, null), new Property(@"^IceSSL\.KeychainPassword$", false, null), @@ -1008,6 +1010,7 @@ namespace IceInternal new Property(@"^IceSSL\.Truststore$", false, null), new Property(@"^IceSSL\.TruststorePassword$", false, null), new Property(@"^IceSSL\.TruststoreType$", false, null), + new Property(@"^IceSSL\.UsePlatformCAs$", false, null), new Property(@"^IceSSL\.VerifyDepthMax$", false, null), new Property(@"^IceSSL\.VerifyPeer$", false, null), null diff --git a/csharp/src/Ice/TcpEndpointI.cs b/csharp/src/Ice/TcpEndpointI.cs index fcfa84ab0c3..71b0e498230 100644 --- a/csharp/src/Ice/TcpEndpointI.cs +++ b/csharp/src/Ice/TcpEndpointI.cs @@ -15,7 +15,7 @@ namespace IceInternal using System; using System.Globalization; - sealed class TcpEndpointI : IPEndpointI + sealed class TcpEndpointI : IPEndpointI, WSEndpointDelegate { public TcpEndpointI(ProtocolInstance instance, string ho, int po, EndPoint sourceAddr, int ti, string conId, bool co) : @@ -71,6 +71,39 @@ namespace IceInternal return info; } + private sealed class WSInfoI : Ice.WSEndpointInfo + { + public WSInfoI(IPEndpointI e) + { + _endpoint = e; + } + + public override short type() + { + return _endpoint.type(); + } + + public override bool datagram() + { + return _endpoint.datagram(); + } + + public override bool secure() + { + return _endpoint.secure(); + } + + private IPEndpointI _endpoint; + } + + public Ice.EndpointInfo getWSInfo(string resource) + { + WSInfoI info = new WSInfoI(this); + fillEndpointInfo(info); + info.resource = resource; + return info; + } + public override int timeout() { return _timeout; diff --git a/csharp/src/Ice/TcpTransceiver.cs b/csharp/src/Ice/TcpTransceiver.cs index 11f7fd49578..c434f1f33db 100644 --- a/csharp/src/Ice/TcpTransceiver.cs +++ b/csharp/src/Ice/TcpTransceiver.cs @@ -12,10 +12,11 @@ namespace IceInternal using System; using System.ComponentModel; using System.Diagnostics; + using System.Collections.Generic; using System.Net; using System.Net.Sockets; - sealed class TcpTransceiver : Transceiver + sealed class TcpTransceiver : Transceiver, WSTransceiverDelegate { public Socket fd() { @@ -88,17 +89,15 @@ namespace IceInternal public Ice.ConnectionInfo getInfo() { Ice.TCPConnectionInfo info = new Ice.TCPConnectionInfo(); - if(_stream.fd() != null) - { - EndPoint localEndpoint = Network.getLocalAddress(_stream.fd()); - info.localAddress = Network.endpointAddressToString(localEndpoint); - info.localPort = Network.endpointPort(localEndpoint); - EndPoint remoteEndpoint = Network.getRemoteAddress(_stream.fd()); - info.remoteAddress = Network.endpointAddressToString(remoteEndpoint); - info.remotePort = Network.endpointPort(remoteEndpoint); - info.rcvSize = Network.getRecvBufferSize(_stream.fd()); - info.sndSize = Network.getSendBufferSize(_stream.fd()); - } + fillConnectionInfo(info); + return info; + } + + public Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers) + { + Ice.WSConnectionInfo info = new Ice.WSConnectionInfo(); + fillConnectionInfo(info); + info.headers = headers; return info; } @@ -130,6 +129,21 @@ namespace IceInternal _stream = stream; } + private void fillConnectionInfo(Ice.TCPConnectionInfo info) + { + if(_stream.fd() != null) + { + EndPoint localEndpoint = Network.getLocalAddress(_stream.fd()); + info.localAddress = Network.endpointAddressToString(localEndpoint); + info.localPort = Network.endpointPort(localEndpoint); + EndPoint remoteEndpoint = Network.getRemoteAddress(_stream.fd()); + info.remoteAddress = Network.endpointAddressToString(remoteEndpoint); + info.remotePort = Network.endpointPort(remoteEndpoint); + info.rcvSize = Network.getRecvBufferSize(_stream.fd()); + info.sndSize = Network.getSendBufferSize(_stream.fd()); + } + } + private readonly ProtocolInstance _instance; private readonly StreamSocket _stream; } diff --git a/csharp/src/Ice/WSEndpoint.cs b/csharp/src/Ice/WSEndpoint.cs index 27f7816d5e9..5d0660726c8 100644 --- a/csharp/src/Ice/WSEndpoint.cs +++ b/csharp/src/Ice/WSEndpoint.cs @@ -14,6 +14,15 @@ namespace IceInternal using System.Collections.Generic; using System.Globalization; + // + // Delegate interface implemented by TcpEndpoint or IceSSL.EndpointI or any endpoint that WS can + // delegate to. + // + public interface WSEndpointDelegate + { + Ice.EndpointInfo getWSInfo(string resource); + }; + sealed class WSEndpoint : EndpointI { internal WSEndpoint(ProtocolInstance instance, EndpointI del, string res) @@ -71,10 +80,8 @@ namespace IceInternal public override Ice.EndpointInfo getInfo() { - InfoI info = new InfoI(this); - _delegate.fillEndpointInfo(info); - info.resource = _resource; - return info; + Debug.Assert(_delegate is WSEndpointDelegate); + return ((WSEndpointDelegate)_delegate).getWSInfo(_resource); } public override short type() diff --git a/csharp/src/Ice/WSTransceiver.cs b/csharp/src/Ice/WSTransceiver.cs index 7218027bdc2..98dd6f8fdae 100644 --- a/csharp/src/Ice/WSTransceiver.cs +++ b/csharp/src/Ice/WSTransceiver.cs @@ -16,6 +16,15 @@ namespace IceInternal using System.Security.Cryptography; using System.Text; + // + // Delegate interface implemented by TcpTransceiver or IceSSL.TransceiverI or any endpoint that WS can + // delegate to. + // + public interface WSTransceiverDelegate + { + Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers); + }; + sealed class WSTransceiver : Transceiver { public Socket fd() @@ -629,16 +638,8 @@ namespace IceInternal public Ice.ConnectionInfo getInfo() { - Ice.IPConnectionInfo di = (Ice.IPConnectionInfo)_delegate.getInfo(); - Ice.WSConnectionInfo info = new Ice.WSConnectionInfo(); - info.localAddress = di.localAddress; - info.localPort = di.localPort; - info.remoteAddress = di.remoteAddress; - info.remotePort = di.remotePort; - info.rcvSize = di.rcvSize; - info.sndSize = di.sndSize; - info.headers = _parser.getHeaders(); - return info; + Debug.Assert(_delegate is WSTransceiverDelegate); + return ((WSTransceiverDelegate)_delegate).getWSInfo(_parser.getHeaders()); } public void checkSendSize(Buffer buf) diff --git a/csharp/src/IceSSL/EndpointI.cs b/csharp/src/IceSSL/EndpointI.cs index edc04dd09d9..8c02bad421a 100644 --- a/csharp/src/IceSSL/EndpointI.cs +++ b/csharp/src/IceSSL/EndpointI.cs @@ -15,7 +15,7 @@ namespace IceSSL using System.Net; using System.Globalization; - sealed class EndpointI : IceInternal.IPEndpointI + sealed class EndpointI : IceInternal.IPEndpointI, IceInternal.WSEndpointDelegate { internal EndpointI(Instance instance, string ho, int po, EndPoint sourceAddr, int ti, string conId, bool co) : base(instance, ho, po, sourceAddr, conId) @@ -76,6 +76,42 @@ namespace IceSSL return info; } + private sealed class WSSInfoI : IceSSL.WSSEndpointInfo + { + public WSSInfoI(EndpointI e) + { + _endpoint = e; + } + + override public short type() + { + return _endpoint.type(); + } + + override public bool datagram() + { + return _endpoint.datagram(); + } + + override public bool secure() + { + return _endpoint.secure(); + } + + private EndpointI _endpoint; + } + + // + // Return the endpoint information. + // + public Ice.EndpointInfo getWSInfo(string resource) + { + WSSInfoI info = new WSSInfoI(this); + fillEndpointInfo(info); + info.resource = resource; + return info; + } + // // Return the timeout for the endpoint in milliseconds. 0 means // non-blocking, -1 means no timeout. diff --git a/csharp/src/IceSSL/SSLEngine.cs b/csharp/src/IceSSL/SSLEngine.cs index c0ae3a79c04..7a0180d3fcf 100644 --- a/csharp/src/IceSSL/SSLEngine.cs +++ b/csharp/src/IceSSL/SSLEngine.cs @@ -305,7 +305,15 @@ namespace IceSSL if(_caCerts == null) { - string certAuthFile = properties.getProperty(prefix + "CertAuthFile"); + string certAuthFile = properties.getProperty(prefix + "CAs"); + if(certAuthFile.Length == 0) + { + certAuthFile = properties.getProperty(prefix + "CertAuthFile"); + } + if(certAuthFile.Length > 0 || properties.getPropertyAsInt(prefix + "UsePlatformCAs") <= 0) + { + _caCerts = new X509Certificate2Collection(); + } if(certAuthFile.Length > 0) { if(!checkPath(ref certAuthFile)) @@ -315,12 +323,59 @@ namespace IceSSL throw e; } - _caCerts = new X509Certificate2Collection(); try { - _caCerts.Add(new X509Certificate2(certAuthFile)); + using(System.IO.FileStream fs = System.IO.File.OpenRead(certAuthFile)) + { + byte[] data = new byte[fs.Length]; + fs.Read(data, 0, data.Length); + + string strbuf = ""; + try + { + strbuf = System.Text.Encoding.UTF8.GetString(data); + } + catch(Exception) + { + // Ignore + } + + if(strbuf.Length == data.Length) + { + int size, startpos, endpos = 0; + bool first = true; + while(true) + { + startpos = strbuf.IndexOf("-----BEGIN CERTIFICATE-----", endpos); + if(startpos != -1) + { + endpos = strbuf.IndexOf("-----END CERTIFICATE-----", startpos); + size = endpos - startpos + "-----END CERTIFICATE-----".Length; + } + else if(first) + { + startpos = 0; + endpos = strbuf.Length; + size = strbuf.Length; + } + else + { + break; + } + + byte[] cert = new byte[size]; + System.Buffer.BlockCopy(data, startpos, cert, 0, size); + _caCerts.Import(cert); + first = false; + } + } + else + { + _caCerts.Import(data); + } + } } - catch(CryptographicException ex) + catch(Exception ex) { Ice.PluginInitializationException e = new Ice.PluginInitializationException(ex); e.reason = "IceSSL: error while attempting to load CA certificate from " + certAuthFile; diff --git a/csharp/src/IceSSL/TransceiverI.cs b/csharp/src/IceSSL/TransceiverI.cs index 96eec4be71b..85ec68d0e4f 100644 --- a/csharp/src/IceSSL/TransceiverI.cs +++ b/csharp/src/IceSSL/TransceiverI.cs @@ -22,7 +22,7 @@ namespace IceSSL using System.Threading; using System.Text; - sealed class TransceiverI : IceInternal.Transceiver + sealed class TransceiverI : IceInternal.Transceiver, IceInternal.WSTransceiverDelegate { public Socket fd() { @@ -49,7 +49,7 @@ namespace IceSSL Debug.Assert(_sslStream.IsAuthenticated); _authenticated = true; - _instance.verifyPeer(getNativeConnectionInfo(), _stream.fd(), _host); + _instance.verifyPeer((NativeConnectionInfo)getInfo(), _stream.fd(), _host); if(_instance.securityTraceLevel() >= 1) { @@ -302,7 +302,17 @@ namespace IceSSL public Ice.ConnectionInfo getInfo() { - return getNativeConnectionInfo(); + NativeConnectionInfo info = new NativeConnectionInfo(); + info.nativeCerts = fillConnectionInfo(info); + return info; + } + + public Ice.ConnectionInfo getWSInfo(Dictionary<string, string> headers) + { + WSSNativeConnectionInfo info = new WSSNativeConnectionInfo(); + info.nativeCerts = fillConnectionInfo(info); + info.headers = headers; + return info; } public void checkSendSize(IceInternal.Buffer buf) @@ -367,9 +377,9 @@ namespace IceSSL } } - private NativeConnectionInfo getNativeConnectionInfo() + private X509Certificate2[] fillConnectionInfo(ConnectionInfo info) { - IceSSL.NativeConnectionInfo info = new IceSSL.NativeConnectionInfo(); + X509Certificate2[] nativeCerts = null; if(_stream.fd() != null) { IPEndPoint localEndpoint = (IPEndPoint)IceInternal.Network.getLocalAddress(_stream.fd()); @@ -392,19 +402,19 @@ namespace IceSSL info.cipher = _sslStream.CipherAlgorithm.ToString(); if(_chain.ChainElements != null && _chain.ChainElements.Count > 0) { - info.nativeCerts = new X509Certificate2[_chain.ChainElements.Count]; + nativeCerts = new X509Certificate2[_chain.ChainElements.Count]; for(int i = 0; i < _chain.ChainElements.Count; ++i) { - info.nativeCerts[i] = _chain.ChainElements[i].Certificate; + nativeCerts[i] = _chain.ChainElements[i].Certificate; } } #endif List<string> certs = new List<string>(); #if !UNITY - if(info.nativeCerts != null) + if(nativeCerts != null) { - foreach(X509Certificate2 cert in info.nativeCerts) + foreach(X509Certificate2 cert in nativeCerts) { StringBuilder s = new StringBuilder(); s.Append("-----BEGIN CERTIFICATE-----\n"); @@ -419,7 +429,7 @@ namespace IceSSL } info.adapterName = _adapterName; info.incoming = _incoming; - return info; + return nativeCerts; } private bool startAuthenticate(IceInternal.AsyncCallback callback, object state) @@ -571,19 +581,44 @@ namespace IceSSL SslPolicyErrors policyErrors) { #if !UNITY - SslPolicyErrors sslPolicyErrors = policyErrors; + string message = ""; + int errors = (int)policyErrors; if(certificate != null) { - sslPolicyErrors = SslPolicyErrors.None; - _verified = _chain.Build(new X509Certificate2(certificate)); - if(_chain.ChainStatus.Length > 0) + _chain.Build(new X509Certificate2(certificate)); + if(_chain.ChainStatus != null && _chain.ChainStatus.Length > 0) + { + errors = (int)SslPolicyErrors.RemoteCertificateChainErrors; + } + else if(_instance.engine().caCerts() != null) + { + X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1]; + if(!_chain.ChainPolicy.ExtraStore.Contains(e.Certificate)) + { + if(_verifyPeer > 0) + { + message = message + "\npuntrusted root certificate"; + } + else + { + message = message + "\nuntrusted root certificate (ignored)"; + _verified = false; + } + errors = (int)SslPolicyErrors.RemoteCertificateChainErrors; + } + else + { + _verified = true; + return true; + } + } + else { - sslPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors; + _verified = true; + return true; } } - string message = ""; - int errors = (int)sslPolicyErrors; if((errors & (int)SslPolicyErrors.RemoteCertificateNotAvailable) > 0) { // @@ -618,81 +653,87 @@ namespace IceSSL } - if((errors & (int)SslPolicyErrors.RemoteCertificateChainErrors) > 0) + if((errors & (int)SslPolicyErrors.RemoteCertificateChainErrors) > 0 && + _chain.ChainStatus != null && _chain.ChainStatus.Length > 0) { - if(_chain.ChainStatus != null) + int errorCount = 0; + foreach(X509ChainStatus status in _chain.ChainStatus) { - int errorCount = _chain.ChainStatus.Length; - foreach(X509ChainStatus status in _chain.ChainStatus) + if(status.Status == X509ChainStatusFlags.UntrustedRoot && _instance.engine().caCerts() != null) { - if(status.Status == X509ChainStatusFlags.UntrustedRoot && - _instance.engine().caCerts() != null && _verified) + // + // Untrusted root is OK when using our custom chain engine if + // the CA certificate is present in the chain policy extra store. + // + X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1]; + if(!_chain.ChainPolicy.ExtraStore.Contains(e.Certificate)) { - // - // Untrusted root is OK when using our custom chain engine if - // the CA certificate is present in the chain policy extra store. - // - X509ChainElement e = _chain.ChainElements[_chain.ChainElements.Count - 1]; - if(_chain.ChainPolicy.ExtraStore.Contains(e.Certificate)) - { - --errorCount; - } - } - else if(status.Status == X509ChainStatusFlags.Revoked) - { - if(_instance.checkCRL() > 0) + if(_verifyPeer > 0) { - message = message + "\ncertificate revoked"; + message = message + "\npuntrusted root certificate"; + ++errorCount; } else { - message = message + "\ncertificate revoked (ignored)"; - --errorCount; + message = message + "\nuntrusted root certificate (ignored)"; } } - else if(status.Status == X509ChainStatusFlags.RevocationStatusUnknown) + else { - // - // If a certificate's revocation status cannot be determined, the strictest - // policy is to reject the connection. - // - if(_instance.checkCRL() > 1) - { - message = message + "\ncertificate revocation status unknown"; - } - else - { - message = message + "\ncertificate revocation status unknown (ignored)"; - --errorCount; - } + _verified = true; } - else if(status.Status == X509ChainStatusFlags.PartialChain) + } + else if(status.Status == X509ChainStatusFlags.Revoked) + { + if(_instance.checkCRL() > 0) { - if(_verifyPeer > 0) - { - message = message + "\npartial certificate chain"; - } - else - { - message = message + "\npartial certificate chain (ignored)"; - --errorCount; - } + message = message + "\ncertificate revoked"; + ++errorCount; } - else if(status.Status == X509ChainStatusFlags.NoError) + else { - --errorCount; + message = message + "\ncertificate revoked (ignored)"; + } + } + else if(status.Status == X509ChainStatusFlags.RevocationStatusUnknown) + { + // + // If a certificate's revocation status cannot be determined, the strictest + // policy is to reject the connection. + // + if(_instance.checkCRL() > 1) + { + message = message + "\ncertificate revocation status unknown"; + ++errorCount; } else { - message = message + "\ncertificate chain error: " + status.Status.ToString(); + message = message + "\ncertificate revocation status unknown (ignored)"; } } - - if(errorCount == 0) + else if(status.Status == X509ChainStatusFlags.PartialChain) + { + if(_verifyPeer > 0) + { + message = message + "\npartial certificate chain"; + ++errorCount; + } + else + { + message = message + "\npartial certificate chain (ignored)"; + } + } + else if(status.Status != X509ChainStatusFlags.NoError) { - errors ^= (int)SslPolicyErrors.RemoteCertificateChainErrors; + message = message + "\ncertificate chain error: " + status.Status.ToString(); + ++errorCount; } } + + if(errorCount == 0) + { + errors ^= (int)SslPolicyErrors.RemoteCertificateChainErrors; + } } if(errors > 0) @@ -714,11 +755,10 @@ namespace IceSSL } else if(message.Length > 0 && _instance.securityTraceLevel() >= 1) { - _instance.logger().trace(_instance.securityTraceCategory(), "SSL certificate validation status:" + - message); + _instance.logger().trace(_instance.securityTraceCategory(), + "SSL certificate validation status:" + message); } #endif - return true; } diff --git a/csharp/src/IceSSL/Util.cs b/csharp/src/IceSSL/Util.cs index 9fa6b8d0142..0dd847fcb10 100644 --- a/csharp/src/IceSSL/Util.cs +++ b/csharp/src/IceSSL/Util.cs @@ -28,6 +28,20 @@ namespace IceSSL public System.Security.Cryptography.X509Certificates.X509Certificate2[] nativeCerts; } + /// <summary> + /// This class provides information about a connection to applications + /// that require information about a peer. + /// </summary> + public sealed class WSSNativeConnectionInfo : WSSConnectionInfo + { + /// <summary> + /// The certificate chain. This may be null if the peer did not + /// supply a certificate. The peer's certificate (if any) is the + /// first one in the chain. + /// </summary> + public System.Security.Cryptography.X509Certificates.X509Certificate2[] nativeCerts; + } + public sealed class Util { public static X509Certificate2 createCertificate(string certPEM) |