From 6f55656e288808437389f7d733e9a466fa5f0e2b Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Tue, 12 Aug 2014 16:14:06 +0200 Subject: [PATCH] Fix CVE-2014-3577 --- .../protocol/SSLProtocolSocketFactory.java | 57 ++++++++++++++-------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java index fa0acc7..e6ce513 100644 --- a/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java +++ b/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java @@ -44,9 +44,15 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; -import java.util.StringTokenizer; +import java.util.NoSuchElementException; import java.util.regex.Pattern; +import javax.naming.InvalidNameException; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; @@ -424,28 +430,39 @@ public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory { return dots; } - private static String getCN(X509Certificate cert) { - // Note: toString() seems to do a better job than getName() - // - // For example, getName() gives me this: - // 1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d - // - // whereas toString() gives me this: - // EMAILADDRESS=juliusdavies@cucbc.com - String subjectPrincipal = cert.getSubjectX500Principal().toString(); - - return getCN(subjectPrincipal); - + private static String getCN(final X509Certificate cert) { + final String subjectPrincipal = cert.getSubjectX500Principal().toString(); + try { + return extractCN(subjectPrincipal); + } catch (SSLException ex) { + return null; + } } - private static String getCN(String subjectPrincipal) { - StringTokenizer st = new StringTokenizer(subjectPrincipal, ","); - while(st.hasMoreTokens()) { - String tok = st.nextToken().trim(); - if (tok.length() > 3) { - if (tok.substring(0, 3).equalsIgnoreCase("CN=")) { - return tok.substring(3); + + private static String extractCN(final String subjectPrincipal) throws SSLException { + if (subjectPrincipal == null) { + return null; + } + try { + final LdapName subjectDN = new LdapName(subjectPrincipal); + final List rdns = subjectDN.getRdns(); + for (int i = rdns.size() - 1; i >= 0; i--) { + final Rdn rds = rdns.get(i); + final Attributes attributes = rds.toAttributes(); + final Attribute cn = attributes.get("cn"); + if (cn != null) { + try { + final Object value = cn.get(); + if (value != null) { + return value.toString(); + } + } catch (NoSuchElementException ignore) { + } catch (NamingException ignore) { + } } } + } catch (InvalidNameException e) { + throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name"); } return null; } -- 1.9.3