|
|
79cc52 |
From 3e3515b42a5c782219ba898f9cb79812c8895349 Mon Sep 17 00:00:00 2001
|
|
|
79cc52 |
From: Michal Srb <msrb@redhat.com>
|
|
|
79cc52 |
Date: Tue, 12 Aug 2014 14:07:29 +0200
|
|
|
79cc52 |
Subject: [PATCH] Fix CVE-2014-3577
|
|
|
79cc52 |
|
|
|
79cc52 |
---
|
|
|
79cc52 |
.../org/apache/http/conn/ssl/AbstractVerifier.java | 87 +++++++++++-----------
|
|
|
79cc52 |
1 file changed, 44 insertions(+), 43 deletions(-)
|
|
|
79cc52 |
|
|
|
79cc52 |
diff --git a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java
|
|
|
79cc52 |
index a7cad68..7245781 100644
|
|
|
79cc52 |
--- a/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java
|
|
|
79cc52 |
+++ b/httpclient/src/main/java/org/apache/http/conn/ssl/AbstractVerifier.java
|
|
|
79cc52 |
@@ -28,7 +28,6 @@
|
|
|
79cc52 |
package org.apache.http.conn.ssl;
|
|
|
79cc52 |
|
|
|
79cc52 |
import org.apache.http.annotation.Immutable;
|
|
|
79cc52 |
-
|
|
|
79cc52 |
import org.apache.http.conn.util.InetAddressUtils;
|
|
|
79cc52 |
|
|
|
79cc52 |
import java.io.IOException;
|
|
|
79cc52 |
@@ -36,14 +35,21 @@ import java.io.InputStream;
|
|
|
79cc52 |
import java.security.cert.Certificate;
|
|
|
79cc52 |
import java.security.cert.CertificateParsingException;
|
|
|
79cc52 |
import java.security.cert.X509Certificate;
|
|
|
79cc52 |
+import java.util.ArrayList;
|
|
|
79cc52 |
import java.util.Arrays;
|
|
|
79cc52 |
import java.util.Collection;
|
|
|
79cc52 |
import java.util.Iterator;
|
|
|
79cc52 |
import java.util.LinkedList;
|
|
|
79cc52 |
import java.util.List;
|
|
|
79cc52 |
import java.util.Locale;
|
|
|
79cc52 |
-import java.util.StringTokenizer;
|
|
|
79cc52 |
-
|
|
|
79cc52 |
+import java.util.NoSuchElementException;
|
|
|
79cc52 |
+
|
|
|
79cc52 |
+import javax.naming.InvalidNameException;
|
|
|
79cc52 |
+import javax.naming.NamingException;
|
|
|
79cc52 |
+import javax.naming.directory.Attribute;
|
|
|
79cc52 |
+import javax.naming.directory.Attributes;
|
|
|
79cc52 |
+import javax.naming.ldap.LdapName;
|
|
|
79cc52 |
+import javax.naming.ldap.Rdn;
|
|
|
79cc52 |
import javax.net.ssl.SSLException;
|
|
|
79cc52 |
import javax.net.ssl.SSLSession;
|
|
|
79cc52 |
import javax.net.ssl.SSLSocket;
|
|
|
79cc52 |
@@ -142,7 +148,8 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
|
|
79cc52 |
|
|
|
79cc52 |
public final void verify(String host, X509Certificate cert)
|
|
|
79cc52 |
throws SSLException {
|
|
|
79cc52 |
- String[] cns = getCNs(cert);
|
|
|
79cc52 |
+ final String subjectPrincipal = cert.getSubjectX500Principal().toString();
|
|
|
79cc52 |
+ final String[] cns = extractCNs(subjectPrincipal);
|
|
|
79cc52 |
String[] subjectAlts = getSubjectAlts(cert, host);
|
|
|
79cc52 |
verify(host, cns, subjectAlts);
|
|
|
79cc52 |
}
|
|
|
79cc52 |
@@ -236,48 +243,42 @@ public abstract class AbstractVerifier implements X509HostnameVerifier {
|
|
|
79cc52 |
return Arrays.binarySearch(BAD_COUNTRY_2LDS, parts[1]) < 0;
|
|
|
79cc52 |
}
|
|
|
79cc52 |
|
|
|
79cc52 |
- public static String[] getCNs(X509Certificate cert) {
|
|
|
79cc52 |
- LinkedList<String> cnList = new LinkedList<String>();
|
|
|
79cc52 |
- /*
|
|
|
79cc52 |
- Sebastian Hauer's original StrictSSLProtocolSocketFactory used
|
|
|
79cc52 |
- getName() and had the following comment:
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- Parses a X.500 distinguished name for the value of the
|
|
|
79cc52 |
- "Common Name" field. This is done a bit sloppy right
|
|
|
79cc52 |
- now and should probably be done a bit more according to
|
|
|
79cc52 |
- RFC 2253 .
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- I've noticed that toString() seems to do a better job than
|
|
|
79cc52 |
- getName() on these X500Principal objects, so I'm hoping that
|
|
|
79cc52 |
- addresses Sebastian's concern.
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- For example, getName() gives me this:
|
|
|
79cc52 |
- 1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- whereas toString() gives me this:
|
|
|
79cc52 |
- EMAILADDRESS=juliusdavies@cucbc.com
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- Looks like toString() even works with non-ascii domain names!
|
|
|
79cc52 |
- I tested it with "花子.co.jp" and it worked fine.
|
|
|
79cc52 |
- */
|
|
|
79cc52 |
-
|
|
|
79cc52 |
- String subjectPrincipal = cert.getSubjectX500Principal().toString();
|
|
|
79cc52 |
- StringTokenizer st = new StringTokenizer(subjectPrincipal, ",");
|
|
|
79cc52 |
- while(st.hasMoreTokens()) {
|
|
|
79cc52 |
- String tok = st.nextToken().trim();
|
|
|
79cc52 |
- if (tok.length() > 3) {
|
|
|
79cc52 |
- if (tok.substring(0, 3).equalsIgnoreCase("CN=")) {
|
|
|
79cc52 |
- cnList.add(tok.substring(3));
|
|
|
79cc52 |
- }
|
|
|
79cc52 |
- }
|
|
|
79cc52 |
+ public static String[] getCNs(final X509Certificate cert) {
|
|
|
79cc52 |
+ final String subjectPrincipal = cert.getSubjectX500Principal().toString();
|
|
|
79cc52 |
+ try {
|
|
|
79cc52 |
+ return extractCNs(subjectPrincipal);
|
|
|
79cc52 |
+ } catch (SSLException ex) {
|
|
|
79cc52 |
+ return null;
|
|
|
79cc52 |
}
|
|
|
79cc52 |
- if(!cnList.isEmpty()) {
|
|
|
79cc52 |
- String[] cns = new String[cnList.size()];
|
|
|
79cc52 |
- cnList.toArray(cns);
|
|
|
79cc52 |
- return cns;
|
|
|
79cc52 |
- } else {
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+
|
|
|
79cc52 |
+ static String[] extractCNs(final String subjectPrincipal) throws SSLException {
|
|
|
79cc52 |
+ if (subjectPrincipal == null) {
|
|
|
79cc52 |
return null;
|
|
|
79cc52 |
}
|
|
|
79cc52 |
+ final List<String> cns = new ArrayList<String>();
|
|
|
79cc52 |
+ try {
|
|
|
79cc52 |
+ final LdapName subjectDN = new LdapName(subjectPrincipal);
|
|
|
79cc52 |
+ final List<Rdn> rdns = subjectDN.getRdns();
|
|
|
79cc52 |
+ for (int i = rdns.size() - 1; i >= 0; i--) {
|
|
|
79cc52 |
+ final Rdn rds = rdns.get(i);
|
|
|
79cc52 |
+ final Attributes attributes = rds.toAttributes();
|
|
|
79cc52 |
+ final Attribute cn = attributes.get("cn");
|
|
|
79cc52 |
+ if (cn != null) {
|
|
|
79cc52 |
+ try {
|
|
|
79cc52 |
+ final Object value = cn.get();
|
|
|
79cc52 |
+ if (value != null) {
|
|
|
79cc52 |
+ cns.add(value.toString());
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+ } catch (NoSuchElementException ignore) {
|
|
|
79cc52 |
+ } catch (NamingException ignore) {
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+ } catch (InvalidNameException e) {
|
|
|
79cc52 |
+ throw new SSLException(subjectPrincipal + " is not a valid X500 distinguished name");
|
|
|
79cc52 |
+ }
|
|
|
79cc52 |
+ return cns.isEmpty() ? null : cns.toArray(new String[cns.size()]);
|
|
|
79cc52 |
}
|
|
|
79cc52 |
|
|
|
79cc52 |
/**
|
|
|
79cc52 |
--
|
|
|
79cc52 |
1.9.3
|
|
|
79cc52 |
|