Hello community,

here is the log from the commit of package jakarta-commons-httpclient for 
openSUSE:12.3 checked in at 2013-02-14 21:00:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:12.3/jakarta-commons-httpclient (Old)
 and      /work/SRC/openSUSE:12.3/.jakarta-commons-httpclient.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "jakarta-commons-httpclient", Maintainer is ""

Changes:
--------
--- 
/work/SRC/openSUSE:12.3/jakarta-commons-httpclient/jakarta-commons-httpclient.changes
       2013-01-31 01:20:33.000000000 +0100
+++ 
/work/SRC/openSUSE:12.3/.jakarta-commons-httpclient.new/jakarta-commons-httpclient.changes
  2013-02-14 21:00:25.000000000 +0100
@@ -1,0 +2,6 @@
+Thu Feb 14 09:10:48 UTC 2013 - mvysko...@suse.com
+
+- fix bnc#8033332: no ssl certificate hostname checking (CVE-2012-5783)
+  * commons-httpclient-CVE-2012-5783.patch
+
+-------------------------------------------------------------------

New:
----
  commons-httpclient-CVE-2012-5783.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ jakarta-commons-httpclient.spec ++++++
--- /var/tmp/diff_new_pack.jZUyB8/_old  2013-02-14 21:00:25.000000000 +0100
+++ /var/tmp/diff_new_pack.jZUyB8/_new  2013-02-14 21:00:25.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package jakarta-commons-httpclient
 #
-# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -32,6 +32,9 @@
 # Add OSGi MANIFEST.MF bits
 Patch1:         %{name}-addosgimanifest.patch
 Patch2:         %{name}-encoding.patch
+#PATCH-FIX-UPSTREAM: bnc#803332
+#http://svn.apache.org/viewvc?view=revision&revision=483925
+Patch3:         commons-httpclient-CVE-2012-5783.patch
 BuildArch:      noarch
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 
@@ -111,6 +114,7 @@
 popd
 
 %patch2
+%patch3 -p1
 
 # Use javax classes, not com.sun ones
 # assume no filename contains spaces

++++++ commons-httpclient-CVE-2012-5783.patch ++++++
Index: 
commons-httpclient-3.1/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
===================================================================
--- 
commons-httpclient-3.1.orig/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
+++ 
commons-httpclient-3.1/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
@@ -31,10 +31,17 @@
 package org.apache.commons.httpclient.protocol;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.UnknownHostException;
 
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 
 import org.apache.commons.httpclient.ConnectTimeoutException;
