Sync from SUSE:SLFO:Main apache-commons-httpclient revision 7d1a442e43871efa726c4b0b3d58bebd

This commit is contained in:
Adrian Schröter 2024-05-03 11:00:29 +02:00
commit ead77d044f
11 changed files with 1147 additions and 0 deletions

23
.gitattributes vendored Normal file
View File

@ -0,0 +1,23 @@
## Default LFS
*.7z filter=lfs diff=lfs merge=lfs -text
*.bsp filter=lfs diff=lfs merge=lfs -text
*.bz2 filter=lfs diff=lfs merge=lfs -text
*.gem filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.jar filter=lfs diff=lfs merge=lfs -text
*.lz filter=lfs diff=lfs merge=lfs -text
*.lzma filter=lfs diff=lfs merge=lfs -text
*.obscpio filter=lfs diff=lfs merge=lfs -text
*.oxt filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.rpm filter=lfs diff=lfs merge=lfs -text
*.tbz filter=lfs diff=lfs merge=lfs -text
*.tbz2 filter=lfs diff=lfs merge=lfs -text
*.tgz filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.txz filter=lfs diff=lfs merge=lfs -text
*.whl filter=lfs diff=lfs merge=lfs -text
*.xz filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.zst filter=lfs diff=lfs merge=lfs -text

View File

@ -0,0 +1,92 @@
From 1bef0d6f6e8f2f68e996737d7be598613e2060b2 Mon Sep 17 00:00:00 2001
From: Fabio Valentini <decathorpe@gmail.com>
Date: Sat, 18 Jul 2020 19:48:08 +0200
Subject: [PATCH 4/6] 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<Rdn> 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;
}
--
2.26.2

View File

@ -0,0 +1,35 @@
From a42239d4dbf88dc577061203c234a91d847a8615 Mon Sep 17 00:00:00 2001
From: Fabio Valentini <decathorpe@gmail.com>
Date: Sat, 18 Jul 2020 19:48:18 +0200
Subject: [PATCH 5/6] CVE-2015-5262
---
.../httpclient/protocol/SSLProtocolSocketFactory.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java b/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
index e6ce513..b7550a2 100644
--- a/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
+++ b/src/java/org/apache/commons/httpclient/protocol/SSLProtocolSocketFactory.java
@@ -152,7 +152,9 @@ public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory {
}
int timeout = params.getConnectionTimeout();
if (timeout == 0) {
- Socket sslSocket = createSocket(host, port, localAddress, localPort);
+ Socket sslSocket = SSLSocketFactory.getDefault().createSocket(
+ host, port, localAddress, localPort);
+ sslSocket.setSoTimeout(params.getSoTimeout());
verifyHostName(host, (SSLSocket) sslSocket);
return sslSocket;
} else {
@@ -163,6 +165,7 @@ public class SSLProtocolSocketFactory implements SecureProtocolSocketFactory {
sslSocket = ControllerThreadSocketFactory.createSocket(
this, host, port, localAddress, localPort, timeout);
}
+ sslSocket.setSoTimeout(params.getSoTimeout());
verifyHostName(host, (SSLSocket) sslSocket);
return sslSocket;
}
--
2.26.2

View File

