Andrew: X509ExtendedTrustManager
--- old/src/share/classes/sun/security/ssl/ClientHandshaker.java 2009-01-20 04:37:00.000000000 -0800
+++ new/src/share/classes/sun/security/ssl/ClientHandshaker.java 2009-01-20 04:36:59.000000000 -0800
@@ -48,8 +48,6 @@
import sun.security.jgss.krb5.Krb5Util;
import sun.security.jgss.GSSUtil;
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.*;
@@ -1030,13 +1028,27 @@
String identificator = getHostnameVerificationSE();
if (tm instanceof X509ExtendedTrustManager) {
- ((X509ExtendedTrustManager)tm).checkServerTrusted(
- (peerCerts != null ?
- peerCerts.clone() :
- null),
+ if (conn != null) {
+ ((X509ExtendedTrustManager)tm).checkServerTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
+ keyExchangeString,
+ conn,
+ identificator);
+ } else {
+ ((X509ExtendedTrustManager)tm).checkServerTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
keyExchangeString,
- getHostSE(),
+ engine,
identificator);
+ }
+ } else if (tm instanceof
+ com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager) {
+ ((com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager)tm).
+ checkServerTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
+ keyExchangeString,
+ getHostSE(),
+ identificator);
} else {
if (identificator != null) {
throw new RuntimeException(
--- old/src/share/classes/sun/security/ssl/SSLContextImpl.java 2009-01-20 04:37:02.000000000 -0800
+++ new/src/share/classes/sun/security/ssl/SSLContextImpl.java 2009-01-20 04:37:01.000000000 -0800
@@ -111,7 +111,9 @@
// We only use the first instance of X509TrustManager passed to us.
for (int i = 0; tm != null && i < tm.length; i++) {
if (tm[i] instanceof X509TrustManager) {
- if (SunJSSE.isFIPS() && !(tm[i] instanceof X509TrustManagerImpl)) {
+ if (SunJSSE.isFIPS() &&
+ !(tm[i] instanceof X509TrustManagerImpl ||
+ tm[i] instanceof X509ExtendedTrustManagerImpl)) {
throw new KeyManagementException
("FIPS mode: only SunJSSE TrustManagers may be used");
}
--- old/src/share/classes/sun/security/ssl/ServerHandshaker.java 2009-01-20 04:37:03.000000000 -0800
+++ new/src/share/classes/sun/security/ssl/ServerHandshaker.java 2009-01-20 04:37:02.000000000 -0800
@@ -45,8 +45,6 @@
import sun.security.jgss.krb5.Krb5Util;
import sun.security.jgss.GSSUtil;
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
import sun.security.ssl.HandshakeMessage.*;
import sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.*;
@@ -1248,13 +1246,27 @@
String identificator = getHostnameVerificationSE();
if (tm instanceof X509ExtendedTrustManager) {
- ((X509ExtendedTrustManager)tm).checkClientTrusted(
- (peerCerts != null ?
- peerCerts.clone() :
- null),
+ if (conn != null) {
+ ((X509ExtendedTrustManager)tm).checkClientTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
+ authType,
+ conn,
+ identificator);
+ } else {
+ ((X509ExtendedTrustManager)tm).checkClientTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
authType,
- getHostSE(),
+ engine,
identificator);
+ }
+ } else if (tm instanceof
+ com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager) {
+ ((com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager)tm).
+ checkClientTrusted(
+ (peerCerts != null ? peerCerts.clone() : null),
+ authType,
+ getHostSE(),
+ identificator);
} else {
if (identificator != null) {
throw new RuntimeException(
--- old/src/share/classes/sun/security/ssl/SunJSSE.java 2009-01-20 04:37:05.000000000 -0800
+++ new/src/share/classes/sun/security/ssl/SunJSSE.java 2009-01-20 04:37:04.000000000 -0800
@@ -198,9 +198,16 @@
"sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
put("TrustManagerFactory.PKIX",
"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory");
+ put("TrustManagerFactory.ExtendedSunX509",
+ "sun.security.ssl.TrustManagerFactoryImpl$ExtendedSimpleFactory");
+ put("TrustManagerFactory.ExtendedPKIX",
+ "sun.security.ssl.TrustManagerFactoryImpl$ExtendedPKIXFactory");
put("Alg.Alias.TrustManagerFactory.SunPKIX", "PKIX");
put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
put("Alg.Alias.TrustManagerFactory.X.509", "PKIX");
+ put("Alg.Alias.TrustManagerFactory.SunX509.Extended",
+ "ExtendedSunX509");
+ put("Alg.Alias.TrustManagerFactory.PKIX.Extended", "ExtendedPKIX");
if (isfips == false) {
put("SSLContext.SSL",
"sun.security.ssl.SSLContextImpl");
--- old/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java 2009-01-20 04:37:06.000000000 -0800
+++ new/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java 2009-01-20 04:37:05.000000000 -0800
@@ -245,7 +245,7 @@
("SunX509 TrustManagerFactory does not use "
+ "ManagerFactoryParameters");
}
- }
+ }
public static final class PKIXFactory extends TrustManagerFactoryImpl {
X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
@@ -267,4 +267,43 @@
return new X509TrustManagerImpl(Validator.TYPE_PKIX, pkixParams);
}
}
+
+ public static final class ExtendedSimpleFactory
+ extends TrustManagerFactoryImpl {
+ X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
+ return new X509ExtendedTrustManagerImpl(Validator.TYPE_SIMPLE, ks);
+ }
+
+ X509TrustManager getInstance(ManagerFactoryParameters spec)
+ throws InvalidAlgorithmParameterException {
+ throw new InvalidAlgorithmParameterException
+ ("SunX509 TrustManagerFactory does not use "
+ + "ManagerFactoryParameters");
+ }
+ }
+
+ public static final class ExtendedPKIXFactory
+ extends TrustManagerFactoryImpl {
+ X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
+ return new X509ExtendedTrustManagerImpl(Validator.TYPE_PKIX, ks);
+ }
+
+ X509TrustManager getInstance(ManagerFactoryParameters spec)
+ throws InvalidAlgorithmParameterException {
+ if (spec instanceof CertPathTrustManagerParameters == false) {
+ throw new InvalidAlgorithmParameterException
+ ("Parameters must be CertPathTrustManagerParameters");
+ }
+ CertPathParameters params =
+ ((CertPathTrustManagerParameters)spec).getParameters();
+ if (params instanceof PKIXBuilderParameters == false) {
+ throw new InvalidAlgorithmParameterException
+ ("Encapsulated parameters must be PKIXBuilderParameters");
+ }
+ PKIXBuilderParameters pkixParams = (PKIXBuilderParameters)params;
+ return new X509ExtendedTrustManagerImpl(Validator.TYPE_PKIX,
+ pkixParams);
+ }
+ }
}
+
--- /dev/null 2008-08-03 09:11:18.000000000 -0700
+++ new/src/share/classes/javax/net/ssl/X509ExtendedTrustManager.java 2009-01-20 04:37:07.000000000 -0800
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package javax.net.ssl;
+
+import java.net.Socket;
+import javax.net.ssl.X509TrustManager;
+
+import java.security.cert.X509Certificate;
+import java.security.cert.CertificateException;
+
+/**
+ * Instance of this class is an extension of <code>X509TrustManager</code>.
+ * <p>
+ * It takes the responsiblity of checking the peer identity with its
+ * principal declared in the cerificate.
+ * <p>
+ * The class provides an alternative to <code>HostnameVerifer</code>.
+ * If application customizes its <code>HostnameVerifer</code> for
+ * <code>HttpsURLConnection</code>, the peer identity will be checked
+ * by the customized <code>HostnameVerifer</code>; otherwise, it will
+ * be checked by the extended trust manager.
+ * <p>
+ * RFC2830 defines the server identification specification for "LDAP"
+ * algorithm. RFC2818 defines both the server identification and the
+ * client identification specification for "HTTPS" algorithm.
+ *
+ * @see X509TrustManager
+ * @see HostnameVerifier
+ *
+ * @since 1.7
+ * @author Xuelei Fan
+ */
+public abstract class X509ExtendedTrustManager implements X509TrustManager {
+ /**
+ * Constructor used by subclasses only.
+ */
+ protected X509ExtendedTrustManager() {
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for client SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is determined by the actual certificate
+ * used. For instance, if RSAPublicKey is used, the authType
+ * should be "RSA". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the client
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>socket</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>socket</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the authentication type based on the client certificate
+ * @param socket the socket to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public abstract void checkClientTrusted(X509Certificate[] chain,
+ String authType, Socket socket, String algorithm)
+ throws CertificateException;
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for server SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is the key exchange algorithm portion
+ * of the cipher suites represented as a String, such as "RSA",
+ * "DHE_DSS". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the server
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>socket</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>socket</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the key exchange algorithm used
+ * @param socket the socket to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public abstract void checkServerTrusted(X509Certificate[] chain,
+ String authType, Socket socket, String algorithm)
+ throws CertificateException;
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for client SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is determined by the actual certificate
+ * used. For instance, if RSAPublicKey is used, the authType
+ * should be "RSA". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the client
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>engine</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>engine</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the authentication type based on the client certificate
+ * @param engine the engine to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public abstract void checkClientTrusted(X509Certificate[] chain,
+ String authType, SSLEngine engine, String algorithm)
+ throws CertificateException;
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for server SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is the key exchange algorithm portion
+ * of the cipher suites represented as a String, such as "RSA",
+ * "DHE_DSS". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the server
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>engine</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>engine</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the key exchange algorithm used
+ * @param engine the engine to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public abstract void checkServerTrusted(X509Certificate[] chain,
+ String authType, SSLEngine engine, String algorithm)
+ throws CertificateException;
+
+}
--- /dev/null 2008-08-03 09:11:18.000000000 -0700
+++ new/src/share/classes/sun/security/ssl/X509ExtendedTrustManagerImpl.java 2009-01-20 04:37:08.000000000 -0800
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ssl;
+
+import java.net.Socket;
+
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.KeyStoreException;
+import java.security.cert.CertificateException;
+
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.X509ExtendedTrustManager;
+
+/**
+ * This class implements the SunJSSE X509ExtendedTrustManager using the
+ * internal validator API in J2SE core. The logic in this class is minimal.<p>
+ *
+ * This class supports both the Simple validation algorithm from previous
+ * JSSE versions and PKIX validation.
+ *
+ * @author Xuelei Fan
+ */
+final class X509ExtendedTrustManagerImpl extends X509ExtendedTrustManager
+ implements X509TrustManager {
+
+ X509TrustManagerImpl trustManager;
+
+ X509ExtendedTrustManagerImpl(String validatorType, KeyStore ks)
+ throws KeyStoreException {
+ trustManager = new X509TrustManagerImpl(validatorType, ks);
+ }
+
+ X509ExtendedTrustManagerImpl(String validatorType,
+ PKIXBuilderParameters params) {
+ trustManager = new X509TrustManagerImpl(validatorType, params);
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, build a certificate path to a trusted root and return if
+ * it can be validated and is trusted for client SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is determined by the actual certificate
+ * used. For instance, if RSAPublicKey is used, the authType
+ * should be "RSA". Checking is case-sensitive.
+ *
+ * @param chain certificates which establish an identity for the client.
+ * Chains of arbitrary length are supported, and certificates
+ * marked internally as trusted will short-circuit signature checks.
+ * @param authType the authentication type based on the client certificate
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkClientTrusted(X509Certificate chain[], String authType)
+ throws CertificateException {
+ trustManager.checkClientTrusted(chain, authType);
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, build a certificate path to a trusted root and return if
+ * it can be validated and is trusted for server SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is the key exchange algorithm portion
+ * of the cipher suites represented as a String, such as "RSA",
+ * "DHE_DSS". Note: for some exportable cipher suites, the key
+ * exchange algorithm is determined at run time during the
+ * handshake. For instance, for TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ * the authType should be RSA_EXPORT when an ephemeral RSA key is
+ * used for the key exchange, and RSA when the key from the server
+ * certificate is used. Checking is case-sensitive.
+ *
+ * @param chain certificates which establish an identity for the server.
+ * Chains of arbitrary length are supported, and certificates
+ * marked internally as trusted will short-circuit signature checks.
+ * @param authType the key exchange algorithm used
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkServerTrusted(X509Certificate chain[], String authType)
+ throws CertificateException {
+ trustManager.checkServerTrusted(chain, authType);
+ }
+
+ /**
+ * Return an array of certificate authority certificates
+ * which are trusted for authenticating peers.
+ *
+ * @return a non-null (possibly empty) array of acceptable
+ * CA issuer certificates.
+ */
+ public X509Certificate[] getAcceptedIssuers() {
+ return trustManager.getAcceptedIssuers();
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for client SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is determined by the actual certificate
+ * used. For instance, if RSAPublicKey is used, the authType
+ * should be "RSA". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the client
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>socket</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>socket</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the authentication type based on the client certificate
+ * @param socket the socket to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkClientTrusted(X509Certificate[] chain, String authType,
+ Socket socket, String algorithm) throws CertificateException {
+ if (socket != null && socket.isConnected()) {
+ String hostname = null;
+ if (socket instanceof SSLSocketImpl) {
+ hostname = ((SSLSocketImpl)socket).getHost();
+ } else { // "can't happen"
+ hostname = socket.getInetAddress().getHostName();
+ }
+
+ trustManager.checkClientTrusted(chain, authType,
+ hostname, algorithm);
+ } else {
+ trustManager.checkClientTrusted(chain, authType);
+ }
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for server SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is the key exchange algorithm portion
+ * of the cipher suites represented as a String, such as "RSA",
+ * "DHE_DSS". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the server
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>socket</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>socket</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the key exchange algorithm used
+ * @param socket the socket to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkServerTrusted(X509Certificate[] chain, String authType,
+ Socket socket, String algorithm) throws CertificateException {
+ if (socket != null && socket.isConnected()) {
+ String hostname = null;
+ if (socket instanceof SSLSocketImpl) {
+ hostname = ((SSLSocketImpl)socket).getHost();
+ } else { // "can't happen"
+ hostname = socket.getInetAddress().getHostName();
+ }
+
+ trustManager.checkServerTrusted(chain, authType,
+ hostname, algorithm);
+ } else {
+ trustManager.checkServerTrusted(chain, authType);
+ }
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for client SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is determined by the actual certificate
+ * used. For instance, if RSAPublicKey is used, the authType
+ * should be "RSA". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the client
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>engine</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>engine</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the authentication type based on the client certificate
+ * @param engine the engine to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkClientTrusted(X509Certificate[] chain, String authType,
+ SSLEngine engine, String algorithm) throws CertificateException {
+ if (engine != null && engine.getPeerHost() != null) {
+ trustManager.checkClientTrusted(chain, authType,
+ engine.getPeerHost(), algorithm);
+ } else {
+ trustManager.checkClientTrusted(chain, authType);
+ }
+ }
+
+ /**
+ * Given the partial or complete certificate chain provided by the
+ * peer, check its identity and build a certificate path to a trusted
+ * root, return if it can be validated and is trusted for server SSL
+ * authentication based on the authentication type.
+ * <p>
+ * The authentication type is the key exchange algorithm portion
+ * of the cipher suites represented as a String, such as "RSA",
+ * "DHE_DSS". Checking is case-sensitive.
+ * <p>
+ * The <code>algorithm</code> parameter specifies the server
+ * identification protocol to use. If the <code>algorithm</code> and
+ * the <code>engine</code> parameters are available, in order to prevent
+ * masquerade attacks, the address that the <code>engine</code>
+ * connected to should be checked against the peer's identity presented
+ * in the X509 certificate.
+ *
+ * @param chain the peer certificate chain
+ * @param authType the key exchange algorithm used
+ * @param engine the engine to be used for this connection. This parameter
+ * can be null, which indicates that implementations will not check
+ * the peer identity.
+ * @param algorithm the identification algorithm
+ * @throws IllegalArgumentException if null or zero-length chain
+ * is passed in for the chain parameter or if null or zero-length
+ * string is passed in for the authType parameter
+ * @throws CertificateException if the certificate chain is not trusted
+ * by this TrustManager.
+ */
+ public void checkServerTrusted(X509Certificate[] chain, String authType,
+ SSLEngine engine, String algorithm) throws CertificateException {
+ if (engine != null && engine.getPeerHost() != null) {
+ trustManager.checkServerTrusted(chain, authType,
+ engine.getPeerHost(), algorithm);
+ } else {
+ trustManager.checkServerTrusted(chain, authType);
+ }
+ }
+
+}
+
--- /dev/null 2008-08-03 09:11:18.000000000 -0700
+++ new/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/PKIXExtendedTM.java 2009-01-20 04:37:09.000000000 -0800
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6586258
+ * @summary X509ExtendedTrustManager is in the wrong namespace
+ * @author Xuelei Fan
+ *
+ * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager.
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.security.*;
+
+public class PKIXExtendedTM {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../../../../etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+ private final static char[] cpasswd = "passphrase".toCharArray();
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ getContext(true).getServerSocketFactory();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+ sslSocket.setNeedClientAuth(true);
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+
+ sslSocket.close();
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLSocketFactory sslsf = getContext(false).getSocketFactory();
+ SSLSocket sslSocket = (SSLSocket)
+ sslsf.createSocket("localhost", serverPort);
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ sslSocket.close();
+ }
+
+ private SSLContext getContext(boolean server) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new FileInputStream(keyFilename), cpasswd);
+ kmf.init(ks, cpasswd);
+
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance("PKIX.Extended");
+ KeyStore ts = KeyStore.getInstance("JKS");
+ ts.load(new FileInputStream(trustFilename), cpasswd);
+ tmf.init(ts);
+
+ TrustManager tms[] = tmf.getTrustManagers();
+ if (tms == null || tms.length == 0) {
+ throw new Exception("unexpected trust manager implementation");
+ } else {
+ if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+ throw new Exception("unexpected trust manager implementation: "
+ + tms[0].getClass().getCanonicalName());
+ }
+ }
+
+ // only use the first TM
+ tms = new TrustManager[] {tms[0]};
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kmf.getKeyManagers(), tms, null);
+
+ return ctx;
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Start the tests.
+ */
+ new PKIXExtendedTM();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ PKIXExtendedTM() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null)
+ throw serverException;
+ if (clientException != null)
+ throw clientException;
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+}
--- /dev/null 2008-08-03 09:11:18.000000000 -0700
+++ new/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/SunX509ExtendedTM.java 2009-01-20 04:37:10.000000000 -0800
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6586258
+ * @summary X509ExtendedTrustManager is in the wrong namespace
+ * @author Xuelei Fan
+ *
+ * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager.
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.security.*;
+
+public class SunX509ExtendedTM {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../../../../etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+ private final static char[] cpasswd = "passphrase".toCharArray();
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ getContext(true).getServerSocketFactory();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+ sslSocket.setNeedClientAuth(true);
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+
+ sslSocket.close();
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLSocketFactory sslsf = getContext(false).getSocketFactory();
+ SSLSocket sslSocket = (SSLSocket)
+ sslsf.createSocket("localhost", serverPort);
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ sslSocket.close();
+ }
+
+ private SSLContext getContext(boolean server) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new FileInputStream(keyFilename), cpasswd);
+ kmf.init(ks, cpasswd);
+
+ TrustManagerFactory tmf =
+ TrustManagerFactory.getInstance("SunX509.Extended");
+ KeyStore ts = KeyStore.getInstance("JKS");
+ ts.load(new FileInputStream(trustFilename), cpasswd);
+ tmf.init(ts);
+
+ TrustManager tms[] = tmf.getTrustManagers();
+ if (tms == null || tms.length == 0) {
+ throw new Exception("unexpected trust manager implementation");
+ } else {
+ if (!(tms[0] instanceof X509ExtendedTrustManager)) {
+ throw new Exception("unexpected trust manager implementation: "
+ + tms[0].getClass().getCanonicalName());
+ }
+ }
+
+ // only use the first TM
+ tms = new TrustManager[] {tms[0]};
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kmf.getKeyManagers(), tms, null);
+
+ return ctx;
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Start the tests.
+ */
+ new SunX509ExtendedTM();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ SunX509ExtendedTM() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null)
+ throw serverException;
+ if (clientException != null)
+ throw clientException;
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+}
--- /dev/null 2008-08-03 09:11:18.000000000 -0700
+++ new/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/X509TrustManagerImpl/X509ExtendedTMEnabled.java 2009-01-20 04:37:11.000000000 -0800
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6586258
+ * @summary X509ExtendedTrustManager is in the wrong namespace
+ * @author Xuelei Fan
+ *
+ * Ensure that the SunJSSE provider enables the X509ExtendedTrustManager.
+ */
+
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.*;
+import java.security.*;
+
+public class X509ExtendedTMEnabled {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "../../../../../../../etc";
+ static String keyStoreFile = "keystore";
+ static String trustStoreFile = "truststore";
+ static String passwd = "passphrase";
+ private final static char[] cpasswd = "passphrase".toCharArray();
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ getContext(true).getServerSocketFactory();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+ sslSocket.setNeedClientAuth(true);
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write(85);
+ sslOS.flush();
+
+ sslSocket.close();
+
+ if (!serverTM.wasServerChecked() && serverTM.wasClientChecked()) {
+ System.out.println("SERVER TEST PASSED!");
+ } else {
+ throw new Exception("SERVER TEST FAILED! " +
+ !serverTM.wasServerChecked() + " " +
+ serverTM.wasClientChecked());
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLSocketFactory sslsf = getContext(false).getSocketFactory();
+ SSLSocket sslSocket = (SSLSocket)
+ sslsf.createSocket("localhost", serverPort);
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write(280);
+ sslOS.flush();
+ sslIS.read();
+
+ sslSocket.close();
+
+ if (clientTM.wasServerChecked() && !clientTM.wasClientChecked()) {
+ System.out.println("CLIENT TEST PASSED!");
+ } else {
+ throw new Exception("CLIENT TEST FAILED! " +
+ clientTM.wasServerChecked() + " " +
+ !clientTM.wasClientChecked());
+ }
+ }
+
+ MyExtendedX509TM serverTM;
+ MyExtendedX509TM clientTM;
+
+ private SSLContext getContext(boolean server) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new FileInputStream(keyFilename), cpasswd);
+ kmf.init(ks, cpasswd);
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ KeyStore ts = KeyStore.getInstance("JKS");
+ ts.load(new FileInputStream(trustFilename), cpasswd);
+ tmf.init(ts);
+
+ TrustManager tms[] = tmf.getTrustManagers();
+ if (tms == null || tms.length == 0) {
+ throw new Exception("unexpected trust manager implementation");
+ } else {
+ if (!(tms[0] instanceof X509TrustManager)) {
+ throw new Exception("unexpected trust manager implementation: "
+ + tms[0].getClass().getCanonicalName());
+ }
+ }
+
+ if (server) {
+ serverTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+ tms = new TrustManager[] {serverTM};
+ } else {
+ clientTM = new MyExtendedX509TM((X509TrustManager)tms[0]);
+
+ tms = new TrustManager[] {clientTM};
+ }
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kmf.getKeyManagers(), tms, null);
+
+ return ctx;
+ }
+
+ static class MyExtendedX509TM extends X509ExtendedTrustManager
+ implements X509TrustManager {
+
+ X509TrustManager tm;
+
+ boolean clientChecked;
+ boolean serverChecked;
+
+ MyExtendedX509TM(X509TrustManager tm) {
+ clientChecked = false;
+ serverChecked = false;
+
+ this.tm = tm;
+ }
+
+ public boolean wasClientChecked() {
+ return clientChecked;
+ }
+
+ public boolean wasServerChecked() {
+ return serverChecked;
+ }
+
+
+ public void checkClientTrusted(X509Certificate chain[], String authType)
+ throws CertificateException {
+ tm.checkClientTrusted(chain, authType);
+ }
+
+ public void checkServerTrusted(X509Certificate chain[], String authType)
+ throws CertificateException {
+ tm.checkServerTrusted(chain, authType);
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return tm.getAcceptedIssuers();
+ }
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType,
+ Socket socket, String algorithm) throws CertificateException {
+ clientChecked = true;
+ tm.checkClientTrusted(chain, authType);
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType,
+ Socket socket, String algorithm) throws CertificateException {
+ serverChecked = true;
+ tm.checkServerTrusted(chain, authType);
+ }
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType,
+ SSLEngine engine, String algorithm) throws CertificateException {
+ clientChecked = true;
+ tm.checkClientTrusted(chain, authType);
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType,
+ SSLEngine engine, String algorithm) throws CertificateException {
+ serverChecked = true;
+ tm.checkServerTrusted(chain, authType);
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Start the tests.
+ */
+ new X509ExtendedTMEnabled();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ X509ExtendedTMEnabled() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null)
+ throw serverException;
+ if (clientException != null)
+ throw clientException;
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+}