diff options
author | Mark Spruiell <mes@zeroc.com> | 2006-04-27 20:40:06 +0000 |
---|---|---|
committer | Mark Spruiell <mes@zeroc.com> | 2006-04-27 20:40:06 +0000 |
commit | f3619db0005a9152b7b8ee0284a66571da7a453e (patch) | |
tree | 639a039f2873a48ac312ba04e7cc29bc22a4eadb /java/src/IceSSL/Instance.java | |
parent | more VerifyPeer changes (diff) | |
download | ice-f3619db0005a9152b7b8ee0284a66571da7a453e.tar.bz2 ice-f3619db0005a9152b7b8ee0284a66571da7a453e.tar.xz ice-f3619db0005a9152b7b8ee0284a66571da7a453e.zip |
adding support for CheckCertName
Diffstat (limited to 'java/src/IceSSL/Instance.java')
-rw-r--r-- | java/src/IceSSL/Instance.java | 129 |
1 files changed, 117 insertions, 12 deletions
diff --git a/java/src/IceSSL/Instance.java b/java/src/IceSSL/Instance.java index dacc577fa71..fac57266a90 100644 --- a/java/src/IceSSL/Instance.java +++ b/java/src/IceSSL/Instance.java @@ -78,6 +78,12 @@ class Instance } // + // CheckCertName determines whether we compare the name in a peer's + // certificate against its hostname. + // + _checkCertName = properties.getPropertyAsIntWithDefault(prefix + "CheckCertName", 0) > 0; + + // // If the user doesn't supply an SSLContext, we need to create one based // on property settings. // @@ -418,26 +424,124 @@ class Instance _logger.trace(_securityTraceCategory, msg); } - boolean - verifyPeer(ConnectionInfo info, javax.net.ssl.SSLSocket fd, String host, boolean incoming) + void + verifyPeer(ConnectionInfo info, javax.net.ssl.SSLSocket fd, String address, boolean incoming) { - CertificateVerifier verifier = _verifier; - if(verifier != null) + // + // Extract the IP addresses and the DNS names from the subject + // alternative names. + // + if(info.certs != null) { - if(!verifier.verify(info)) + try { - if(_securityTraceLevel > 0) + java.util.Collection subjectAltNames = + ((java.security.cert.X509Certificate)info.certs[0]).getSubjectAlternativeNames(); + java.util.ArrayList ipAddresses = new java.util.ArrayList(); + java.util.ArrayList dnsNames = new java.util.ArrayList(); + java.util.Iterator i = subjectAltNames.iterator(); + while(i.hasNext()) { - _logger.trace(_securityTraceCategory, - (incoming ? "incoming" : "outgoing") + - " connection rejected by certificate verifier\n" + - IceInternal.Network.fdToString(fd)); + java.util.List l = (java.util.List)i.next(); + assert(!l.isEmpty()); + Integer n = (Integer)l.get(0); + if(n.intValue() == 7) + { + ipAddresses.add((String)l.get(1)); + } + else if(n.intValue() == 2) + { + dnsNames.add(((String)l.get(1)).toLowerCase()); + } + } + + // + // Compare the peer's address against the dnsName and ipAddress values. + // This is only relevant for an outgoing connection. + // + if(address.length() > 0) + { + boolean certNameOK = ipAddresses.contains(address); + if(!certNameOK) + { + certNameOK = dnsNames.contains(address.toLowerCase()); + } + + // + // Log a message if the name comparison fails. If CheckCertName is defined, + // we also raise an exception to abort the connection. Don't log a message if + // CheckCertName is not defined and a verifier is present. + // + if(!certNameOK && (_checkCertName || (_securityTraceLevel >= 1 && _verifier == null))) + { + StringBuffer sb = new StringBuffer(); + sb.append("IceSSL: "); + if(!_checkCertName) + { + sb.append("ignoring "); + } + sb.append("certificate validation failure:\npeer certificate does not contain `" + + address + "' in its subjectAltName extension"); + if(!dnsNames.isEmpty()) + { + sb.append("\nDNS names found in certificate: "); + for(int j = 0; j < dnsNames.size(); ++j) + { + if(j > 0) + { + sb.append(", "); + } + sb.append(dnsNames.get(j).toString()); + } + } + if(!ipAddresses.isEmpty()) + { + sb.append("\nIP addresses found in certificate: "); + for(int j = 0; j < ipAddresses.size(); ++j) + { + if(j > 0) + { + sb.append(", "); + } + sb.append(ipAddresses.get(j).toString()); + } + } + if(_securityTraceLevel >= 1) + { + _logger.trace(_securityTraceCategory, sb.toString()); + } + if(_checkCertName) + { + Ice.SecurityException ex = new Ice.SecurityException(); + ex.reason = sb.toString(); + throw ex; + } + } } - return false; + } + catch(java.security.cert.CertificateParsingException ex) + { + assert(false); } } - return true; + if(_verifier != null) + { + if(!_verifier.verify(info)) + { + String msg = (incoming ? "incoming" : "outgoing") + " connection rejected by certificate verifier\n" + + IceInternal.Network.fdToString(fd); + + if(_securityTraceLevel > 0) + { + _logger.trace(_securityTraceCategory, msg); + } + + Ice.SecurityException ex = new Ice.SecurityException(); + ex.reason = msg; + throw ex; + } + } } private void @@ -566,5 +670,6 @@ class Instance private boolean _allCiphers; private boolean _noCiphers; private String[] _protocols; + private boolean _checkCertName; private CertificateVerifier _verifier; } |