@ -0,0 +1,31 @@
--- MANIFEST.MF 2007-09-06 12:31:02.000000000 -0400
+++ MANIFEST.MF 2007-09-06 12:30:45.000000000 -0400
@@ -3,4 +3,27 @@
Specification-Version: 1.0
Implementation-Vendor: Apache Software Foundation
Implementation-Version: @version@
-
+Bundle-ManifestVersion: 2
+Bundle-Name: %bundleName
+Bundle-SymbolicName: org.apache.commons.httpclient
+Bundle-Version: 3.1.0.v20080605-1935
+Import-Package: javax.crypto;resolution:=optional,
+ javax.crypto.spec;resolution:=optional,
+ javax.net;resolution:=optional,
+ javax.net.ssl;resolution:=optional,
+ org.apache.commons.codec;version="[1.2.0,2.0.0)",
+ org.apache.commons.codec.binary;version="[1.2.0,2.0.0)",
+ org.apache.commons.codec.net;version="[1.2.0,2.0.0)",
+ org.apache.commons.logging;version="[1.0.4,2.0.0)"
+Export-Package: org.apache.commons.httpclient;version="3.1.0",
+ org.apache.commons.httpclient.auth;version="3.1.0",
+ org.apache.commons.httpclient.cookie;version="3.1.0",
+ org.apache.commons.httpclient.methods;version="3.1.0",
+ org.apache.commons.httpclient.methods.multipart;version="3.1.0",
+ org.apache.commons.httpclient.params;version="3.1.0",
+ org.apache.commons.httpclient.protocol;version="3.1.0",
+ org.apache.commons.httpclient.util;version="3.1.0"
+Bundle-Vendor: %bundleProvider
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,
+ J2SE-1.2

View File

@ -0,0 +1,20 @@
--- ./src/test/org/apache/commons/httpclient/params/TestParamsAll.java.sav 2006-07-20 18:42:17.000000000 -0400
+++ ./src/test/org/apache/commons/httpclient/params/TestParamsAll.java 2006-07-20 18:42:26.000000000 -0400
@@ -43,7 +43,6 @@
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(TestHttpParams.suite());
- suite.addTest(TestSSLTunnelParams.suite());
return suite;
}
--- ./src/test/org/apache/commons/httpclient/TestAll.java.sav 2006-07-20 18:42:56.000000000 -0400
+++ ./src/test/org/apache/commons/httpclient/TestAll.java 2006-07-20 18:43:01.000000000 -0400
@@ -100,7 +100,6 @@
// Non compliant behaviour
suite.addTest(TestNoncompliant.suite());
// Proxy
- suite.addTest(TestProxy.suite());
suite.addTest(TestProxyWithRedirect.suite());
return suite;
}

View File

@ -0,0 +1,34 @@
--- build.xml 2007-08-18 05:02:14.000000000 -0400
+++ build.xml 2012-01-23 09:52:50.405796336 -0500
@@ -179,6 +179,7 @@
description="Compile shareable components">
<javac srcdir ="${source.home}/java"
destdir ="${build.home}/classes"
+ encoding ="ISO-8859-1"
debug ="${compile.debug}"
deprecation ="${compile.deprecation}"
optimize ="${compile.optimize}">
@@ -186,6 +187,7 @@
</javac>
<javac srcdir ="${source.home}/examples"
destdir ="${build.home}/examples"
+ encoding ="ISO-8859-1"
debug ="${compile.debug}"
deprecation ="${compile.deprecation}"
optimize ="${compile.optimize}">
@@ -197,6 +199,7 @@
description="Compile unit test cases">
<javac srcdir ="${test.home}"
destdir ="${build.home}/tests"
+ encoding ="ISO-8859-1"
debug ="${compile.debug}"
deprecation ="${compile.deprecation}"
optimize ="${compile.optimize}">
@@ -244,6 +244,7 @@
<mkdir dir="${dist.home}/docs/api"/>
<javadoc sourcepath ="${source.home}/java"
destdir ="${dist.home}/docs/api"
+ encoding ="ISO-8859-1"
packagenames ="org.apache.commons.*"
author ="true"
protected ="true"

View File

