HTTPCLIENT-614: allow different strategies when checking CN of x509 cert
* Test coverage Contributed by Julius Davies <juliusdavies at gmail.com> Reviewed by Oleg Kalnichevski git-svn-id: https://svn.apache.org/repos/asf/jakarta/httpcomponents/httpclient/trunk@487346 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
dd9500e009
commit
81e5ce2d12
|
@ -0,0 +1,434 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* Copyright 2002-2004 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
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.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Interface for checking if a hostname matches the names stored inside the
|
||||
* server's X.509 certificate. Implements javax.net.ssl.HostnameVerifier, but
|
||||
* we don't actually use that interface. Instead we added some methods that
|
||||
* take String parameters (instead of javax.net.ssl.HostnameVerifier's
|
||||
* SSLSession). JUnit is a lot easier this way! :-)
|
||||
* <p/>
|
||||
* We provide the HostnameVerifier.DEFAULT, HostnameVerifier.STRICT, and
|
||||
* HostnameVerifier.ALLOW_ALL implementations. But feel free to define
|
||||
* your own implementation!
|
||||
* <p/>
|
||||
* Inspired by Sebastian Hauer's original StrictSSLProtocolSocketFactory in the
|
||||
* HttpClient "contrib" repository.
|
||||
*
|
||||
* @author Julius Davies
|
||||
* @author <a href="mailto:hauer@psicode.com">Sebastian Hauer</a>
|
||||
* @since 8-Dec-2006
|
||||
*/
|
||||
public interface HostnameVerifier extends javax.net.ssl.HostnameVerifier {
|
||||
|
||||
boolean verify(String host, SSLSession session);
|
||||
|
||||
void verify(String host, SSLSocket ssl) throws IOException;
|
||||
|
||||
void verify(String host, X509Certificate cert) throws SSLException;
|
||||
|
||||
/**
|
||||
* Checks to see if the supplied hostname matches any of the supplied CNs
|
||||
* or "DNS" Subject-Alts. Most implementations only look at the first CN,
|
||||
* and ignore any additional CNs. Most implementations do look at all of
|
||||
* the "DNS" Subject-Alts. The CNs or Subject-Alts may contain wildcards
|
||||
* according to RFC 2818.
|
||||
*
|
||||
* @param cns CN fields, in order, as extracted from the X.509
|
||||
* certificate.
|
||||
* @param subjectAlts Subject-Alt fields of type 2 ("DNS"), as extracted
|
||||
* from the X.509 certificate.
|
||||
* @param host The hostname to verify.
|
||||
* @throws SSLException If verification failed.
|
||||
*/
|
||||
void verify(String host, String[] cns, String[] subjectAlts)
|
||||
throws SSLException;
|
||||
|
||||
|
||||
/**
|
||||
* The DEFAULT HostnameVerifier works the same way as Curl and Firefox.
|
||||
* <p/>
|
||||
* The hostname must match either the first CN, or any of the subject-alts.
|
||||
* A wildcard can occur in the CN, and in any of the subject-alts.
|
||||
* <p/>
|
||||
* The only difference between DEFAULT and STRICT is that a wildcard (such
|
||||
* as "*.foo.com") with DEFAULT matches all subdomains, including
|
||||
* "a.b.foo.com".
|
||||
*/
|
||||
public final static HostnameVerifier DEFAULT =
|
||||
new AbstractVerifier() {
|
||||
public final void verify(final String host, final String[] cns,
|
||||
final String[] subjectAlts)
|
||||
throws SSLException {
|
||||
verify(host, cns, subjectAlts, false);
|
||||
}
|
||||
|
||||
public final String toString() { return "DEFAULT"; }
|
||||
};
|
||||
|
||||
/**
|
||||
* The Strict HostnameVerifier works the same way as Sun Java 1.4, Sun
|
||||
* Java 5, Sun Java 6-rc. It's also pretty close to IE6. This
|
||||
* implementation appears to be compliant with RFC 2818 for dealing with
|
||||
* wildcards.
|
||||
* <p/>
|
||||
* The hostname must match either the first CN, or any of the subject-alts.
|
||||
* A wildcard can occur in the CN, and in any of the subject-alts. The
|
||||
* one divergence from IE6 is how we only check the first CN. IE6 allows
|
||||
* a match against any of the CNs present. We decided to follow in
|
||||
* Sun Java 1.4's footsteps and only check the first CN. (If you need
|
||||
* to check all the CN's, feel free to write your own implementation!).
|
||||
* <p/>
|
||||
* A wildcard such as "*.foo.com" matches only subdomains in the same
|
||||
* level, for example "a.foo.com". It does not match deeper subdomains
|
||||
* such as "a.b.foo.com".
|
||||
*/
|
||||
public final static HostnameVerifier STRICT =
|
||||
new AbstractVerifier() {
|
||||
public final void verify(final String host, final String[] cns,
|
||||
final String[] subjectAlts)
|
||||
throws SSLException {
|
||||
verify(host, cns, subjectAlts, true);
|
||||
}
|
||||
|
||||
public final String toString() { return "STRICT"; }
|
||||
};
|
||||
|
||||
/**
|
||||
* The ALLOW_ALL HostnameVerifier essentially turns hostname verification
|
||||
* off. This implementation is a no-op, and never throws the SSLException.
|
||||
*/
|
||||
public final static HostnameVerifier ALLOW_ALL =
|
||||
new AbstractVerifier() {
|
||||
public final void verify(final String host, final String[] cns,
|
||||
final String[] subjectAlts) {
|
||||
// Allow everything - so never blowup.
|
||||
}
|
||||
|
||||
public final String toString() { return "ALLOW_ALL"; }
|
||||
};
|
||||
|
||||
abstract class AbstractVerifier implements HostnameVerifier {
|
||||
|
||||
/**
|
||||
* This contains a list of 2nd-level domains that aren't allowed to
|
||||
* have wildcards when combined with country-codes.
|
||||
* For example: [*.co.uk].
|
||||
* <p/>
|
||||
* The [*.co.uk] problem is an interesting one. Should we just hope
|
||||
* that CA's would never foolishly allow such a certificate to happen?
|
||||
* Looks like we're the only implementation guarding against this.
|
||||
* Firefox, Curl, Sun Java 1.4, 5, 6 don't bother with this check.
|
||||
*/
|
||||
private final static String[] BAD_COUNTRY_2LDS =
|
||||
{ "ac", "co", "com", "ed", "edu", "go", "gouv", "gov", "info",
|
||||
"lg", "ne", "net", "or", "org" };
|
||||
|
||||
static {
|
||||
// Just in case developer forgot to manually sort the array. :-)
|
||||
Arrays.sort(BAD_COUNTRY_2LDS);
|
||||
}
|
||||
|
||||
AbstractVerifier() {}
|
||||
|
||||
public final void verify(String host, SSLSocket ssl)
|
||||
throws IOException {
|
||||
if(host == null) {
|
||||
throw new NullPointerException("host to verify is 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'
|
||||
// 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];
|
||||
verify(host, x509);
|
||||
}
|
||||
|
||||
public final boolean verify(String host, SSLSession session) {
|
||||
try {
|
||||
Certificate[] certs = session.getPeerCertificates();
|
||||
X509Certificate x509 = (X509Certificate) certs[0];
|
||||
verify(host, x509);
|
||||
return true;
|
||||
}
|
||||
catch(SSLException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public final void verify(String host, X509Certificate cert)
|
||||
throws SSLException {
|
||||
String[] cns = getCNs(cert);
|
||||
String[] subjectAlts = getDNSSubjectAlts(cert);
|
||||
verify(host, cns, subjectAlts);
|
||||
}
|
||||
|
||||
public final void verify(final String host, final String[] cns,
|
||||
final String[] subjectAlts,
|
||||
final boolean strictWithSubDomains)
|
||||
throws SSLException {
|
||||
|
||||
// Build the list of names we're going to check. Our DEFAULT and
|
||||
// STRICT implementations of the HostnameVerifier only use the
|
||||
// first CN provided. All other CNs are ignored.
|
||||
// (Firefox, wget, curl, Sun Java 1.4, 5, 6 all work this way).
|
||||
LinkedList names = new LinkedList();
|
||||
if(cns != null && cns.length > 0 && cns[0] != null) {
|
||||
names.add(cns[0]);
|
||||
}
|
||||
if(subjectAlts != null) {
|
||||
for(int i = 0; i < subjectAlts.length; i++) {
|
||||
if(subjectAlts[i] != null) {
|
||||
names.add(subjectAlts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(names.isEmpty()) {
|
||||
String msg = "Certificate for <" + host + "> doesn't contain CN or DNS subjectAlt";
|
||||
throw new SSLException(msg);
|
||||
}
|
||||
|
||||
// StringBuffer for building the error message.
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
// We're can be case-insensitive when comparing the host we used to
|
||||
// establish the socket to the hostname in the certificate.
|
||||
String hostName = host.trim().toLowerCase();
|
||||
boolean match = false;
|
||||
for(Iterator it = names.iterator(); it.hasNext();) {
|
||||
// Don't trim the CN, though!
|
||||
String cn = (String) it.next();
|
||||
cn = cn.toLowerCase();
|
||||
// Store CN in StringBuffer in case we need to report an error.
|
||||
buf.append(" <");
|
||||
buf.append(cn);
|
||||
buf.append('>');
|
||||
if(it.hasNext()) {
|
||||
buf.append(" OR");
|
||||
}
|
||||
|
||||
// The CN better have at least two dots if it wants wildcard
|
||||
// action. It also can't be [*.co.uk] or [*.co.jp] or
|
||||
// [*.org.uk], etc...
|
||||
boolean doWildcard = cn.startsWith("*.") &&
|
||||
cn.lastIndexOf('.') >= 0 &&
|
||||
acceptableCountryWildcard(cn);
|
||||
|
||||
if(doWildcard) {
|
||||
match = hostName.endsWith(cn.substring(1));
|
||||
if(match && strictWithSubDomains) {
|
||||
// If we're in strict mode, then [*.foo.com] is not
|
||||
// allowed to match [a.b.foo.com]
|
||||
match = countDots(hostName) == countDots(cn);
|
||||
}
|
||||
} else {
|
||||
match = hostName.equals(cn);
|
||||
}
|
||||
if(match) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!match) {
|
||||
throw new SSLException("hostname in certificate didn't match: <" + host + "> !=" + buf);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean acceptableCountryWildcard(String cn) {
|
||||
int cnLen = cn.length();
|
||||
if(cnLen >= 7 && cnLen <= 9) {
|
||||
// Look for the '.' in the 3rd-last position:
|
||||
if(cn.charAt(cnLen - 3) == '.') {
|
||||
// Trim off the [*.] and the [.XX].
|
||||
String s = cn.substring(2, cnLen - 3);
|
||||
// And test against the sorted array of bad 2lds:
|
||||
int x = Arrays.binarySearch(BAD_COUNTRY_2LDS, s);
|
||||
return x < 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String[] getCNs(X509Certificate cert) {
|
||||
LinkedList cnList = new LinkedList();
|
||||
/*
|
||||
Sebastian Hauer's original StrictSSLProtocolSocketFactory used
|
||||
getName() and had the following comment:
|
||||
|
||||
Parses a X.500 distinguished name for the value of the
|
||||
"Common Name" field. This is done a bit sloppy right
|
||||
now and should probably be done a bit more according to
|
||||
<code>RFC 2253</code>.
|
||||
|
||||
I've noticed that toString() seems to do a better job than
|
||||
getName() on these X500Principal objects, so I'm hoping that
|
||||
addresses Sebastian's concern.
|
||||
|
||||
For example, getName() gives me this:
|
||||
1.2.840.113549.1.9.1=#16166a756c6975736461766965734063756362632e636f6d
|
||||
|
||||
whereas toString() gives me this:
|
||||
EMAILADDRESS=juliusdavies@cucbc.com
|
||||
|
||||
Looks like toString() even works with non-ascii domain names!
|
||||
I tested it with "花子.co.jp" and it worked fine.
|
||||
*/
|
||||
String subjectPrincipal = cert.getSubjectX500Principal().toString();
|
||||
StringTokenizer st = new StringTokenizer(subjectPrincipal, ",");
|
||||
while(st.hasMoreTokens()) {
|
||||
String tok = st.nextToken();
|
||||
int x = tok.indexOf("CN=");
|
||||
if(x >= 0) {
|
||||
cnList.add(tok.substring(x + 3));
|
||||
}
|
||||
}
|
||||
if(!cnList.isEmpty()) {
|
||||
String[] cns = new String[cnList.size()];
|
||||
cnList.toArray(cns);
|
||||
return cns;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts the array of SubjectAlt DNS names from an X509Certificate.
|
||||
* Returns null if there aren't any.
|
||||
* <p/>
|
||||
* Note: Java doesn't appear able to extract international characters
|
||||
* from the SubjectAlts. It can only extract international characters
|
||||
* from the CN field.
|
||||
* <p/>
|
||||
* (Or maybe the version of OpenSSL I'm using to test isn't storing the
|
||||
* international characters correctly in the SubjectAlts?).
|
||||
*
|
||||
* @param cert X509Certificate
|
||||
* @return Array of SubjectALT DNS names stored in the certificate.
|
||||
*/
|
||||
public 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 null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of dots "." in a string.
|
||||
* @param s string to count dots from
|
||||
* @return number of dots
|
||||
*/
|
||||
public static int countDots(final String s) {
|
||||
int count = 0;
|
||||
for(int i = 0; i < s.length(); i++) {
|
||||
if(s.charAt(i) == '.') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -34,16 +34,14 @@ import org.apache.http.conn.SecureSocketFactory;
|
|||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
@ -54,8 +52,6 @@ import java.security.KeyStoreException;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -156,6 +152,7 @@ public class SSLSocketFactory implements SecureSocketFactory {
|
|||
|
||||
private final SSLContext sslcontext;
|
||||
private final javax.net.ssl.SSLSocketFactory socketfactory;
|
||||
private HostnameVerifier hostnameVerifier = HostnameVerifier.DEFAULT;
|
||||
|
||||
public SSLSocketFactory(
|
||||
String algorithm,
|
||||
|
@ -206,8 +203,7 @@ public class SSLSocketFactory implements SecureSocketFactory {
|
|||
public SSLSocketFactory() {
|
||||
super();
|
||||
this.sslcontext = null;
|
||||
this.socketfactory = (javax.net.ssl.SSLSocketFactory)
|
||||
javax.net.ssl.SSLSocketFactory.getDefault();
|
||||
this.socketfactory = HttpsURLConnection.getDefaultSSLSocketFactory();
|
||||
}
|
||||
|
||||
private static KeyManager[] createKeyManagers(final KeyStore keystore, final String password)
|
||||
|
@ -261,155 +257,47 @@ public class SSLSocketFactory implements SecureSocketFactory {
|
|||
if (params == null) {
|
||||
throw new IllegalArgumentException("Parameters may not be null");
|
||||
}
|
||||
SSLSocket socket = (SSLSocket) this.socketfactory.createSocket();
|
||||
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket();
|
||||
if (localAddress != null) {
|
||||
socket.bind(new InetSocketAddress(localAddress, localPort));
|
||||
sslSocket.bind(new InetSocketAddress(localAddress, localPort));
|
||||
}
|
||||
int timeout = HttpConnectionParams.getConnectionTimeout(params);
|
||||
socket.connect(new InetSocketAddress(host, port), timeout);
|
||||
|
||||
verifyHostName( host, (SSLSocket) socket );
|
||||
|
||||
sslSocket.connect(new InetSocketAddress(host, port), timeout);
|
||||
hostnameVerifier.verify(host, sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
|
||||
return socket;
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SecureSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
|
||||
*/
|
||||
public Socket createSocket(
|
||||
Socket socket,
|
||||
String host,
|
||||
int port,
|
||||
boolean autoClose)
|
||||
throws IOException, UnknownHostException {
|
||||
SSLSocket s = (SSLSocket) this.socketfactory.createSocket(
|
||||
final Socket socket,
|
||||
final String host,
|
||||
final int port,
|
||||
final boolean autoClose
|
||||
) throws IOException, UnknownHostException {
|
||||
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
|
||||
socket,
|
||||
host,
|
||||
port,
|
||||
autoClose
|
||||
);
|
||||
|
||||
verifyHostName( host, (SSLSocket) socket );
|
||||
|
||||
hostnameVerifier.verify(host, sslSocket);
|
||||
// verifyHostName() didn't blowup - good!
|
||||
return s;
|
||||
return sslSocket;
|
||||
}
|
||||
|
||||
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 ) );
|
||||
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
|
||||
if ( hostnameVerifier == null ) {
|
||||
this.hostnameVerifier = HostnameVerifier.DEFAULT;
|
||||
} else {
|
||||
match = host.equals( cn );
|
||||
}
|
||||
if ( !match ) {
|
||||
throw new SSLException( "hostname in certificate didn't match: <" + host + "> != <" + cn + ">" );
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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;
|
||||
}
|
||||
public HostnameVerifier getHostnameVerifier() {
|
||||
return hostnameVerifier;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,451 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* Copyright 1999-2006 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
/**
|
||||
* Some X509 certificates to test against.
|
||||
* <p/>
|
||||
* Note: some of these certificates have Japanese Kanji in the "subjectAlt"
|
||||
* field (UTF8). Not sure how realistic that is since international characters
|
||||
* in DNS names usually get translated into ASCII using "xn--" style DNS
|
||||
* entries. "xn--i8s592g.co.jp" is what FireFox actually uses when trying to
|
||||
* find 花子.co.jp. So would the CN in the certificate contain
|
||||
* "xn--i8s592g.co.jp" in ASCII, or "花子.co.jp" in UTF8? (Both?)
|
||||
*
|
||||
* @author Julius Davies
|
||||
* @since 11-Dec-2006
|
||||
*/
|
||||
public interface CertificatesToPlayWith {
|
||||
|
||||
/**
|
||||
* CN=foo.com
|
||||
*/
|
||||
public final static byte[] X509_FOO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aQMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzE0MVoXDTI4MTEwNTE1MzE0MVowgaQx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
|
||||
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
|
||||
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
|
||||
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
|
||||
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
|
||||
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
|
||||
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
|
||||
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB\n" +
|
||||
"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE\n" +
|
||||
"FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS\n" +
|
||||
"yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQC3jRmEya6sQCkmieULcvx8zz1euCk9\n" +
|
||||
"fSez7BEtki8+dmfMXe3K7sH0lI8f4jJR0rbSCjpmCQLYmzC3NxBKeJOW0RcjNBpO\n" +
|
||||
"c2JlGO9auXv2GDP4IYiXElLJ6VSqc8WvDikv0JmCCWm0Zga+bZbR/EWN5DeEtFdF\n" +
|
||||
"815CLpJZNcYwiYwGy/CVQ7w2TnXlG+mraZOz+owr+cL6J/ZesbdEWfjoS1+cUEhE\n" +
|
||||
"HwlNrAu8jlZ2UqSgskSWlhYdMTAP9CPHiUv9N7FcT58Itv/I4fKREINQYjDpvQcx\n" +
|
||||
"SaTYb9dr5sB4WLNglk7zxDtM80H518VvihTcP7FHL+Gn6g4j5fkI98+S\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=花子.co.jp
|
||||
*/
|
||||
public final static byte[] X509_HANAKO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIESzCCAzOgAwIBAgIJAIz+EYMBU6aTMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1NDIxNVoXDTI4MTEwNTE1NDIxNVowgakx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEVMBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkB\n" +
|
||||
"FhZqdWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" +
|
||||
"MIIBCgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjU\n" +
|
||||
"g4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQc\n" +
|
||||
"wHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t\n" +
|
||||
"7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAn\n" +
|
||||
"AxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArD\n" +
|
||||
"qUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwG\n" +
|
||||
"CWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNV\n" +
|
||||
"HQ4EFgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLS\n" +
|
||||
"rNuzA1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBALJ27i3okV/KvlDp6KMID3gd\n" +
|
||||
"ITl68PyItzzx+SquF8gahMh016NX73z/oVZoVUNdftla8wPUB1GwIkAnGkhQ9LHK\n" +
|
||||
"spBdbRiCj0gMmLCsX8SrjFvr7cYb2cK6J/fJe92l1tg/7Y4o7V/s4JBe/cy9U9w8\n" +
|
||||
"a0ctuDmEBCgC784JMDtT67klRfr/2LlqWhlOEq7pUFxRLbhpquaAHSOjmIcWnVpw\n" +
|
||||
"9BsO7qe46hidgn39hKh1WjKK2VcL/3YRsC4wUi0PBtFW6ScMCuMhgIRXSPU55Rae\n" +
|
||||
"UIlOdPjjr1SUNWGId1rD7W16Scpwnknn310FNxFMHVI0GTGFkNdkilNCFJcIoRA=\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=foo.com, subjectAlt=bar.com
|
||||
*/
|
||||
public final static byte[] X509_FOO_BAR = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEXDCCA0SgAwIBAgIJAIz+EYMBU6aRMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzYyOVoXDTI4MTEwNTE1MzYyOVowgaQx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
|
||||
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
|
||||
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
|
||||
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
|
||||
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
|
||||
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
|
||||
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
|
||||
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCG\n" +
|
||||
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
|
||||
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
|
||||
"A1LKh6YNPg0wEgYDVR0RBAswCYIHYmFyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEA\n" +
|
||||
"dQyprNZBmVnvuVWjV42sey/PTfkYShJwy1j0/jcFZR/ypZUovpiHGDO1DgL3Y3IP\n" +
|
||||
"zVQ26uhUsSw6G0gGRiaBDe/0LUclXZoJzXX1qpS55OadxW73brziS0sxRgGrZE/d\n" +
|
||||
"3g5kkio6IED47OP6wYnlmZ7EKP9cqjWwlnvHnnUcZ2SscoLNYs9rN9ccp8tuq2by\n" +
|
||||
"88OyhKwGjJfhOudqfTNZcDzRHx4Fzm7UsVaycVw4uDmhEHJrAsmMPpj/+XRK9/42\n" +
|
||||
"2xq+8bc6HojdtbCyug/fvBZvZqQXSmU8m8IVcMmWMz0ZQO8ee3QkBHMZfCy7P/kr\n" +
|
||||
"VbWx/uETImUu+NZg22ewEw==\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=foo.com, subjectAlt=bar.com, subjectAlt=花子.co.jp
|
||||
* (hanako.co.jp in kanji)
|
||||
*/
|
||||
public final static byte[] X509_FOO_BAR_HANAKO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEajCCA1KgAwIBAgIJAIz+EYMBU6aSMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE1MzgxM1oXDTI4MTEwNTE1MzgxM1owgaQx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEQMA4GA1UEAxMHZm9vLmNvbTElMCMGCSqGSIb3DQEJARYWanVs\n" +
|
||||
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
|
||||
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
|
||||
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
|
||||
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
|
||||
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
|
||||
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
|
||||
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaOBnjCBmzAJBgNVHRMEAjAAMCwGCWCG\n" +
|
||||
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
|
||||
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
|
||||
"A1LKh6YNPg0wIAYDVR0RBBkwF4IHYmFyLmNvbYIM6Iqx5a2QLmNvLmpwMA0GCSqG\n" +
|
||||
"SIb3DQEBBQUAA4IBAQBeZs7ZIYyKtdnVxVvdLgwySEPOE4pBSXii7XYv0Q9QUvG/\n" +
|
||||
"++gFGQh89HhABzA1mVUjH5dJTQqSLFvRfqTHqLpxSxSWqMHnvRM4cPBkIRp/XlMK\n" +
|
||||
"PlXadYtJLPTgpbgvulA1ickC9EwlNYWnowZ4uxnfsMghW4HskBqaV+PnQ8Zvy3L0\n" +
|
||||
"12c7Cg4mKKS5pb1HdRuiD2opZ+Hc77gRQLvtWNS8jQvd/iTbh6fuvTKfAOFoXw22\n" +
|
||||
"sWIKHYrmhCIRshUNohGXv50m2o+1w9oWmQ6Dkq7lCjfXfUB4wIbggJjpyEtbNqBt\n" +
|
||||
"j4MC2x5rfsLKKqToKmNE7pFEgqwe8//Aar1b+Qj+\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=*.foo.com
|
||||
*/
|
||||
public final static byte[] X509_WILD_FOO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIESDCCAzCgAwIBAgIJAIz+EYMBU6aUMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTU1NVoXDTI4MTEwNTE2MTU1NVowgaYx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq\n" +
|
||||
"dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
|
||||
"CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN\n" +
|
||||
"jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0\n" +
|
||||
"ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1\n" +
|
||||
"JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6\n" +
|
||||
"q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx\n" +
|
||||
"qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCG\n" +
|
||||
"SAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4E\n" +
|
||||
"FgQUnxR3vz86tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuz\n" +
|
||||
"A1LKh6YNPg0wDQYJKoZIhvcNAQEFBQADggEBAH0ipG6J561UKUfgkeW7GvYwW98B\n" +
|
||||
"N1ZooWX+JEEZK7+Pf/96d3Ij0rw9ACfN4bpfnCq0VUNZVSYB+GthQ2zYuz7tf/UY\n" +
|
||||
"A6nxVgR/IjG69BmsBl92uFO7JTNtHztuiPqBn59pt+vNx4yPvno7zmxsfI7jv0ww\n" +
|
||||
"yfs+0FNm7FwdsC1k47GBSOaGw38kuIVWqXSAbL4EX9GkryGGOKGNh0qvAENCdRSB\n" +
|
||||
"G9Z6tyMbmfRY+dLSh3a9JwoEcBUso6EWYBakLbq4nG/nvYdYvG9ehrnLVwZFL82e\n" +
|
||||
"l3Q/RK95bnA6cuRClGusLad0e6bjkBzx/VQ3VarDEpAkTLUGVAa0CLXtnyc=\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=*.co.jp
|
||||
*/
|
||||
public final static byte[] X509_WILD_CO_JP = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIERjCCAy6gAwIBAgIJAIz+EYMBU6aVMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTYzMFoXDTI4MTEwNTE2MTYzMFowgaQx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEQMA4GA1UEAxQHKi5jby5qcDElMCMGCSqGSIb3DQEJARYWanVs\n" +
|
||||
"aXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC\n" +
|
||||
"ggEBAMhjr5aCPoyp0R1iroWAfnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2B\n" +
|
||||
"lYho4O84X244QrZTRl8kQbYtxnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRy\n" +
|
||||
"zerA/ZtrlUqf+lKo0uWcocxeRc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY\n" +
|
||||
"07hNKXAb2odnVqgzcYiDkLV8ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8\n" +
|
||||
"BqnGd87xQU3FVZI4tbtkB+KzjD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiV\n" +
|
||||
"JTxpTKqym93whYk93l3ocEe55c0CAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgB\n" +
|
||||
"hvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYE\n" +
|
||||
"FJ8Ud78/OrbKOIJCSBYs2tDLXofYMB8GA1UdIwQYMBaAFHua2o+QmU5S0qzbswNS\n" +
|
||||
"yoemDT4NMA0GCSqGSIb3DQEBBQUAA4IBAQA0sWglVlMx2zNGvUqFC73XtREwii53\n" +
|
||||
"CfMM6mtf2+f3k/d8KXhLNySrg8RRlN11zgmpPaLtbdTLrmG4UdAHHYr8O4y2BBmE\n" +
|
||||
"1cxNfGxxechgF8HX10QV4dkyzp6Z1cfwvCeMrT5G/V1pejago0ayXx+GPLbWlNeZ\n" +
|
||||
"S+Kl0m3p+QplXujtwG5fYcIpaGpiYraBLx3Tadih39QN65CnAh/zRDhLCUzKyt9l\n" +
|
||||
"UGPLEUDzRHMPHLnSqT1n5UU5UDRytbjJPXzF+l/+WZIsanefWLsxnkgAuZe/oMMF\n" +
|
||||
"EJMryEzOjg4Tfuc5qM0EXoPcQ/JlheaxZ40p2IyHqbsWV4MRYuFH4bkM\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=*.foo.com, subjectAlt=*.bar.com, subjectAlt=*.花子.co.jp
|
||||
* (*.hanako.co.jp in kanji)
|
||||
*/
|
||||
public final static byte[] X509_WILD_FOO_BAR_HANAKO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEcDCCA1igAwIBAgIJAIz+EYMBU6aWMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTczMVoXDTI4MTEwNTE2MTczMVowgaYx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhNYXJ5bGFuZDEUMBIGA1UEBxMLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoTDmh0dHBjb21wb25lbnRzMRowGAYDVQQLExF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczESMBAGA1UEAxQJKi5mb28uY29tMSUwIwYJKoZIhvcNAQkBFhZq\n" +
|
||||
"dWxpdXNkYXZpZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" +
|
||||
"CgKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pN\n" +
|
||||
"jYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0\n" +
|
||||
"ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1\n" +
|
||||
"JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6\n" +
|
||||
"q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYx\n" +
|
||||
"qJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABo4GiMIGfMAkGA1UdEwQCMAAwLAYJ\n" +
|
||||
"YIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1Ud\n" +
|
||||
"DgQWBBSfFHe/Pzq2yjiCQkgWLNrQy16H2DAfBgNVHSMEGDAWgBR7mtqPkJlOUtKs\n" +
|
||||
"27MDUsqHpg0+DTAkBgNVHREEHTAbggkqLmJhci5jb22CDiou6Iqx5a2QLmNvLmpw\n" +
|
||||
"MA0GCSqGSIb3DQEBBQUAA4IBAQBobWC+D5/lx6YhX64CwZ26XLjxaE0S415ajbBq\n" +
|
||||
"DK7lz+Rg7zOE3GsTAMi+ldUYnhyz0wDiXB8UwKXl0SDToB2Z4GOgqQjAqoMmrP0u\n" +
|
||||
"WB6Y6dpkfd1qDRUzI120zPYgSdsXjHW9q2H77iV238hqIU7qCvEz+lfqqWEY504z\n" +
|
||||
"hYNlknbUnR525ItosEVwXFBJTkZ3Yw8gg02c19yi8TAh5Li3Ad8XQmmSJMWBV4XK\n" +
|
||||
"qFr0AIZKBlg6NZZFf/0dP9zcKhzSriW27bY0XfzA6GSiRDXrDjgXq6baRT6YwgIg\n" +
|
||||
"pgJsDbJtZfHnV1nd3M6zOtQPm1TIQpNmMMMd/DPrGcUQerD3\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* CN=foo.com, CN=bar.com, CN=花子.co.jp
|
||||
*/
|
||||
public final static byte[] X509_THREE_CNS_FOO_BAR_HANAKO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEbzCCA1egAwIBAgIJAIz+EYMBU6aXMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MTk0NVoXDTI4MTEwNTE2MTk0NVowgc0x\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczEQMA4GA1UEAwwHZm9vLmNvbTEQMA4GA1UEAwwHYmFyLmNvbTEV\n" +
|
||||
"MBMGA1UEAwwM6Iqx5a2QLmNvLmpwMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyGOv\n" +
|
||||
"loI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7PlpgpjUg4pNjYGViGjg7zhf\n" +
|
||||
"bjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc8BQcwHf0ZHLN6sD9m2uV\n" +
|
||||
"Sp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTjHE5t7iu1JVjTuE0pcBva\n" +
|
||||
"h2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindxOSAnAxK6q/wGqcZ3zvFB\n" +
|
||||
"TcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfDHArDqUYxqJUlPGlMqrKb\n" +
|
||||
"3fCFiT3eXehwR7nlzQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf\n" +
|
||||
"Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86\n" +
|
||||
"tso4gkJIFiza0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0w\n" +
|
||||
"DQYJKoZIhvcNAQEFBQADggEBAGuZb8ai1NO2j4v3y9TLZvd5s0vh5/TE7n7RX+8U\n" +
|
||||
"y37OL5k7x9nt0mM1TyAKxlCcY+9h6frue8MemZIILSIvMrtzccqNz0V1WKgA+Orf\n" +
|
||||
"uUrabmn+CxHF5gpy6g1Qs2IjVYWA5f7FROn/J+Ad8gJYc1azOWCLQqSyfpNRLSvY\n" +
|
||||
"EriQFEV63XvkJ8JrG62b+2OT2lqT4OO07gSPetppdlSa8NBSKP6Aro9RIX1ZjUZQ\n" +
|
||||
"SpQFCfo02NO0uNRDPUdJx2huycdNb+AXHaO7eXevDLJ+QnqImIzxWiY6zLOdzjjI\n" +
|
||||
"VBMkLHmnP7SjGSQ3XA4ByrQOxfOUTyLyE7NuemhHppuQPxE=\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* subjectAlt=foo.com
|
||||
*/
|
||||
public final static byte[] X509_NO_CNS_FOO = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIESjCCAzKgAwIBAgIJAIz+EYMBU6aYMA0GCSqGSIb3DQEBBQUAMIGiMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxEjAQBgNVBAcTCVZhbmNvdXZlcjEWMBQGA1UE\n" +
|
||||
"ChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9uc19zc2wxHTAbBgNVBAMU\n" +
|
||||
"FGRlbW9faW50ZXJtZWRpYXRlX2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZp\n" +
|
||||
"ZXNAZ21haWwuY29tMB4XDTA2MTIxMTE2MjYxMFoXDTI4MTEwNTE2MjYxMFowgZIx\n" +
|
||||
"CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhNYXJ5bGFuZDEUMBIGA1UEBwwLRm9yZXN0\n" +
|
||||
"IEhpbGwxFzAVBgNVBAoMDmh0dHBjb21wb25lbnRzMRowGAYDVQQLDBF0ZXN0IGNl\n" +
|
||||
"cnRpZmljYXRlczElMCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNv\n" +
|
||||
"bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMhjr5aCPoyp0R1iroWA\n" +
|
||||
"fnEyBMGYWoCidH96yGPFjYLowez5aYKY1IOKTY2BlYho4O84X244QrZTRl8kQbYt\n" +
|
||||
"xnGh4gSCD+Z8gjZ/gMvLUlhqOb+WXPAUHMB39GRyzerA/ZtrlUqf+lKo0uWcocxe\n" +
|
||||
"Rc771KN8cPH3nHZ0rV0Hx4ZAZy6U4xxObe4rtSVY07hNKXAb2odnVqgzcYiDkLV8\n" +
|
||||
"ilvEmoNWMWrp8UBqkTcpEhYhCYp3cTkgJwMSuqv8BqnGd87xQU3FVZI4tbtkB+Kz\n" +
|
||||
"jD9zz8QCDJAfDjZHR03KNQ5mxOgXwxwKw6lGMaiVJTxpTKqym93whYk93l3ocEe5\n" +
|
||||
"5c0CAwEAAaOBkDCBjTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM\n" +
|
||||
"IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxR3vz86tso4gkJIFiza\n" +
|
||||
"0Mteh9gwHwYDVR0jBBgwFoAUe5raj5CZTlLSrNuzA1LKh6YNPg0wEgYDVR0RBAsw\n" +
|
||||
"CYIHZm9vLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAjl78oMjzFdsMy6F1sGg/IkO8\n" +
|
||||
"tF5yUgPgFYrs41yzAca7IQu6G9qtFDJz/7ehh/9HoG+oqCCIHPuIOmS7Sd0wnkyJ\n" +
|
||||
"Y7Y04jVXIb3a6f6AgBkEFP1nOT0z6kjT7vkA5LJ2y3MiDcXuRNMSta5PYVnrX8aZ\n" +
|
||||
"yiqVUNi40peuZ2R8mAUSBvWgD7z2qWhF8YgDb7wWaFjg53I36vWKn90ZEti3wNCw\n" +
|
||||
"qAVqixM+J0qJmQStgAc53i2aTMvAQu3A3snvH/PHTBo+5UL72n9S1kZyNCsVf1Qo\n" +
|
||||
"n8jKTiRriEM+fMFlcgQP284EBFzYHyCXFb9O/hMjK2+6mY9euMB1U1aFFzM/Bg==\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* Intermediate CA for all of these.
|
||||
*/
|
||||
public final static byte[] X509_INTERMEDIATE_CA = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEnDCCA4SgAwIBAgIJAJTNwZ6yNa5cMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS\n" +
|
||||
"BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq\n" +
|
||||
"hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjE0OTMx\n" +
|
||||
"WhcNMDcxMTA1MjE0OTMxWjCBojELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRIw\n" +
|
||||
"EAYDVQQHEwlWYW5jb3V2ZXIxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDASBgNV\n" +
|
||||
"BAsUC2NvbW1vbnNfc3NsMR0wGwYDVQQDFBRkZW1vX2ludGVybWVkaWF0ZV9jYTEl\n" +
|
||||
"MCMGCSqGSIb3DQEJARYWanVsaXVzZGF2aWVzQGdtYWlsLmNvbTCCASIwDQYJKoZI\n" +
|
||||
"hvcNAQEBBQADggEPADCCAQoCggEBAL0S4y3vUO0EM6lwqOEfK8fvrUprIbsikXaG\n" +
|
||||
"XzejcZ+T3l2Dc7t8WtBfRf78i4JypMqJQSijrUicj3H6mOMIReKaXm6ls4hA5d8w\n" +
|
||||
"Lhmgiqsz/kW+gA8SeWGWRN683BD/RbQmzOls6ynBvap9jZlthXWBrSIlPCQoBLXY\n" +
|
||||
"KVaxGzbL4ezaq+XFMKMQSm2uKwVmHHQNbfmZlPsuendBVomb/ked53Ab9IH6dwwN\n" +
|
||||
"qJH9WIrvIzIVEXWlpvQ5MCqozM7u1akU+G8cazr8theGPCaYkzoXnigWua4OjdpV\n" +
|
||||
"9z5ZDknhfBzG1AjapdG07FIirwWWgIyZXqZSD96ikmLtwT29qnsCAwEAAaOB7jCB\n" +
|
||||
"6zAdBgNVHQ4EFgQUe5raj5CZTlLSrNuzA1LKh6YNPg0wgbsGA1UdIwSBszCBsIAU\n" +
|
||||
"rN8eFIvMiRFXXgDqKumS0/W2AhOhgYykgYkwgYYxCzAJBgNVBAYTAkNBMQswCQYD\n" +
|
||||
"VQQIEwJCQzEWMBQGA1UEChMNd3d3LmN1Y2JjLmNvbTEUMBIGA1UECxQLY29tbW9u\n" +
|
||||
"c19zc2wxFTATBgNVBAMUDGRlbW9fcm9vdF9jYTElMCMGCSqGSIb3DQEJARYWanVs\n" +
|
||||
"aXVzZGF2aWVzQGdtYWlsLmNvbYIJAJTNwZ6yNa5bMAwGA1UdEwQFMAMBAf8wDQYJ\n" +
|
||||
"KoZIhvcNAQEFBQADggEBAIB4KMZvHD20pdKajFtMBpL7X4W4soq6EeTtjml3NYa9\n" +
|
||||
"Qc52bsQEGNccKY9afYSBIndaQvFdtmz6HdoN+B8TjYShw2KhyjtKimGLpWYoi1YF\n" +
|
||||
"e4aHdmA/Gp5xk8pZzR18FmooxC9RqBux+NAM2iTFSLgDtGIIj4sg2rbn6Bb6ZlQT\n" +
|
||||
"1rg6VucXCA1629lNfMeNcu7CBNmUKIdaxHR/YJQallE0KfGRiOIWPrPj/VNk0YA6\n" +
|
||||
"XFg0ocjqXJ2/N0N9rWVshMUaXgOh7m4D/5zga5/nuxDU+PoToA6mQ4bV6eCYqZbh\n" +
|
||||
"aa1kQYtR9B4ZiG6pB82qVc2dCqStOH2FAEWos2gAVkQ=\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* Root CA for all of these.
|
||||
*/
|
||||
public final static byte[] X509_ROOT_CA = (
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIEgDCCA2igAwIBAgIJAJTNwZ6yNa5bMA0GCSqGSIb3DQEBBQUAMIGGMQswCQYD\n" +
|
||||
"VQQGEwJDQTELMAkGA1UECBMCQkMxFjAUBgNVBAoTDXd3dy5jdWNiYy5jb20xFDAS\n" +
|
||||
"BgNVBAsUC2NvbW1vbnNfc3NsMRUwEwYDVQQDFAxkZW1vX3Jvb3RfY2ExJTAjBgkq\n" +
|
||||
"hkiG9w0BCQEWFmp1bGl1c2Rhdmllc0BnbWFpbC5jb20wHhcNMDYxMTA1MjEzNjQz\n" +
|
||||
"WhcNMjYxMTA1MjEzNjQzWjCBhjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYw\n" +
|
||||
"FAYDVQQKEw13d3cuY3VjYmMuY29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMG\n" +
|
||||
"A1UEAxQMZGVtb19yb290X2NhMSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNA\n" +
|
||||
"Z21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv+OnocmJ\n" +
|
||||
"79UeO2hlCwK+Cle5uZWnU6uwJl+08z5cvebb5tT64WL9+psDbfgUH/Gm9JsuxKTg\n" +
|
||||
"w1tZO/4duIgnaLNSx4HoqaTjwigd/hR3TsoGEPXTCkz1ikgTCOEDvl+iMid6aOrd\n" +
|
||||
"mViE8HhscxKZ+h5FE7oHZyuT6gFoiaIXhFq+xK2w4ZwDz9L+paiwqywyUJJMnh9U\n" +
|
||||
"jKorY+nua81N0oxpIhHPspCanDU4neMzCzYOZyLR/LqV5xORvHcFY84GWMz5hI25\n" +
|
||||
"JbgaWJsYKuCAvNsnQwVoqKPGa7x1fn7x6oGsXJaCVt8weUwIj2xwg1lxMhrNaisH\n" +
|
||||
"EvKpEAEnGGwWKQIDAQABo4HuMIHrMB0GA1UdDgQWBBSs3x4Ui8yJEVdeAOoq6ZLT\n" +
|
||||
"9bYCEzCBuwYDVR0jBIGzMIGwgBSs3x4Ui8yJEVdeAOoq6ZLT9bYCE6GBjKSBiTCB\n" +
|
||||
"hjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgTAkJDMRYwFAYDVQQKEw13d3cuY3VjYmMu\n" +
|
||||
"Y29tMRQwEgYDVQQLFAtjb21tb25zX3NzbDEVMBMGA1UEAxQMZGVtb19yb290X2Nh\n" +
|
||||
"MSUwIwYJKoZIhvcNAQkBFhZqdWxpdXNkYXZpZXNAZ21haWwuY29tggkAlM3BnrI1\n" +
|
||||
"rlswDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAlPl3/8h1LttR1svC\n" +
|
||||
"S8RXbHpAWIT2BEDhGHUNjSmgDQNkE/itf/FCEXh0tlU4bYdtBSOHzflbnzOyIPId\n" +
|
||||
"VZeSWs33V38xDFy6KoVg1gT8JxkLmE5S1vWkpsHIlpw/U6r7KD0Kx9FYx5AiXjw0\n" +
|
||||
"lzz/zlVNuO2U09KIDwDPVG1mBzQiMiSWj1U1pM4KxINkWQwDy/fvu/I983s8lW5z\n" +
|
||||
"hf2WuFNzQN3fcMK5dpBE9NVIu27oYuGYh2sak34v+7T700W2ooBB71qFXtm9P5rl\n" +
|
||||
"Yp9RCEsg3KEEPNTtCBs8fROeXvLDrP0cmBIqwGYDuRNCxFDTOdjv6YGdA8nLOjaH\n" +
|
||||
"2dDk0g==\n" +
|
||||
"-----END CERTIFICATE-----\n").getBytes();
|
||||
|
||||
/**
|
||||
* Below is the private key for all the server certificates above (but
|
||||
* not the intermediate CA or the root CA). All of those server certs
|
||||
* came from the same private key.
|
||||
*/
|
||||
public final static String RSA_PUBLIC_MODULUS =
|
||||
"00c863af96823e8ca9d11d62ae85807e713204c1985a80a2747f7ac863c5" +
|
||||
"8d82e8c1ecf9698298d4838a4d8d81958868e0ef385f6e3842b653465f24" +
|
||||
"41b62dc671a1e204820fe67c82367f80cbcb52586a39bf965cf0141cc077" +
|
||||
"f46472cdeac0fd9b6b954a9ffa52a8d2e59ca1cc5e45cefbd4a37c70f1f7" +
|
||||
"9c7674ad5d07c78640672e94e31c4e6dee2bb52558d3b84d29701bda8767" +
|
||||
"56a83371888390b57c8a5bc49a8356316ae9f1406a913729121621098a77" +
|
||||
"713920270312baabfc06a9c677cef1414dc5559238b5bb6407e2b38c3f73" +
|
||||
"cfc4020c901f0e3647474dca350e66c4e817c31c0ac3a94631a895253c69" +
|
||||
"4caab29bddf085893dde5de87047b9e5cd";
|
||||
|
||||
public final static String RSA_PUBLIC_EXPONENT = "65537";
|
||||
|
||||
public final static String RSA_PRIVATE_EXPONENT =
|
||||
"577abd3295553d0efd4d38c13b62a6d03fa7b7e40cce4f1d5071877d96c6" +
|
||||
"7a39a63f0f7ab21a89db8acae45587b3ef251309a70f74dc1ac02bde68f3" +
|
||||
"8ed658e54e685ed370a18c054449512ea66a2252ed36e82b565b5159ec83" +
|
||||
"f23df40ae189550a183865b25fd77789e960f0d8cedcd72f32d7a66edb4b" +
|
||||
"a0a2baf3fbeb6c7d75f56ef0af9a7cff1c8c7f297d72eae7982164e50a89" +
|
||||
"d450698cf598d39343201094241d2d180a95882a7111e58f4a5bdbc5c125" +
|
||||
"a967dd6ed9ec614c5853e88e4c71e8b682a7cf89cb1d82b6fe78cc865084" +
|
||||
"c8c5dfbb50c939df2b839c977b0245bfa3615e0592b527b1013d5b675ecb" +
|
||||
"44e6b355c1df581f50997175166eef39";
|
||||
|
||||
public final static String RSA_PRIME1 =
|
||||
"00fe759c4f0ce8b763880215e82767e7a937297668f4e4b1e119c6b22a3c" +
|
||||
"a2c7b06c547d88d0aa45f645d7d3aeadaf7f8bc594deae0978529592977c" +
|
||||
"b1ff890f05033a9e9e15551cad9fbf9c41d12139ccd99c1c3ac7b2197eff" +
|
||||
"350d236bb900c1440953b64956e0a058ef824a2e16894af175177c77dbe1" +
|
||||
"fef7d8b532608d2513";
|
||||
|
||||
public final static String RSA_PRIME2 =
|
||||
"00c99a45878737a4cf73f9896680b75487f1b669b7686a6ba07103856f31" +
|
||||
"db668c2c440c44cdd116f708f631c37a9adf119f5b5cb58ffe3dc62e20af" +
|
||||
"af72693d936dc6bb3c5194996468389c1f094079b81522e94572b4ad7d39" +
|
||||
"529178e9b8ebaeb1f0fdd83b8731c5223f1dea125341d1d64917f6b1a6ae" +
|
||||
"c18d320510d79f859f";
|
||||
|
||||
public final static String RSA_EXPONENT1 =
|
||||
"029febf0d4cd41b7011c2465b4a259bd6118486464c247236f44a169d61e" +
|
||||
"47b9062508f674508d5031003ceabc57e714e600d71b2c75d5443db2da52" +
|
||||
"6bb45a374f0537c5a1aab3150764ce93cf386c84346a6bd01f6732e42075" +
|
||||
"c7a0e9e78a9e73b934e7d871d0f75673820089e129a1604438edcbbeb4e2" +
|
||||
"106467da112ce389";
|
||||
|
||||
public final static String RSA_EXPONENT2 =
|
||||
"00827e76650c946afcd170038d32e1f8386ab00d6be78d830efe382e45d4" +
|
||||
"7ad4bd04e6231ee22e66740efbf52838134932c9f8c460cdccdec58a1424" +
|
||||
"4427859192fd6ab6c58b74e97941b0eaf577f2a11713af5e5952af3ae124" +
|
||||
"9a9a892e98410dfa2628d9af668a43b5302fb7d496c9b2fec69f595292b6" +
|
||||
"e997f079b0f6314eb7";
|
||||
|
||||
public final static String RSA_COEFFICIENT =
|
||||
"00e6b62add350f1a2a8968903ff76c31cf703b0d7326c4a620aef01225b7" +
|
||||
"1640b3f2ec375208c5f7299863f6005b7799b6e529bb1133c8435bf5fdb5" +
|
||||
"a786f6cd8a19ee7094a384e6557c600a38845a0960ddbfd1df18d0af5740" +
|
||||
"001853788f1b5ccbf9affb4c52c9d2efdb8aab0183d86735b32737fb4e79" +
|
||||
"2b8a9c7d91c7d175ae";
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
* ====================================================================
|
||||
*
|
||||
* Copyright 1999-2006 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
public class TestAllSSL extends TestCase {
|
||||
|
||||
public TestAllSSL(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite suite = new TestSuite();
|
||||
suite.addTest(TestHostnameVerifier.suite());
|
||||
suite.addTest(TestSSLSocketFactory.suite());
|
||||
return suite;
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
String[] testCaseName = { TestAllSSL.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* Copyright 1999-2006 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link HostnameVerifier}.
|
||||
*
|
||||
* @author Julius Davies
|
||||
* @since 11-Dec-2006
|
||||
*/
|
||||
public class TestHostnameVerifier extends TestCase
|
||||
implements CertificatesToPlayWith {
|
||||
|
||||
public TestHostnameVerifier(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
String[] testCaseName = { TestHostnameVerifier.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite ts = new TestSuite();
|
||||
ts.addTestSuite(TestHostnameVerifier.class);
|
||||
return ts;
|
||||
}
|
||||
|
||||
public void testVerify() throws Exception {
|
||||
HostnameVerifier DEFAULT = HostnameVerifier.DEFAULT;
|
||||
HostnameVerifier STRICT = HostnameVerifier.STRICT;
|
||||
HostnameVerifier ALLOW_ALL = HostnameVerifier.ALLOW_ALL;
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
InputStream in;
|
||||
X509Certificate x509;
|
||||
in = new ByteArrayInputStream(X509_FOO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
|
||||
DEFAULT.verify("foo.com", x509);
|
||||
STRICT.verify("foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "bar.com", x509);
|
||||
exceptionPlease(STRICT, "bar.com", x509);
|
||||
ALLOW_ALL.verify("foo.com", x509);
|
||||
ALLOW_ALL.verify("a.foo.com", x509);
|
||||
ALLOW_ALL.verify("bar.com", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_HANAKO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
DEFAULT.verify("\u82b1\u5b50.co.jp", x509);
|
||||
STRICT.verify("\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_FOO_BAR);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
DEFAULT.verify("foo.com", x509);
|
||||
STRICT.verify("foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
DEFAULT.verify("bar.com", x509);
|
||||
STRICT.verify("bar.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.bar.com", x509);
|
||||
exceptionPlease(STRICT, "a.bar.com", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_FOO_BAR_HANAKO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
DEFAULT.verify("foo.com", x509);
|
||||
STRICT.verify("foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
DEFAULT.verify("bar.com", x509);
|
||||
STRICT.verify("bar.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.bar.com", x509);
|
||||
exceptionPlease(STRICT, "a.bar.com", x509);
|
||||
|
||||
/*
|
||||
Java isn't extracting international subjectAlts properly. (Or
|
||||
OpenSSL isn't storing them properly).
|
||||
*/
|
||||
// DEFAULT.verify("\u82b1\u5b50.co.jp", x509 );
|
||||
// STRICT.verify("\u82b1\u5b50.co.jp", x509 );
|
||||
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_NO_CNS_FOO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
DEFAULT.verify("foo.com", x509);
|
||||
STRICT.verify("foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_NO_CNS_FOO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
DEFAULT.verify("foo.com", x509);
|
||||
STRICT.verify("foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_THREE_CNS_FOO_BAR_HANAKO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
exceptionPlease(DEFAULT, "foo.com", x509);
|
||||
exceptionPlease(STRICT, "foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.foo.com", x509);
|
||||
exceptionPlease(DEFAULT, "bar.com", x509);
|
||||
exceptionPlease(STRICT, "bar.com", x509);
|
||||
exceptionPlease(DEFAULT, "a.bar.com", x509);
|
||||
exceptionPlease(STRICT, "a.bar.com", x509);
|
||||
DEFAULT.verify("\u82b1\u5b50.co.jp", x509);
|
||||
STRICT.verify("\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(DEFAULT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(STRICT, "a.\u82b1\u5b50.co.jp", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_WILD_FOO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
exceptionPlease(DEFAULT, "foo.com", x509);
|
||||
exceptionPlease(STRICT, "foo.com", x509);
|
||||
DEFAULT.verify("www.foo.com", x509);
|
||||
STRICT.verify("www.foo.com", x509);
|
||||
DEFAULT.verify("\u82b1\u5b50.foo.com", x509);
|
||||
STRICT.verify("\u82b1\u5b50.foo.com", x509);
|
||||
DEFAULT.verify("a.b.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.b.foo.com", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_WILD_CO_JP);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
// Silly test because no-one would ever be able to lookup an IP address
|
||||
// using "*.co.jp".
|
||||
DEFAULT.verify("*.co.jp", x509);
|
||||
STRICT.verify("*.co.jp", x509);
|
||||
exceptionPlease(DEFAULT, "foo.co.jp", x509);
|
||||
exceptionPlease(STRICT, "foo.co.jp", x509);
|
||||
exceptionPlease(DEFAULT, "\u82b1\u5b50.co.jp", x509);
|
||||
exceptionPlease(STRICT, "\u82b1\u5b50.co.jp", x509);
|
||||
|
||||
in = new ByteArrayInputStream(X509_WILD_FOO_BAR_HANAKO);
|
||||
x509 = (X509Certificate) cf.generateCertificate(in);
|
||||
// try the foo.com variations
|
||||
exceptionPlease(DEFAULT, "foo.com", x509);
|
||||
exceptionPlease(STRICT, "foo.com", x509);
|
||||
DEFAULT.verify("www.foo.com", x509);
|
||||
STRICT.verify("www.foo.com", x509);
|
||||
DEFAULT.verify("\u82b1\u5b50.foo.com", x509);
|
||||
STRICT.verify("\u82b1\u5b50.foo.com", x509);
|
||||
DEFAULT.verify("a.b.foo.com", x509);
|
||||
exceptionPlease(STRICT, "a.b.foo.com", x509);
|
||||
// try the bar.com variations
|
||||
exceptionPlease(DEFAULT, "bar.com", x509);
|
||||
exceptionPlease(STRICT, "bar.com", x509);
|
||||
DEFAULT.verify("www.bar.com", x509);
|
||||
STRICT.verify("www.bar.com", x509);
|
||||
DEFAULT.verify("\u82b1\u5b50.bar.com", x509);
|
||||
STRICT.verify("\u82b1\u5b50.bar.com", x509);
|
||||
DEFAULT.verify("a.b.bar.com", x509);
|
||||
exceptionPlease(STRICT, "a.b.bar.com", x509);
|
||||
// try the \u82b1\u5b50.co.jp variations
|
||||
/*
|
||||
Java isn't extracting international subjectAlts properly. (Or
|
||||
OpenSSL isn't storing them properly).
|
||||
*/
|
||||
//exceptionPlease( DEFAULT, "\u82b1\u5b50.co.jp", x509 );
|
||||
//exceptionPlease( STRICT, "\u82b1\u5b50.co.jp", x509 );
|
||||
//DEFAULT.verify("www.\u82b1\u5b50.co.jp", x509 );
|
||||
//STRICT.verify("www.\u82b1\u5b50.co.jp", x509 );
|
||||
//DEFAULT.verify("\u82b1\u5b50.\u82b1\u5b50.co.jp", x509 );
|
||||
//STRICT.verify("\u82b1\u5b50.\u82b1\u5b50.co.jp", x509 );
|
||||
//DEFAULT.verify("a.b.\u82b1\u5b50.co.jp", x509 );
|
||||
//exceptionPlease(STRICT,"a.b.\u82b1\u5b50.co.jp", x509 );
|
||||
}
|
||||
|
||||
private void exceptionPlease(HostnameVerifier hv, String host,
|
||||
X509Certificate x509) {
|
||||
try {
|
||||
hv.verify(host, x509);
|
||||
fail("HostnameVerifier shouldn't allow [" + host + "]");
|
||||
}
|
||||
catch(SSLException e) {
|
||||
// whew! we're okay!
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* ====================================================================
|
||||
*
|
||||
* Copyright 1999-2006 The Apache Software Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Software Foundation. For more
|
||||
* information on the Apache Software Foundation, please see
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.http.conn.ssl;
|
||||
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import org.apache.http.impl.DefaultHttpParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
import javax.net.ssl.SSLServerSocketFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.security.spec.RSAPrivateCrtKeySpec;
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SSLSocketFactory}.
|
||||
*
|
||||
* @author Julius Davies
|
||||
* @since 8-Dec-2006
|
||||
*/
|
||||
public class TestSSLSocketFactory extends TestCase
|
||||
implements CertificatesToPlayWith {
|
||||
|
||||
public TestSSLSocketFactory(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
String[] testCaseName = { TestSSLSocketFactory.class.getName() };
|
||||
junit.textui.TestRunner.main(testCaseName);
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
TestSuite ts = new TestSuite();
|
||||
ts.addTestSuite(TestSSLSocketFactory.class);
|
||||
return ts;
|
||||
}
|
||||
|
||||
public void testConstructor() {}
|
||||
|
||||
public void testCreateKeyManagers() {}
|
||||
|
||||
public void testCreateTrustManagers() {}
|
||||
|
||||
public void testHashCode() {}
|
||||
|
||||
public void testEquals() {}
|
||||
|
||||
public void testToString() {}
|
||||
|
||||
public void testCreateSocket() throws Exception {
|
||||
HttpParams params = new DefaultHttpParams();
|
||||
String password = "changeit";
|
||||
char[] pwd = password.toCharArray();
|
||||
|
||||
RSAPrivateCrtKeySpec k;
|
||||
k = new RSAPrivateCrtKeySpec(new BigInteger(RSA_PUBLIC_MODULUS, 16),
|
||||
new BigInteger(RSA_PUBLIC_EXPONENT, 10),
|
||||
new BigInteger(RSA_PRIVATE_EXPONENT, 16),
|
||||
new BigInteger(RSA_PRIME1, 16),
|
||||
new BigInteger(RSA_PRIME2, 16),
|
||||
new BigInteger(RSA_EXPONENT1, 16),
|
||||
new BigInteger(RSA_EXPONENT2, 16),
|
||||
new BigInteger(RSA_COEFFICIENT, 16));
|
||||
|
||||
PrivateKey pk = KeyFactory.getInstance("RSA").generatePrivate(k);
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(null, null);
|
||||
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
InputStream in1, in2, in3;
|
||||
in1 = new ByteArrayInputStream(X509_FOO);
|
||||
in2 = new ByteArrayInputStream(X509_INTERMEDIATE_CA);
|
||||
in3 = new ByteArrayInputStream(X509_ROOT_CA);
|
||||
X509Certificate[] chain = new X509Certificate[3];
|
||||
chain[0] = (X509Certificate) cf.generateCertificate(in1);
|
||||
chain[1] = (X509Certificate) cf.generateCertificate(in2);
|
||||
chain[2] = (X509Certificate) cf.generateCertificate(in3);
|
||||
|
||||
ks.setKeyEntry("RSA_KEY", pk, pwd, chain);
|
||||
ks.setCertificateEntry("CERT", chain[2]); // Let's trust ourselves. :-)
|
||||
|
||||
File tempFile = File.createTempFile("junit", "jks");
|
||||
try {
|
||||
String path = tempFile.getCanonicalPath();
|
||||
tempFile.deleteOnExit();
|
||||
FileOutputStream fOut = new FileOutputStream(tempFile);
|
||||
ks.store(fOut, pwd);
|
||||
fOut.close();
|
||||
|
||||
System.setProperty("javax.net.ssl.keyStore", path);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", password);
|
||||
System.setProperty("javax.net.ssl.trustStore", path);
|
||||
System.setProperty("javax.net.ssl.trustStorePassword", password);
|
||||
|
||||
ServerSocketFactory server = SSLServerSocketFactory.getDefault();
|
||||
// Let the operating system just choose an available port:
|
||||
ServerSocket serverSocket = server.createServerSocket(0);
|
||||
serverSocket.setSoTimeout(30000);
|
||||
int port = serverSocket.getLocalPort();
|
||||
// System.out.println("\nlistening on port: " + port);
|
||||
|
||||
SSLSocketFactory ssf = new SSLSocketFactory();
|
||||
ssf.setHostnameVerifier(HostnameVerifier.ALLOW_ALL);
|
||||
|
||||
// Test 1 - createSocket()
|
||||
IOException[] e = new IOException[1];
|
||||
boolean[] success = new boolean[1];
|
||||
listen(serverSocket, e, success);
|
||||
Socket s = ssf.createSocket("localhost", port, null, 0, params);
|
||||
exerciseSocket(s, e, success);
|
||||
|
||||
// Test 2 - createSocket( Socket ), where we upgrade a plain socket
|
||||
// to SSL.
|
||||
success[0] = false;
|
||||
listen(serverSocket, e, success);
|
||||
s = new Socket("localhost", port);
|
||||
s = ssf.createSocket(s, "localhost", port, true);
|
||||
exerciseSocket(s, e, success);
|
||||
}
|
||||
finally {
|
||||
tempFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void listen(final ServerSocket ss,
|
||||
final IOException[] e,
|
||||
final boolean[] success) {
|
||||
Runnable r = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Socket s = ss.accept();
|
||||
InputStream in = s.getInputStream();
|
||||
OutputStream out = s.getOutputStream();
|
||||
out.write("server says hello\n".getBytes());
|
||||
byte[] buf = new byte[4096];
|
||||
in.read(buf);
|
||||
out.close();
|
||||
in.close();
|
||||
s.close();
|
||||
} catch(IOException ioe) {
|
||||
e[0] = ioe;
|
||||
} finally {
|
||||
success[0] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
new Thread(r).start();
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
private static void exerciseSocket(Socket s, IOException[] e,
|
||||
boolean[] success)
|
||||
throws IOException {
|
||||
InputStream in = s.getInputStream();
|
||||
OutputStream out = s.getOutputStream();
|
||||
out.write(42);
|
||||
byte[] buf = new byte[4096];
|
||||
in.read(buf);
|
||||
out.close();
|
||||
in.close();
|
||||
s.close();
|
||||
// String response = new String( buf, 0, c );
|
||||
while(!success[0]) {
|
||||
Thread.yield();
|
||||
}
|
||||
if(e[0] != null) {
|
||||
throw e[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@ package org.apache.httpclient;
|
|||
|
||||
import org.apache.http.cookie.TestAllCookie;
|
||||
import org.apache.http.cookie.impl.TestAllCookieImpl;
|
||||
import org.apache.http.conn.ssl.TestAllSSL;
|
||||
import org.apache.httpclient.impl.TestAllHttpClientImpl;
|
||||
|
||||
import junit.framework.*;
|
||||
|
@ -45,6 +46,7 @@ public class TestAll extends TestCase {
|
|||
suite.addTest(TestAllCookie.suite());
|
||||
suite.addTest(TestAllCookieImpl.suite());
|
||||
suite.addTest(TestAllHttpClientImpl.suite());
|
||||
suite.addTest(TestAllSSL.suite());
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue