Blame SOURCES/0001-Fix-CVE-2014-3577.patch

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