@ -0,0 +1,80 @@
-------------------------------------------------------------------
Tue Oct 27 10:39:27 UTC 2020 - Pedro Monreal <pmonreal@suse.com>
- Security fix [bsc#945190, CVE-2015-5262]
* http/conn/ssl/SSLConnectionSocketFactory.java ignores the
http.socket.timeout configuration setting during an SSL handshake,
which allows remote attackers to cause a denial of service (HTTPS
call hang) via unspecified vectors.
- Add apache-commons-httpclient-CVE-2015-5262.patch
-------------------------------------------------------------------
Tue Oct 27 10:38:45 UTC 2020 - Pedro Monreal <pmonreal@suse.com>
- Security fix [bsc#1178171, CVE-2014-3577]
* org.apache.http.conn.ssl.AbstractVerifier does not properly
verify that the server hostname matches a domain name in the
subject's Common Name (CN) or subjectAltName field of the X.509
certificate, which allows MITM attackers to spoof SSL servers
via a "CN=" string in a field in the distinguished name (DN)
of a certificate.
- Add apache-commons-httpclient-CVE-2014-3577.patch
-------------------------------------------------------------------
Mon Apr 1 23:15:55 UTC 2019 - Jan Engelhardt <jengelh@inai.de>
- Trim conjecture from description.
-------------------------------------------------------------------
Mon Jan 21 15:28:32 UTC 2019 - Fridrich Strba <fstrba@suse.com>
- Add maven pom file and clean-up the spec file
-------------------------------------------------------------------
Tue May 15 10:34:34 UTC 2018 - fstrba@suse.com
- Build with source and target 8 to prepare for a possible removal
of 1.6 compatibility
- Run fdupes on documentation
-------------------------------------------------------------------
Thu Sep 7 11:49:25 UTC 2017 - fstrba@suse.com
- Build with java source and target versions 1.6
* fixes build with jdk9
-------------------------------------------------------------------
Tue Jul 8 08:23:35 UTC 2014 - tchvatal@suse.com
- Redo the bytcode disabling properly.
- Cleanup with spec-cleaner
-------------------------------------------------------------------
Mon Apr 14 17:24:13 UTC 2014 - darin@darins.net
- disable bytecode test on SLES
-------------------------------------------------------------------
Fri Oct 25 08:30:33 UTC 2013 - mvyskocil@suse.com
- really apply CVE-2012-5783 patch
- build with java 6 and higher
-------------------------------------------------------------------
Thu Mar 28 10:54:13 UTC 2013 - mvyskocil@suse.com
- enhance fix of bnc#803332 / CVE-2012-5783
* add a check for subjectAltNames for instance
-------------------------------------------------------------------
Thu Feb 14 09:10:48 UTC 2013 - mvyskocil@suse.com
- fix bnc#803332: no ssl certificate hostname checking (CVE-2012-5783)
* commons-httpclient-CVE-2012-5783.patch
- add jakarta- compat symlinks
-------------------------------------------------------------------
Sun Feb 3 20:07:59 UTC 2013 - p.drouand@gmail.com
- Initial release

View File

@ -0,0 +1,206 @@
#
# spec file for package apache-commons-httpclient
#
# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
%define short_name commons-httpclient
Name: apache-commons-httpclient
Version: 3.1
Release: 0
Summary: Feature rich package for accessing resources via HTTP
License: Apache-2.0
Group: Development/Libraries/Java
URL: http://hc.apache.org/httpclient-3.x/
Source0: http://www.apache.org/dist/httpcomponents/commons-httpclient/source/%{short_name}-%{version}-src.tar.gz
Source1: http://repo.maven.apache.org/maven2/%{short_name}/%{short_name}/%{version}/%{short_name}-%{version}.pom
Patch0: %{name}-disablecryptotests.patch
# Add OSGi MANIFEST.MF bits
Patch1: %{name}-addosgimanifest.patch
Patch2: %{name}-encoding.patch
#PATCH-FIX-UPSTREAM: bnc#803332
#https://issues.apache.org/jira/secure/attachment/12560251/CVE-2012-5783-2.patch
Patch3: %{short_name}-CVE-2012-5783-2.patch
#PATCH-FIX-UPSTREAM bsc#1178171 CVE-2014-3577 MITM security vulnerability
Patch4: apache-commons-httpclient-CVE-2014-3577.patch
#PATCH-FIX-UPSTREAM bsc#945190 CVE-2015-5262 Missing HTTPS connection timeout
Patch5: apache-commons-httpclient-CVE-2015-5262.patch
BuildRequires: ant
BuildRequires: ant-junit
BuildRequires: commons-codec
BuildRequires: commons-logging >= 1.0.3
BuildRequires: fdupes
BuildRequires: java-devel >= 1.8
BuildRequires: javapackages-local
BuildRequires: junit
Requires: commons-codec
Requires: commons-logging >= 1.0.3
Provides: %{short_name} = %{version}
Provides: jakarta-%{short_name} = %{version}
Obsoletes: jakarta-%{short_name} < %{version}
Provides: jakarta-%{short_name}3 = %{version}
Obsoletes: jakarta-%{short_name}3 < %{version}
BuildArch: noarch
%description
Although the java.net package provides basic functionality for
accessing resources via HTTP, it doesn't provide the full flexibility
or functionality needed by many applications. The Apache Commons
HttpClient component provides a package implementing the client side
of the most recent HTTP standards and recommendations.
The HttpClient component may be of interest to anyone building
HTTP-aware client applications such as web browsers, web service
clients, or systems that leverage or extend the HTTP protocol for
distributed communication.
%package javadoc
Summary: Developer documentation for %{name}
Group: Development/Libraries/Java
%description javadoc
Developer documentation for %{name} in JavaDoc
format.
%{summary}.
%package demo
Summary: Demonstration files for %{name}
Group: Development/Libraries/Java
Requires: %{name} = %{version}
%description demo
Demonstration files for %{name}. NOTE: It is
possible that some demonstration files are specially prepared for SUN
Java runtime environment. If they fail with IBM or BEA Java, the
package itself does not need to be broken.
%{summary}.
%package manual
Summary: Manual for %{name}
Group: Development/Libraries/Java
%description manual
Manual for %{name}
%{summary}.
%prep
%setup -q -n %{short_name}-%{version}
mkdir lib # duh
rm -rf docs/apidocs docs/*.patch docs/*.orig docs/*.rej
%patch0
pushd src/conf
sed -i 's/\r//' MANIFEST.MF
%patch1
popd
%patch2
%patch3 -p1
%patch4 -p1
%patch5 -p1
# Use javax classes, not com.sun ones
# assume no filename contains spaces
pushd src
for j in $(find . -name "*.java" -exec grep -l 'com\.sun\.net\.ssl' {} \;); do
sed -e 's|com\.sun\.net\.ssl|javax.net.ssl|' $j > tempf
cp tempf $j
done
rm tempf
popd
sed -i 's/\r//' RELEASE_NOTES.txt
sed -i 's/\r//' README.txt
sed -i 's/\r//' LICENSE.txt
%build
ant \
-Dant.build.javac.source=8 -Dant.build.javac.target=8 \
-Dbuild.sysclasspath=first \
-Djavadoc.j2sdk.link=%{_javadocdir}/java \
-Djavadoc.logging.link=%{_javadocdir}/apache-commons-logging \
-Dtest.failonerror=false \
-Dlib.dir=%{_javadir} \
-Djavac.encoding=UTF-8 \
dist test
%install
# jars
mkdir -p %{buildroot}%{_javadir}
cp -p dist/%{short_name}.jar \
%{buildroot}%{_javadir}/%{name}.jar
# compat symlink
pushd %{buildroot}%{_javadir}
ln -s %{name}.jar %{name}3.jar
ln -s %{name}.jar %{short_name}3.jar
ln -s %{name}.jar %{short_name}.jar
ln -s %{name}.jar jakarta-%{short_name}.jar
ln -s %{name}.jar jakarta-%{short_name}3.jar
popd
# pom
mkdir -p %{buildroot}%{_mavenpomdir}
cp -p %{SOURCE1} %{buildroot}%{_mavenpomdir}/%{name}.pom
%add_maven_depmap %{name}.pom %{name}.jar -a apache:commons-httpclient
# javadoc
mkdir -p %{buildroot}%{_javadocdir}
mv dist/docs/api %{buildroot}%{_javadocdir}/%{name}
%fdupes -s %{buildroot}%{_javadocdir}/%{name}
# demo
mkdir -p %{buildroot}%{_datadir}/%{name}
cp -pr src/examples src/contrib %{buildroot}%{_datadir}/%{name}
%fdupes -s %{buildroot}%{_datadir}/%{name}
# manual and docs
rm -f dist/docs/{BUILDING,TESTING}.txt
ln -s %{_javadocdir}/%{name} dist/docs/apidocs
%fdupes -s dist/docs
%files
%defattr(0644,root,root,0755)
%license LICENSE.txt
%doc README.txt RELEASE_NOTES.txt
%{_javadir}/%{name}.jar
%{_javadir}/%{name}3.jar
%{_javadir}/%{short_name}3.jar
%{_javadir}/%{short_name}.jar
%{_javadir}/jakarta-%{short_name}3.jar
%{_javadir}/jakarta-%{short_name}.jar
%{_mavenpomdir}/*
%if %{defined _maven_repository}
%{_mavendepmapfragdir}/%{name}
%else
%{_datadir}/maven-metadata/%{name}.xml*
%endif
%files javadoc
%defattr(0644,root,root,0755)
%doc %{_javadocdir}/%{name}
%files demo
%defattr(0644,root,root,0755)
%{_datadir}/%{name}
%files manual
%defattr(0644,root,root,0755)
%doc dist/docs/*
%changelog

BIN
commons-httpclient-3.1-src.tar.gz (Stored with Git LFS) Normal file

Binary file not shown.

254
commons-httpclient-3.1.pom Normal file
View File

@ -0,0 +1,254 @@
<?xml version="1.0" encoding="UTF-8"?><project>
<modelVersion>4.0.0</modelVersion>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<name>HttpClient</name>
<version>3.1</version>
<description>The HttpClient component supports the client-side of RFC 1945 (HTTP/1.0) and RFC 2616 (HTTP/1.1) , several related specifications (RFC 2109 (Cookies) , RFC 2617 (HTTP Authentication) , etc.), and provides a framework by which new request types (methods) or HTTP extensions can be created easily.</description>
<url>http://jakarta.apache.org/httpcomponents/httpclient-3.x/</url>
<issueManagement>
<url>http://issues.apache.org/jira/browse/HTTPCLIENT</url>
</issueManagement>
<ciManagement>
<notifiers>
<notifier>
<configuration>
<address>httpcomponents-dev@jakarta.apache.org</address>
</configuration>
</notifier>
</notifiers>
</ciManagement>
<inceptionYear>2001</inceptionYear>
<mailingLists>
<mailingList>
<name>HttpComponents Developer List</name>
<subscribe>httpcomponents-dev-subscribe@jakarta.apache.org</subscribe>
<unsubscribe>httpcomponents-dev-unsubscribe@jakarta.apache.org</unsubscribe>
<archive>http://mail-archives.apache.org/mod_mbox/jakarta-httpcomponents-dev/</archive>
</mailingList>
<mailingList>
<name>HttpClient User List</name>
<subscribe>httpclient-user-subscribe@jakarta.apache.org</subscribe>
<unsubscribe>httpclient-user-unsubscribe@jakarta.apache.org</unsubscribe>
<archive>http://mail-archives.apache.org/mod_mbox/jakarta-httpclient-user/</archive>
</mailingList>
</mailingLists>
<developers>
<developer>
<id>mbecke</id>
<name>Michael Becke</name>
<email>mbecke -at- apache.org</email>
<organization></organization>
<roles>
<role>Release Prime</role>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>jsdever</id>
<name>Jeff Dever</name>
<email>jsdever -at- apache.org</email>
<organization>Independent consultant</organization>
<roles>
<role>2.0 Release Prime</role>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>dion</id>
<name>dIon Gillard</name>
<email>dion -at- apache.org</email>
<organization>Multitask Consulting</organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>oglueck</id>
<name>Ortwin Glueck</name>
<email>oglueck -at- apache.org</email>
<url>http://www.odi.ch/</url>
<organization></organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>jericho</id>
<name>Sung-Gu</name>
<email>jericho -at- apache.org</email>
<organization></organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>olegk</id>
<name>Oleg Kalnichevski</name>
<email>olegk -at- apache.org</email>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>sullis</id>
<name>Sean C. Sullivan</name>
<email>sullis -at- apache.org</email>
<organization>Independent consultant</organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>adrian</id>
<name>Adrian Sutton</name>
<email>adrian.sutton -at- ephox.com</email>
<organization>Intencha</organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
<developer>
<id>rwaldhoff</id>
<name>Rodney Waldhoff</name>
<email>rwaldhoff -at- apache</email>
<organization>Britannica</organization>
<roles>
<role>Java Developer</role>
</roles>
</developer>
</developers>
<contributors>
<contributor>
<name>Armando Anton</name>
<email>armando.anton -at- newknow.com</email>
</contributor>
<contributor>
<name>Sebastian Bazley</name>
<email>sebb -at- apache.org</email>
</contributor>
<contributor>
<name>Ola Berg</name>
<email></email>
</contributor>
<contributor>
<name>Sam Berlin</name>
<email>sberlin -at- limepeer.com</email>
</contributor>
<contributor>
<name>Mike Bowler</name>
<email></email>
</contributor>
<contributor>
<name>Samit Jain</name>
<email>jain.samit -at- gmail.com</email>
</contributor>
<contributor>
<name>Eric Johnson</name>
<email>eric -at- tibco.com</email>
</contributor>
<contributor>
<name>Christian Kohlschuetter</name>
<email>ck -at- newsclub.de</email>
</contributor>
<contributor>
<name>Ryan Lubke</name>
<email>Ryan.Lubke -at- Sun.COM</email>
</contributor>
<contributor>
<name>Sam Maloney</name>
<email>sam.maloney -at- filogix.com</email>
</contributor>
<contributor>
<name>Rob Di Marco</name>
<email>rdimarco -at- hmsonline.com</email>
</contributor>
<contributor>
<name>Juergen Pill</name>
<email>Juergen.Pill -at- softwareag.com</email>
</contributor>
<contributor>
<name>Mohammad Rezaei</name>
<email>mohammad.rezaei -at- gs.com</email>
</contributor>
<contributor>
<name>Roland Weber</name>
<email>rolandw -at- apache.org</email>
</contributor>
<contributor>
<name>Laura Werner</name>
<email>laura -at- lwerner.org</email>
</contributor>
<contributor>
<name>Mikael Wilstrom</name>
<email>mikael.wikstrom -at- it.su.se</email>
</contributor>
</contributors>
<licenses>
<license>
<name>Apache License</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/httpcomponents/oac.hc3x/trunk</connection>
<url>http://svn.apache.org/repos/asf/jakarta/httpcomponents/oac.hc3x/trunk</url>
</scm>
<organization>
<name>Apache Software Foundation</name>
<url>http://jakarta.apache.org/</url>
</organization>
<build>
<sourceDirectory>src/java</sourceDirectory>
<testSourceDirectory>src/test</testSourceDirectory>
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test</directory>
<includes>
<include>**/*.keystore</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/TestAll.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<distributionManagement>
<site>
<id>default</id>
<name>Default Site</name>
<url>scp://people.apache.org//www/jakarta.apache.org/httpcomponents/httpclient-3.x/</url>
</site>
<status>converted</status>
</distributionManagement>
</project>

View File

@ -0,0 +1,369 @@
--- 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,25 @@
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.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+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;
@@ -55,6 +70,11 @@ public class SSLProtocolSocketFactory im
*/
private static final SSLProtocolSocketFactory factory = new SSLProtocolSocketFactory();
+ // This is a a sorted list, if you insert new elements do it orderdered.
+ private final static String[] BAD_COUNTRY_2LDS =
+ {"ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
+ "lg", "ne", "net", "or", "org"};
+
/**
* Gets an singleton instance of the SSLProtocolSocketFactory.
* @return a SSLProtocolSocketFactory
@@ -79,12 +99,14 @@ public class SSLProtocolSocketFactory im
InetAddress clientHost,
int clientPort)
throws IOException, UnknownHostException {
- return SSLSocketFactory.getDefault().createSocket(
+ Socket sslSocket = SSLSocketFactory.getDefault().createSocket(
host,
port,
clientHost,
clientPort
);
+ verifyHostName(host, (SSLSocket) sslSocket);
+ return sslSocket;
}
/**
@@ -124,16 +146,19 @@ public class SSLProtocolSocketFactory im
}
int timeout = params.getConnectionTimeout();
if (timeout == 0) {
- return createSocket(host, port, localAddress, localPort);
+ Socket sslSocket = createSocket(host, port, localAddress, localPort);
+ verifyHostName(host, (SSLSocket) sslSocket);
+ return sslSocket;
} else {
// To be eventually deprecated when migrated to Java 1.4 or above
- Socket socket = ReflectionSocketFactory.createSocket(
+ Socket sslSocket = ReflectionSocketFactory.createSocket(
"javax.net.ssl.SSLSocketFactory", host, port, localAddress, localPort, timeout);
- if (socket == null) {
- socket = ControllerThreadSocketFactory.createSocket(
+ if (sslSocket == null) {
+ sslSocket = ControllerThreadSocketFactory.createSocket(
this, host, port, localAddress, localPort, timeout);
}
- return socket;
+ verifyHostName(host, (SSLSocket) sslSocket);
+ return sslSocket;
}
}
@@ -142,10 +167,12 @@ public class SSLProtocolSocketFactory im
*/
public Socket createSocket(String host, int port)
throws IOException, UnknownHostException {
- return SSLSocketFactory.getDefault().createSocket(
+ Socket sslSocket = SSLSocketFactory.getDefault().createSocket(
host,
port
);
+ verifyHostName(host, (SSLSocket) sslSocket);
+ return sslSocket;
}
/**
@@ -157,13 +184,271 @@ public class SSLProtocolSocketFactory im
int port,
boolean autoClose)
throws IOException, UnknownHostException {
- return ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
+ Socket sslSocket = ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
socket,
host,
port,
autoClose
);
+ verifyHostName(host, (SSLSocket) sslSocket);
+ return sslSocket;
}
+
+
+
+
+ /**
+ * Verifies that the given hostname in certicifate is the hostname we are trying to connect to
+ * http://www.cvedetails.com/cve/CVE-2012-5783/
+ * @param host
+ * @param ssl
+ * @throws IOException
+ */
+
+ private static void verifyHostName(String host, SSLSocket ssl)
+ throws IOException {
+ if (host == null) {
+ throw new IllegalArgumentException("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();
+ verifyHostName(host.trim().toLowerCase(Locale.US), (X509Certificate) certs[0]);
+ }
+ /**
+ * Extract the names from the certificate and tests host matches one of them
+ * @param host
+ * @param cert
+ * @throws SSLException
+ */
+
+ private static void verifyHostName(final String host, X509Certificate cert)
+ throws SSLException {
+ // 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.
+
+ String cn = getCN(cert);
+ String[] subjectAlts = getDNSSubjectAlts(cert);
+ verifyHostName(host, cn.toLowerCase(Locale.US), subjectAlts);
+
+ }
+
+ /**
+ * Extract all alternative names from a certificate.
+ * @param cert
+ * @return
+ */
+ private static String[] getDNSSubjectAlts(X509Certificate cert) {
+ LinkedList subjectAltList = new LinkedList();
+ Collection c = null;
+ try {
+ c = cert.getSubjectAlternativeNames();
+ } catch (CertificateParsingException cpe) {
+ // Should probably log.debug() this?
+ cpe.printStackTrace();
+ }
+ if (c != null) {
+ Iterator it = c.iterator();
+ while (it.hasNext()) {
+ List list = (List) it.next();
+ int type = ((Integer) list.get(0)).intValue();
+ // If type is 2, then we've got a dNSName
+ if (type == 2) {
+ String s = (String) list.get(1);
+ subjectAltList.add(s);
+ }
+ }
+ }
+ if (!subjectAltList.isEmpty()) {
+ String[] subjectAlts = new String[subjectAltList.size()];
+ subjectAltList.toArray(subjectAlts);
+ return subjectAlts;
+ } else {
+ return new String[0];
+ }
+
+ }
+ /**
+ * Verifies
+ * @param host
+ * @param cn
+ * @param subjectAlts
+ * @throws SSLException
+ */
+
+ private static void verifyHostName(final String host, String cn, String[] subjectAlts)throws SSLException{
+ StringBuffer cnTested = new StringBuffer();
+
+ for (int i = 0; i < subjectAlts.length; i++){
+ String name = subjectAlts[i];
+ if (name != null) {
+ name = name.toLowerCase();
+ if (verifyHostName(host, name)){
+ return;
+ }
+ cnTested.append("/").append(name);
+ }
+ }
+ if (cn != null && verifyHostName(host, cn)){
+ return;
+ }
+ cnTested.append("/").append(cn);
+ throw new SSLException("hostname in certificate didn't match: <"
+ + host + "> != <" + cnTested + ">");
+
+ }
+
+ private static boolean verifyHostName(final String host, final String cn){
+ if (doWildCard(cn) && !isIPAddress(host)) {
+ return matchesWildCard(cn, host);
+ }
+ return host.equalsIgnoreCase(cn);
+ }
+ private static boolean doWildCard(String cn) {
+ // Contains a wildcard
+ // wildcard in the first block
+ // not an ipaddress (ip addres must explicitily be equal)
+ // not using 2nd level common tld : ex: not for *.co.uk
+ String parts[] = cn.split("\\.");
+ return parts.length >= 3 &&
+ parts[0].endsWith("*") &&
+ acceptableCountryWildcard(cn) &&
+ !isIPAddress(cn);
+ }
+
+
+ private static final Pattern IPV4_PATTERN =
+ Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}$");
+
+ private static final Pattern IPV6_STD_PATTERN =
+ Pattern.compile("^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$");
+
+ private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
+ Pattern.compile("^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$");
+
+
+ private static boolean isIPAddress(final String hostname) {
+ return hostname != null
+ && (
+ IPV4_PATTERN.matcher(hostname).matches()
+ || IPV6_STD_PATTERN.matcher(hostname).matches()
+ || IPV6_HEX_COMPRESSED_PATTERN.matcher(hostname).matches()
+ );
+
+ }
+
+ private static boolean acceptableCountryWildcard(final String cn) {
+ // 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...
+ // The [*.co.uk] problem is an interesting one. Should we just
+ // hope that CA's would never foolishly allow such a
+ // certificate to happen?
+
+ String[] parts = cn.split("\\.");
+ // Only checks for 3 levels, with country code of 2 letters.
+ if (parts.length > 3 || parts[parts.length - 1].length() != 2) {
+ return true;
+ }
+ String countryCode = parts[parts.length - 2];
+ return Arrays.binarySearch(BAD_COUNTRY_2LDS, countryCode) < 0;
+ }
+
+ private static boolean matchesWildCard(final String cn,
+ final String hostName) {
+ String parts[] = cn.split("\\.");
+ boolean match = false;
+ String firstpart = parts[0];
+ if (firstpart.length() > 1) {
+ // server
+ // e.g. server
+ String prefix = firstpart.substring(0, firstpart.length() - 1);
+ // skipwildcard part from cn
+ String suffix = cn.substring(firstpart.length());
+ // skip wildcard part from host
+ String hostSuffix = hostName.substring(prefix.length());
+ match = hostName.startsWith(prefix) && hostSuffix.endsWith(suffix);
+ } else {
+ match = hostName.endsWith(cn.substring(1));
+ }
+ if (match) {
+ // I f we're in strict mode ,
+ // [ .foo.com] is not allowed to match [a.b.foo.com]
+ match = countDots(hostName) == countDots(cn);
+ }
+ return match;
+ }
+
+ private static int countDots(final String data) {
+ int dots = 0;
+ for (int i = 0; i < data.length(); i++) {
+ if (data.charAt(i) == '.') {
+ dots += 1;
+ }
+ }
+ 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(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);
+ }
+ }
+ }
+ return null;
+ }
/**
* All instances of SSLProtocolSocketFactory are the same.