@@ -79,12 +86,17 @@ public class SSLProtocolSocketFactory im
         InetAddress clientHost,
         int clientPort)
         throws IOException, UnknownHostException {
-        return SSLSocketFactory.getDefault().createSocket(
+        SSLSocket socket = (SSLSocket) 
SSLSocketFactory.getDefault().createSocket(
             host,
             port,
             clientHost,
             clientPort
         );
+
+        verifyHostName( host, (SSLSocket) socket );
+
+        // verifyHostName() didn't blowup - good!
+        return socket;
     }
 
     /**
@@ -124,15 +136,18 @@ public class SSLProtocolSocketFactory im
         }
         int timeout = params.getConnectionTimeout();
         if (timeout == 0) {
-            return createSocket(host, port, localAddress, localPort);
+            SSLSocket socket = (SSLSocket) createSocket(host, port, 
localAddress, localPort);
+            verifyHostName(host, (SSLSocket) socket);
+            return socket;
         } else {
             // To be eventually deprecated when migrated to Java 1.4 or above
-            Socket socket = ReflectionSocketFactory.createSocket(
+            SSLSocket socket =(SSLSocket) ReflectionSocketFactory.createSocket(
                 "javax.net.ssl.SSLSocketFactory", host, port, localAddress, 
localPort, timeout);
             if (socket == null) {
-                socket = ControllerThreadSocketFactory.createSocket(
+                socket = (SSLSocket) 
ControllerThreadSocketFactory.createSocket(
                     this, host, port, localAddress, localPort, timeout);
             }
+            verifyHostName(host, (SSLSocket) socket);
             return socket;
         }
     }
@@ -142,10 +157,12 @@ public class SSLProtocolSocketFactory im
      */
     public Socket createSocket(String host, int port)
         throws IOException, UnknownHostException {
-        return SSLSocketFactory.getDefault().createSocket(
+        SSLSocket socket = (SSLSocket) 
SSLSocketFactory.getDefault().createSocket(
             host,
             port
         );
+        verifyHostName( host, (SSLSocket) socket );
+        return socket;
     }
 
     /**
@@ -157,14 +174,133 @@ public class SSLProtocolSocketFactory im
         int port,
         boolean autoClose)
         throws IOException, UnknownHostException {
-        return ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
+        SSLSocket s = (SSLSocket) ((SSLSocketFactory) 
SSLSocketFactory.getDefault()).createSocket(
             socket,
             host,
             port,
             autoClose
         );
+        verifyHostName( host, (SSLSocket) socket );
+
+        // verifyHostName() didn't blowup - good!
+        return s;
+    }
+
+    private static void verifyHostName( String host, SSLSocket ssl )
+          throws IOException {
+        if ( host == null ) {
+            throw new NullPointerException( "host to verify was null" );
+        }
+
+        SSLSession session = ssl.getSession();
+        if ( session == null ) {
+            // In our experience this only happens under IBM 1.4.x when
+            // spurious (unrelated) certificates show up in the server's chain.
+            // Hopefully this will unearth the real problem:
+            InputStream in = ssl.getInputStream();
+            in.available();
+            /*
+               If you're looking at the 2 lines of code above because you're
+               running into a problem, you probably have two options:
+
+                  #1.  Clean up the certificate chain that your server
+                       is presenting (e.g. edit "/etc/apache2/server.crt" or
+                       wherever it is your server's certificate chain is
+                       defined).
+
+                                           OR
+
+                  #2.   Upgrade to an IBM 1.5.x or greater JVM, or switch to a
+                        non-IBM JVM.
+            */
+
+            // If ssl.getInputStream().available() didn't cause an exception,
+            // maybe at least now the session is available?
+            session = ssl.getSession();
+            if ( session == null ) {
+                // If it's still null, probably a startHandshake() will
+                // unearth the real problem.
+                ssl.startHandshake();
+
+                // Okay, if we still haven't managed to cause an exception,
+                // might as well go for the NPE.  Or maybe we're okay now?
+                session = ssl.getSession();
+            }
+        }
+
+        Certificate[] certs = session.getPeerCertificates();
+        X509Certificate x509 = (X509Certificate) certs[ 0 ];
+        String cn = getCN( x509 );
+        if ( cn == null ) {
+            String subject = x509.getSubjectX500Principal().toString();
+            String msg = "certificate doesn't contain CN: " + subject;
+            throw new SSLException( msg );
+        }
+        // I'm okay with being case-insensitive when comparing the host we used
+        // to establish the socket to the hostname in the certificate.
+        // Don't trim the CN, though.
+        cn = cn.toLowerCase();
+        host = host.trim().toLowerCase();
+        boolean doWildcard = false;
+        if ( cn.startsWith( "*." ) ) {
+            // The CN better have at least two dots if it wants wildcard 
action,
+            // but can't be [*.co.uk] or [*.co.jp] or [*.org.uk], etc...
+            String withoutCountryCode = "";
+            if ( cn.length() >= 7 && cn.length() <= 9 ) {
+                withoutCountryCode = cn.substring( 2, cn.length() - 2 );
+            }
+            doWildcard = cn.lastIndexOf( '.' ) >= 0 &&
+                         !"ac.".equals( withoutCountryCode ) &&
+                         !"co.".equals( withoutCountryCode ) &&
+                         !"com.".equals( withoutCountryCode ) &&
+                         !"ed.".equals( withoutCountryCode ) &&
+                         !"edu.".equals( withoutCountryCode ) &&
+                         !"go.".equals( withoutCountryCode ) &&
+                         !"gouv.".equals( withoutCountryCode ) &&
+                         !"gov.".equals( withoutCountryCode ) &&
+                         !"info.".equals( withoutCountryCode ) &&
+                         !"lg.".equals( withoutCountryCode ) &&
+                         !"ne.".equals( withoutCountryCode ) &&
+                         !"net.".equals( withoutCountryCode ) &&
+                         !"or.".equals( withoutCountryCode ) &&
+                         !"org.".equals( withoutCountryCode );
+
+            // The [*.co.uk] problem is an interesting one.  Should we just
+            // hope that CA's would never foolishly allow such a
+            // certificate to happen?
+        }
+
+        boolean match;
+        if ( doWildcard ) {
+            match = host.endsWith( cn.substring( 1 ) );
+        } else {
+            match = host.equals( cn );
+        }
+        if ( !match ) {
+            throw new SSLException( "hostname in certificate didn't match: <" 
+ host + "> != <" + cn + ">" );
+        }
     }
 
+    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=juliusdav...@cucbc.com
+        String subjectPrincipal = cert.getSubjectX500Principal().toString();
+        int x = subjectPrincipal.indexOf( "CN=" );
+        if ( x >= 0 ) {
+            int y = subjectPrincipal.indexOf( ',', x );
+            // If there are no more commas, then CN= is the last entry.
+            y = ( y >= 0 ) ? y : subjectPrincipal.length();
+            return subjectPrincipal.substring( x + 3, y );
+        } else {
+            return null;
+        }
+     }
+
     /**
      * All instances of SSLProtocolSocketFactory are the same.
      */
-- 
To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org
For additional commands, e-mail: opensuse-commit+h...@opensuse.org

Reply via email to