Merge
authorwetmore
Mon, 16 Jun 2008 10:46:22 -0700
changeset 711 b22e3837ba56
parent 702 3bd5e70b2fe9 (current diff)
parent 710 57367409c4a5 (diff)
child 712 077c2f7a8d79
child 784 b42ef9406aae
child 791 dd30869a7046
Merge
--- a/jdk/src/share/classes/java/net/CookieHandler.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/java/net/CookieHandler.java	Mon Jun 16 10:46:22 2008 -0700
@@ -43,7 +43,7 @@
  * CookieHandler.getDefault().
  *
  * For more information on HTTP state management, see <a
- * href="http://www.ietf.org/rfc/rfc2965.txt""><i>RFC&nbsp;2965: HTTP
+ * href="http://www.ietf.org/rfc/rfc2965.txt"><i>RFC&nbsp;2965: HTTP
  * State Management Mechanism</i></a>
  *
  * @author Yingxian Wang
--- a/jdk/src/share/classes/java/net/ResponseCache.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/java/net/ResponseCache.java	Mon Jun 16 10:46:22 2008 -0700
@@ -52,7 +52,7 @@
  * protocol is allowed to use a cached response.
  *
  * For more information on HTTP caching, see <a
- * href="http://www.ietf.org/rfc/rfc2616.txt""><i>RFC&nbsp;2616: Hypertext
+ * href="http://www.ietf.org/rfc/rfc2616.txt"><i>RFC&nbsp;2616: Hypertext
  * Transfer Protocol -- HTTP/1.1</i></a>
  *
  * @author Yingxian Wang
--- a/jdk/src/share/classes/java/net/URI.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/java/net/URI.java	Mon Jun 16 10:46:22 2008 -0700
@@ -49,7 +49,7 @@
  *
  * <p> Aside from some minor deviations noted below, an instance of this
  * class represents a URI reference as defined by
- * <a href="http://www.ietf.org/rfc/rfc2396.txt""><i>RFC&nbsp;2396: Uniform
+ * <a href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
  * Resource Identifiers (URI): Generic Syntax</i></a>, amended by <a
  * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
  * Literal IPv6 Addresses in URLs</i></a>. The Literal IPv6 address format
@@ -461,7 +461,7 @@
  * transformation format of ISO 10646</i></a>, <br><a
  * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IPv6 Addressing
  * Architecture</i></a>, <br><a
- * href="http://www.ietf.org/rfc/rfc2396.txt""><i>RFC&nbsp;2396: Uniform
+ * href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
  * Resource Identifiers (URI): Generic Syntax</i></a>, <br><a
  * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
  * Literal IPv6 Addresses in URLs</i></a>, <br><a
--- a/jdk/src/share/classes/java/net/URL.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/java/net/URL.java	Mon Jun 16 10:46:22 2008 -0700
@@ -66,7 +66,7 @@
  * </pre></blockquote>
  * <p>
  * The syntax of <code>URL</code> is defined by  <a
- * href="http://www.ietf.org/rfc/rfc2396.txt""><i>RFC&nbsp;2396: Uniform
+ * href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
  * Resource Identifiers (URI): Generic Syntax</i></a>, amended by <a
  * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
  * Literal IPv6 Addresses in URLs</i></a>. The Literal IPv6 address format
--- a/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/ClientHandshaker.java	Mon Jun 16 10:46:22 2008 -0700
@@ -32,6 +32,7 @@
 import java.util.*;
 
 import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
 import java.security.spec.ECParameterSpec;
 
 import java.security.cert.X509Certificate;
@@ -147,8 +148,33 @@
         case HandshakeMessage.ht_server_key_exchange:
             serverKeyExchangeReceived = true;
             switch (keyExchange) {
-            case K_RSA:
             case K_RSA_EXPORT:
+                /**
+                 * The server key exchange message is sent by the server only
+                 * when the server certificate message does not contain the
+                 * proper amount of data to allow the client to exchange a
+                 * premaster secret, such as when RSA_EXPORT is used and the
+                 * public key in the server certificate is longer than 512 bits.
+                 */
+                if (serverKey == null) {
+                    throw new SSLProtocolException
+                        ("Server did not send certificate message");
+                }
+
+                if (!(serverKey instanceof RSAPublicKey)) {
+                    throw new SSLProtocolException("Protocol violation:" +
+                        " the certificate type must be appropriate for the" +
+                        " selected cipher suite's key exchange algorithm");
+                }
+
+                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
+                    throw new SSLProtocolException("Protocol violation:" +
+                        " server sent a server key exchange message for" +
+                        " key exchange " + keyExchange +
+                        " when the public key in the server certificate" +
+                        " is less than or equal to 512 bits in length");
+                }
+
                 try {
                     this.serverKeyExchange(new RSA_ServerKeyExchange(input));
                 } catch (GeneralSecurityException e) {
@@ -180,6 +206,9 @@
                     throwSSLException("Server key", e);
                 }
                 break;
+            case K_RSA:
+            case K_DH_RSA:
+            case K_DH_DSS:
             case K_ECDH_ECDSA:
             case K_ECDH_RSA:
                 throw new SSLProtocolException("Protocol violation: server sent"
@@ -580,6 +609,16 @@
 
         case K_RSA:
         case K_RSA_EXPORT:
+            if (serverKey == null) {
+                throw new SSLProtocolException
+                        ("Server did not send certificate message");
+            }
+
+            if (!(serverKey instanceof RSAPublicKey)) {
+                throw new SSLProtocolException
+                        ("Server certificate does not include an RSA key");
+            }
+
             /*
              * For RSA key exchange, we randomly generate a new
              * pre-master secret and encrypt it with the server's
@@ -588,8 +627,29 @@
              * it's a performance speedup not to do that until
              * the client's waiting for the server response, but
              * more of a speedup for the D-H case.
+             *
+             * If the RSA_EXPORT scheme is active, when the public
+             * key in the server certificate is less than or equal
+             * to 512 bits in length, use the cert's public key,
+             * otherwise, the ephemeral one.
              */
-            PublicKey key = (keyExchange == K_RSA) ? serverKey : ephemeralServerKey;
+            PublicKey key;
+            if (keyExchange == K_RSA) {
+                key = serverKey;
+            } else {    // K_RSA_EXPORT
+                if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
+                    // extraneous ephemeralServerKey check done
+                    // above in processMessage()
+                    key = serverKey;
+                } else {
+                    if (ephemeralServerKey == null) {
+                        throw new SSLProtocolException("Server did not send" +
+                            " a RSA_EXPORT Server Key Exchange message");
+                    }
+                    key = ephemeralServerKey;
+                }
+            }
+
             m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion,
                                 sslContext.getSecureRandom(), key);
             break;
--- a/jdk/src/share/classes/sun/security/tools/PolicyTool.java	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/share/classes/sun/security/tools/PolicyTool.java	Mon Jun 16 10:46:22 2008 -0700
@@ -4104,7 +4104,7 @@
                 "getClassLoader",
                 "setContextClassLoader",
                 "enableContextClassLoaderOverride",
-                "setSecurityManage",
+                "setSecurityManager",
                 "createSecurityManager",
                 "getenv.<" +
                     PolicyTool.rb.getString("environment variable name") + ">",
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Mon Jun 16 10:46:22 2008 -0700
@@ -138,7 +138,6 @@
 Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
                                                 jstring host) {
     const char *hostname;
-    jobject name;
     jobjectArray ret = 0;
     struct hostent res, *hp = 0;
     char buf[HENT_BUF_SIZE];
@@ -210,12 +209,6 @@
             addrp++;
         }
 
-        name = (*env)->NewStringUTF(env, hostname);
-
-        if (IS_NULL(name)) {
-          goto cleanupAndReturn;
-        }
-
         ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
         if (IS_NULL(ret)) {
             /* we may have memory to free at the end of this */
@@ -231,7 +224,7 @@
           }
           (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                               ntohl((*addrp)->s_addr));
-          (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+          (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
           (*env)->SetObjectArrayElement(env, ret, i, iaObj);
           addrp++;
           i++;
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Mon Jun 16 10:46:22 2008 -0700
@@ -142,7 +142,6 @@
                                                 jstring host) {
     const char *hostname;
     jobjectArray ret = 0;
-    jobject name;
     int retLen = 0;
     jclass byteArrayCls;
     jboolean preferIPv6Address;
@@ -310,11 +309,6 @@
                 inet6Index = inetCount;
             }
 
-            name = (*env)->NewStringUTF(env, hostname);
-            if (IS_NULL(name)) {
-              ret = NULL;
-              goto cleanupAndReturn;
-            }
             while (iterator != NULL) {
               if (iterator->ai_family == AF_INET) {
                 jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
@@ -324,7 +318,7 @@
                 }
                 (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                                     ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
-                (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+                (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
                 inetIndex++;
               } else if (iterator->ai_family == AF_INET6) {
@@ -355,7 +349,7 @@
                   (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
                 }
                 (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
-                (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+                (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                 (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
                 inet6Index++;
               }
--- a/jdk/src/solaris/native/java/net/NetworkInterface.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c	Mon Jun 16 10:46:22 2008 -0700
@@ -1117,9 +1117,33 @@
   if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) {
     ret = if2.ifr_flags;
   } else {
+#if defined(__solaris__) && defined(AF_INET6)
+    /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
+    struct lifreq lifr;
+
+    close(sock);
+    sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+
+    if (sock < 0) {
+      (*env)->ReleaseStringUTFChars(env, name, name_utf);
+      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                  "Socket creation failed");
+      return -1;
+    }
+
+    memset((caddr_t)&lifr, 0, sizeof(lifr));
+    strcpy((caddr_t)&(lifr.lifr_name), name_utf);
+
+    if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) {
+      ret = lifr.lifr_flags;
+    } else {
+      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                               "IOCTL failed");
+    }
+#else
     NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                                  "IOCTL failed");
-    ret = -1;
+#endif
   }
   close(sock);
   /* release the UTF string and interface list */
@@ -1484,8 +1508,23 @@
     if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
       ret = lifr.lifr_mtu;
     } else {
-      NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
-                                   "IOCTL failed");
+      /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */
+      close(sock);
+      sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
+
+      if (sock < 0) {
+        (*env)->ReleaseStringUTFChars(env, name, name_utf);
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "Socket creation failed");
+        return -1;
+      }
+
+      if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) {
+        ret = lifr.lifr_mtu;
+      } else {
+        NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
+                                     "IOCTL failed");
+      }
     }
 #endif
     close(sock);
--- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c	Mon Jun 16 10:46:22 2008 -0700
@@ -95,94 +95,24 @@
  */
 static int getMarkerFD()
 {
-    int server_fd, child_fd, connect_fd;
-    SOCKADDR him;
-    int type, len, port;
+    int sv[2];
 
-    type = AF_INET;
-#ifdef AF_INET6
-    if (ipv6_available()) {
-        type = AF_INET6;
+#ifdef AF_UNIX
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) {
+        return -1;
     }
+#else
+    return -1;
 #endif
 
     /*
-     * Create listener on any port
-     */
-    server_fd = JVM_Socket(type, SOCK_STREAM, 0);
-    if (server_fd < 0) {
-        return -1;
-    }
-    if (JVM_Listen(server_fd, 1) == -1) {
-        JVM_SocketClose(server_fd);
-        return -1;
-    }
-    len = SOCKADDR_LEN;
-    if (JVM_GetSockName(server_fd, (struct sockaddr *)&him, &len) == -1) {
-        JVM_SocketClose(server_fd);
-        return -1;
-    }
-    port = NET_GetPortFromSockaddr((struct sockaddr *)&him);
-
-    /*
-     * Establish connection from client socket.
-     * Server is bound to 0.0.0.0/X or ::/X
-     * We connect to 127.0.0.1/X or ::1/X
-     */
-#ifdef AF_INET6
-    if (ipv6_available()) {
-        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)&him;
-        jbyte caddr[16];
-        memset((char *) caddr, 0, 16);
-        caddr[15] = 1;
-        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
-        memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
-        him6->sin6_port = htons((short) port);
-        him6->sin6_family = AF_INET6;
-        len = sizeof(struct sockaddr_in6) ;
-    } else
-#endif /* AF_INET6 */
-    {
-        struct sockaddr_in *him4 = (struct sockaddr_in*)&him;
-        memset((char *) him4, 0, sizeof(struct sockaddr_in));
-        him4->sin_port = htons((short) port);
-        him4->sin_addr.s_addr = (uint32_t) htonl(0x7f000001);
-        him4->sin_family = AF_INET;
-        len = sizeof(struct sockaddr_in);
-    }
-    connect_fd = JVM_Socket(type, SOCK_STREAM, 0);
-    if (connect_fd < 0) {
-        JVM_SocketClose(server_fd);
-        return -1;
-    }
-    if (JVM_Connect(connect_fd, (struct sockaddr *) &him, len) == -1) {
-        JVM_SocketClose(server_fd);
-        JVM_SocketClose(connect_fd);
-        return -1;
-    }
-
-    /*
-     * Server accepts connection - do in in non-blocking mode to avoid
-     * hanging if there's an error (should never happen!!!)
-     */
-    SET_NONBLOCKING(server_fd);
-    len = SOCKADDR_LEN;
-    child_fd = JVM_Accept(server_fd, (struct sockaddr *)&him, (jint *)&len);
-    if (child_fd == -1) {
-        JVM_SocketClose(server_fd);
-        JVM_SocketClose(connect_fd);
-        return -1;
-    }
-
-    /*
-     * Finally shutdown connect_fd (any reads to this fd will get
+     * Finally shutdown sv[0] (any reads to this fd will get
      * EOF; any writes will get an error).
      */
-    JVM_SocketShutdown(connect_fd, 2);
-    JVM_SocketClose(child_fd);
-    JVM_SocketClose(server_fd);
+    JVM_SocketShutdown(sv[0], 2);
+    JVM_SocketClose(sv[1]);
 
-    return connect_fd;
+    return sv[0];
 }
 
 
@@ -1087,7 +1017,7 @@
      */
     if (cmd == java_net_SocketOptions_SO_BINDADDR) {
         SOCKADDR him;
-        int len = 0;
+        socklen_t len = 0;
         int port;
         jobject iaObj;
         jclass iaCntrClass;
--- a/jdk/src/windows/native/java/net/Inet4AddressImpl.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/windows/native/java/net/Inet4AddressImpl.c	Mon Jun 16 10:46:22 2008 -0700
@@ -137,7 +137,6 @@
 Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
                                                 jstring host) {
     const char *hostname;
-    jobject name;
     struct hostent *hp;
     unsigned int addr[4];
 
@@ -229,10 +228,6 @@
             addrp++;
         }
 
-        name = (*env)->NewStringUTF(env, hostname);
-        if (IS_NULL(name)) {
-          goto cleanupAndReturn;
-        }
         ret = (*env)->NewObjectArray(env, i, ni_iacls, NULL);
 
         if (IS_NULL(ret)) {
@@ -249,7 +244,7 @@
           }
           (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                               ntohl((*addrp)->s_addr));
-          (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+          (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
           (*env)->SetObjectArrayElement(env, ret, i, iaObj);
           addrp++;
           i++;
--- a/jdk/src/windows/native/java/net/Inet6AddressImpl.c	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/src/windows/native/java/net/Inet6AddressImpl.c	Mon Jun 16 10:46:22 2008 -0700
@@ -86,7 +86,6 @@
 Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
                                                 jstring host) {
     const char *hostname;
-    jobject name;
     jobjectArray ret = 0;
     int retLen = 0;
     jboolean preferIPv6Address;
@@ -237,12 +236,6 @@
                 inet6Index = inetCount;
             }
 
-            name = (*env)->NewStringUTF(env, hostname);
-            if (IS_NULL(name)) {
-              ret = NULL;
-              goto cleanupAndReturn;
-            }
-
             while (iterator != NULL) {
                 if (iterator->ai_family == AF_INET) {
                   jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID);
@@ -252,7 +245,7 @@
                   }
                   (*env)->SetIntField(env, iaObj, ni_iaaddressID,
                                       ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
-                  (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+                  (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                   (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
                     inetIndex ++;
                 } else if (iterator->ai_family == AF_INET6) {
@@ -276,7 +269,7 @@
                     (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE);
                   }
                   (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress);
-                  (*env)->SetObjectField(env, iaObj, ni_iahostID, name);
+                  (*env)->SetObjectField(env, iaObj, ni_iahostID, host);
                   (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
                   inet6Index ++;
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/ClientHandshaker/RSAExport.java	Mon Jun 16 10:46:22 2008 -0700
@@ -0,0 +1,561 @@
+/*
+ * Copyright 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.
+ *
+ * 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 6690018
+ * @summary RSAClientKeyExchange NullPointerException
+ */
+
+/*
+ * Certificates and key used in the test.
+ *
+ * TLS server certificate:
+ * server private key:
+ * -----BEGIN RSA PRIVATE KEY-----
+ * Proc-Type: 4,ENCRYPTED
+ * DEK-Info: DES-EDE3-CBC,97EC03A2D031B7BC
+ *
+ * 22wrD+DPv3VF8xg9xoeBqHzFnOVbTLQgVulzaCECDF4zWdxElYKy4yYyY6dMDehi
+ * XT77NTsq1J14zjJHPp2/U6B5OpZxnf97ZSD0ZC9/DDe/2gjW4fY1Lv0TVP0PdXnm
+ * cj84RaDiiSk/cERlFzFJ5L8ULMwxdOtYwXwZ4upITw2lT+8zDlBD2i3zZ4TcWrzE
+ * /su5Kpu+Mp3wthfGX+ZGga2T/NS8ZCKZE+gJDPKQZ/x34VBw+YANQGyCJPv1iMaE
+ * RyagnpApH9OPSrRIp2iR6uWT6836CET2erbfPaC1odyd8IsbnLldVs9CklH7EgXL
+ * Nms+DqrQEbNmvMuQYEFyZEHN9D1fGONeacx+cjI85FyMSHSEO65JJmasAxgQe4nF
+ * /yVz3rNQ2qAGqBhjsjP/WaXuB2aLZiAli/HjN17EJws=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * -----BEGIN RSA PRIVATE KEY-----
+ * MIIBOQIBAAJBALlfGg/5ZweJcW5zqLdnQ2uyircqDDlENKnv9FABOm/j0wnlPHqX
+ * CCqFBLoM7tG8ohci1SPy6fLJ5dqLf5FOH2sCAwEAAQJATO0/hpOMgx8xmJGc2Yeb
+ * /gyY7kwfyIAajs9Khw0LcDTYTo2EAI+vMmDpU+dvmOCLUqq/Z2tiKJhGyrmcBlxr
+ * kQIhAPYkbYovtvWHslxRb78x4eCrn2p1H7iolNKbyepjCI3zAiEAwMufJlLI9Q0O
+ * BIr7fPnUhbs9NyMHLIvIQAf/hXYubqkCIGJZR9NxIT+VyrSMbYQNoF0u9fGJfvU/
+ * lsdYLCOVEnP1AiAsSFjUx50K1CXNG1MqYIPU963W1T/Xln+3XV7ue7esiQIgW2Lu
+ * xGvz2dAUsGId+Xr2GZXb7ZucY/cPt4o5qdP1m7c=
+ * -----END RSA PRIVATE KEY-----
+ *
+ * Private-Key: (512 bit)
+ * modulus:
+ *     00:b9:5f:1a:0f:f9:67:07:89:71:6e:73:a8:b7:67:
+ *     43:6b:b2:8a:b7:2a:0c:39:44:34:a9:ef:f4:50:01:
+ *     3a:6f:e3:d3:09:e5:3c:7a:97:08:2a:85:04:ba:0c:
+ *     ee:d1:bc:a2:17:22:d5:23:f2:e9:f2:c9:e5:da:8b:
+ *     7f:91:4e:1f:6b
+ * publicExponent: 65537 (0x10001)
+ * privateExponent:
+ *     4c:ed:3f:86:93:8c:83:1f:31:98:91:9c:d9:87:9b:
+ *     fe:0c:98:ee:4c:1f:c8:80:1a:8e:cf:4a:87:0d:0b:
+ *     70:34:d8:4e:8d:84:00:8f:af:32:60:e9:53:e7:6f:
+ *     98:e0:8b:52:aa:bf:67:6b:62:28:98:46:ca:b9:9c:
+ *     06:5c:6b:91
+ * prime1:
+ *     00:f6:24:6d:8a:2f:b6:f5:87:b2:5c:51:6f:bf:31:
+ *     e1:e0:ab:9f:6a:75:1f:b8:a8:94:d2:9b:c9:ea:63:
+ *     08:8d:f3
+ * prime2:
+ *     00:c0:cb:9f:26:52:c8:f5:0d:0e:04:8a:fb:7c:f9:
+ *     d4:85:bb:3d:37:23:07:2c:8b:c8:40:07:ff:85:76:
+ *     2e:6e:a9
+ * exponent1:
+ *     62:59:47:d3:71:21:3f:95:ca:b4:8c:6d:84:0d:a0:
+ *     5d:2e:f5:f1:89:7e:f5:3f:96:c7:58:2c:23:95:12:
+ *     73:f5
+ * exponent2:
+ *     2c:48:58:d4:c7:9d:0a:d4:25:cd:1b:53:2a:60:83:
+ *     d4:f7:ad:d6:d5:3f:d7:96:7f:b7:5d:5e:ee:7b:b7:
+ *     ac:89
+ * coefficient:
+ *     5b:62:ee:c4:6b:f3:d9:d0:14:b0:62:1d:f9:7a:f6:
+ *     19:95:db:ed:9b:9c:63:f7:0f:b7:8a:39:a9:d3:f5:
+ *     9b:b7
+ *
+ *
+ * server certificate:
+ *  Data:
+ *      Version: 3 (0x2)
+ *      Serial Number: 11 (0xb)
+ *      Signature Algorithm: sha1WithRSAEncryption
+ *      Issuer: C=US, ST=Some-State, O=Some Org, CN=Someone
+ *      Validity
+ *          Not Before: Apr 18 15:07:30 2008 GMT
+ *          Not After : Jan  4 15:07:30 2028 GMT
+ *      Subject: C=US, ST=Some-State, O=Some Org, CN=SomeoneExport
+ *      Subject Public Key Info:
+ *          Public Key Algorithm: rsaEncryption
+ *          RSA Public Key: (512 bit)
+ *              Modulus (512 bit):
+ *                  00:b9:5f:1a:0f:f9:67:07:89:71:6e:73:a8:b7:67:
+ *                  43:6b:b2:8a:b7:2a:0c:39:44:34:a9:ef:f4:50:01:
+ *                  3a:6f:e3:d3:09:e5:3c:7a:97:08:2a:85:04:ba:0c:
+ *                  ee:d1:bc:a2:17:22:d5:23:f2:e9:f2:c9:e5:da:8b:
+ *                  7f:91:4e:1f:6b
+ *              Exponent: 65537 (0x10001)
+ *      X509v3 extensions:
+ *          X509v3 Basic Constraints:
+ *              CA:FALSE
+ *          X509v3 Key Usage:
+ *              Digital Signature, Non Repudiation, Key Encipherment
+ *          X509v3 Subject Key Identifier:
+ *              F1:30:98:BE:7C:AA:F9:B1:91:38:60:AE:13:5F:67:9C:0A:32:9E:31
+ *          X509v3 Authority Key Identifier:
+ *              keyid:B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICIDCCAYmgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT
+ * B1NvbWVvbmUwHhcNMDgwNDE4MTUwNzMwWhcNMjgwMTA0MTUwNzMwWjBNMQswCQYD
+ * VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx
+ * FjAUBgNVBAMTDVNvbWVvbmVFeHBvcnQwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA
+ * uV8aD/lnB4lxbnOot2dDa7KKtyoMOUQ0qe/0UAE6b+PTCeU8epcIKoUEugzu0byi
+ * FyLVI/Lp8snl2ot/kU4fawIDAQABo1owWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF
+ * 4DAdBgNVHQ4EFgQU8TCYvnyq+bGROGCuE19nnAoynjEwHwYDVR0jBBgwFoAUtTJD
+ * 1wAkkrrpleX5o2RshO4zLhUwDQYJKoZIhvcNAQEFBQADgYEAFU+fP9FSTQNVZOhv
+ * eJ+zq6wI/biwzTgPbAq3yu2gb5kT85z4nzqBhPd2LWWFXhUW/D8QyNZ54X30y0Ug
+ * 3NfUAvOANW7CgUbHBmm77KQiF4nWdh338qqq9HzLGrPqcxX0dmiq2RBVPy9wb2Ea
+ * FTZiU2v+9pkoLoSDnCOfPCg/4Q4=
+ * -----END CERTIFICATE-----
+ *
+ *
+ * Trusted CA certificate:
+ * Certificate:
+ *   Data:
+ *       Version: 3 (0x2)
+ *       Serial Number: 0 (0x0)
+ *       Signature Algorithm: md5WithRSAEncryption
+ *       Issuer: C=US, ST=Some-State, O=Some Org, CN=Someone
+ *       Validity
+ *           Not Before: Mar 30 11:44:47 2001 GMT
+ *           Not After : Apr 27 11:44:47 2028 GMT
+ *       Subject: C=US, ST=Some-State, O=Some Org, CN=Someone
+ *       Subject Public Key Info:
+ *           Public Key Algorithm: rsaEncryption
+ *           RSA Public Key: (1024 bit)
+ *               Modulus (1024 bit):
+ *                   00:c1:98:e4:7a:87:53:0f:94:87:dc:da:f3:59:39:
+ *                   3e:36:95:e8:77:58:ff:46:8a:81:1b:5e:c5:4c:fa:
+ *                   b6:91:19:30:be:5b:ef:4c:aa:84:30:a4:9a:d4:68:
+ *                   af:ef:fa:b4:2c:76:8b:29:33:46:cf:38:74:7c:79:
+ *                   d5:07:a6:43:39:84:52:39:4f:8a:1c:f3:73:19:12:
+ *                   40:cf:ee:a1:77:43:01:02:be:8d:32:11:28:70:f4:
+ *                   cf:ab:43:75:e4:fb:74:f1:8c:2e:43:24:ba:85:3f:
+ *                   66:3a:05:ea:f7:ce:5b:97:e2:34:a3:f0:87:f4:f8:
+ *                   d1:59:12:5a:68:b7:78:64:a9
+ *               Exponent: 65537 (0x10001)
+ *       X509v3 extensions:
+ *           X509v3 Subject Key Identifier:
+ *               B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
+ *           X509v3 Authority Key Identifier:
+ *               keyid:B5:32:43:D7:00:24:92:BA:E9:95:E5:F9:A3:64:6C:84:EE:33:2E:15
+ *               DirName:/C=US/ST=Some-State/O=Some Org/CN=Someone
+ *               serial:00
+ *
+ *           X509v3 Basic Constraints:
+ *               CA:TRUE
+ *
+ * -----BEGIN CERTIFICATE-----
+ * MIICpjCCAg+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBHMQswCQYDVQQGEwJVUzET
+ * MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT
+ * B1NvbWVvbmUwHhcNMDEwMzMwMTE0NDQ3WhcNMjgwNDI3MTE0NDQ3WjBHMQswCQYD
+ * VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx
+ * EDAOBgNVBAMTB1NvbWVvbmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMGY
+ * 5HqHUw+Uh9za81k5PjaV6HdY/0aKgRtexUz6tpEZML5b70yqhDCkmtRor+/6tCx2
+ * iykzRs84dHx51QemQzmEUjlPihzzcxkSQM/uoXdDAQK+jTIRKHD0z6tDdeT7dPGM
+ * LkMkuoU/ZjoF6vfOW5fiNKPwh/T40VkSWmi3eGSpAgMBAAGjgaEwgZ4wHQYDVR0O
+ * BBYEFLUyQ9cAJJK66ZXl+aNkbITuMy4VMG8GA1UdIwRoMGaAFLUyQ9cAJJK66ZXl
+ * +aNkbITuMy4VoUukSTBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0
+ * ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMTB1NvbWVvbmWCAQAwDAYDVR0T
+ * BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBhf3PX0xWxtaUwZlWCO7GfPwCKgBWr
+ * CXqlqjtWHCshaaU7wUsDOwxFDWwKjFrMerQLsLuBlhdXEbNfSPjychkQtfezQHcS
+ * q0Atq7+KVSmRbDw6oKVRs5v1BBzLCupy+o16fNz3/hwreAWwQnSMtAh/osNS9w1b
+ * QeVWU+JV47H+vg==
+ * -----END CERTIFICATE-----
+ *
+ */
+
+import java.io.*;
+import java.net.*;
+import java.security.KeyStore;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import javax.net.ssl.*;
+import java.math.BigInteger;
+
+public class RSAExport {
+
+    /*
+     * =============================================================
+     * 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 trusedCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICpjCCAg+gAwIBAgIBADANBgkqhkiG9w0BAQQFADBHMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT\n" +
+        "B1NvbWVvbmUwHhcNMDEwMzMwMTE0NDQ3WhcNMjgwNDI3MTE0NDQ3WjBHMQswCQYD\n" +
+        "VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx\n" +
+        "EDAOBgNVBAMTB1NvbWVvbmUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMGY\n" +
+        "5HqHUw+Uh9za81k5PjaV6HdY/0aKgRtexUz6tpEZML5b70yqhDCkmtRor+/6tCx2\n" +
+        "iykzRs84dHx51QemQzmEUjlPihzzcxkSQM/uoXdDAQK+jTIRKHD0z6tDdeT7dPGM\n" +
+        "LkMkuoU/ZjoF6vfOW5fiNKPwh/T40VkSWmi3eGSpAgMBAAGjgaEwgZ4wHQYDVR0O\n" +
+        "BBYEFLUyQ9cAJJK66ZXl+aNkbITuMy4VMG8GA1UdIwRoMGaAFLUyQ9cAJJK66ZXl\n" +
+        "+aNkbITuMy4VoUukSTBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0\n" +
+        "ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMTB1NvbWVvbmWCAQAwDAYDVR0T\n" +
+        "BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBhf3PX0xWxtaUwZlWCO7GfPwCKgBWr\n" +
+        "CXqlqjtWHCshaaU7wUsDOwxFDWwKjFrMerQLsLuBlhdXEbNfSPjychkQtfezQHcS\n" +
+        "q0Atq7+KVSmRbDw6oKVRs5v1BBzLCupy+o16fNz3/hwreAWwQnSMtAh/osNS9w1b\n" +
+        "QeVWU+JV47H+vg==\n" +
+        "-----END CERTIFICATE-----";
+
+    static String serverCertStr =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIICIDCCAYmgAwIBAgIBCzANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzET\n" +
+        "MBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcxEDAOBgNVBAMT\n" +
+        "B1NvbWVvbmUwHhcNMDgwNDE4MTUwNzMwWhcNMjgwMTA0MTUwNzMwWjBNMQswCQYD\n" +
+        "VQQGEwJVUzETMBEGA1UECBMKU29tZS1TdGF0ZTERMA8GA1UEChMIU29tZSBPcmcx\n" +
+        "FjAUBgNVBAMTDVNvbWVvbmVFeHBvcnQwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA\n" +
+        "uV8aD/lnB4lxbnOot2dDa7KKtyoMOUQ0qe/0UAE6b+PTCeU8epcIKoUEugzu0byi\n" +
+        "FyLVI/Lp8snl2ot/kU4fawIDAQABo1owWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF\n" +
+        "4DAdBgNVHQ4EFgQU8TCYvnyq+bGROGCuE19nnAoynjEwHwYDVR0jBBgwFoAUtTJD\n" +
+        "1wAkkrrpleX5o2RshO4zLhUwDQYJKoZIhvcNAQEFBQADgYEAFU+fP9FSTQNVZOhv\n" +
+        "eJ+zq6wI/biwzTgPbAq3yu2gb5kT85z4nzqBhPd2LWWFXhUW/D8QyNZ54X30y0Ug\n" +
+        "3NfUAvOANW7CgUbHBmm77KQiF4nWdh338qqq9HzLGrPqcxX0dmiq2RBVPy9wb2Ea\n" +
+        "FTZiU2v+9pkoLoSDnCOfPCg/4Q4=\n" +
+        "-----END CERTIFICATE-----";
+
+    static byte privateExponent[] = {
+        (byte)0x4c, (byte)0xed, (byte)0x3f, (byte)0x86,
+        (byte)0x93, (byte)0x8c, (byte)0x83, (byte)0x1f,
+        (byte)0x31, (byte)0x98, (byte)0x91, (byte)0x9c,
+        (byte)0xd9, (byte)0x87, (byte)0x9b, (byte)0xfe,
+        (byte)0x0c, (byte)0x98, (byte)0xee, (byte)0x4c,
+        (byte)0x1f, (byte)0xc8, (byte)0x80, (byte)0x1a,
+        (byte)0x8e, (byte)0xcf, (byte)0x4a, (byte)0x87,
+        (byte)0x0d, (byte)0x0b, (byte)0x70, (byte)0x34,
+        (byte)0xd8, (byte)0x4e, (byte)0x8d, (byte)0x84,
+        (byte)0x00, (byte)0x8f, (byte)0xaf, (byte)0x32,
+        (byte)0x60, (byte)0xe9, (byte)0x53, (byte)0xe7,
+        (byte)0x6f, (byte)0x98, (byte)0xe0, (byte)0x8b,
+        (byte)0x52, (byte)0xaa, (byte)0xbf, (byte)0x67,
+        (byte)0x6b, (byte)0x62, (byte)0x28, (byte)0x98,
+        (byte)0x46, (byte)0xca, (byte)0xb9, (byte)0x9c,
+        (byte)0x06, (byte)0x5c, (byte)0x6b, (byte)0x91
+    };
+
+    static byte modulus[] = {
+        (byte)0x00,
+        (byte)0xb9, (byte)0x5f, (byte)0x1a, (byte)0x0f,
+        (byte)0xf9, (byte)0x67, (byte)0x07, (byte)0x89,
+        (byte)0x71, (byte)0x6e, (byte)0x73, (byte)0xa8,
+        (byte)0xb7, (byte)0x67, (byte)0x43, (byte)0x6b,
+        (byte)0xb2, (byte)0x8a, (byte)0xb7, (byte)0x2a,
+        (byte)0x0c, (byte)0x39, (byte)0x44, (byte)0x34,
+        (byte)0xa9, (byte)0xef, (byte)0xf4, (byte)0x50,
+        (byte)0x01, (byte)0x3a, (byte)0x6f, (byte)0xe3,
+        (byte)0xd3, (byte)0x09, (byte)0xe5, (byte)0x3c,
+        (byte)0x7a, (byte)0x97, (byte)0x08, (byte)0x2a,
+        (byte)0x85, (byte)0x04, (byte)0xba, (byte)0x0c,
+        (byte)0xee, (byte)0xd1, (byte)0xbc, (byte)0xa2,
+        (byte)0x17, (byte)0x22, (byte)0xd5, (byte)0x23,
+        (byte)0xf2, (byte)0xe9, (byte)0xf2, (byte)0xc9,
+        (byte)0xe5, (byte)0xda, (byte)0x8b, (byte)0x7f,
+        (byte)0x91, (byte)0x4e, (byte)0x1f, (byte)0x6b
+    };
+
+    static char passphrase[] = "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 =
+                getSSLContext(true).getServerSocketFactory();
+        SSLServerSocket sslServerSocket =
+                (SSLServerSocket) sslssf.createServerSocket(serverPort);
+
+        serverPort = sslServerSocket.getLocalPort();
+
+        /*
+         * Signal Client, we're ready for this connect.
+         */
+        serverReady = true;
+
+        // Enable RSA_EXPORT cipher suites only.
+        try {
+            String enabledSuites[] = {
+                "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"};
+            sslServerSocket.setEnabledCipherSuites(enabledSuites);
+        } catch (IllegalArgumentException iae) {
+            // ignore the exception a cipher suite is unsupported.
+        }
+
+        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+        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 =
+                getSSLContext(false).getSocketFactory();
+        SSLSocket sslSocket = (SSLSocket)
+                sslsf.createSocket("localhost", serverPort);
+
+        // Enable RSA_EXPORT cipher suites only.
+        try {
+            String enabledSuites[] = {
+                "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+                "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"};
+            sslSocket.setEnabledCipherSuites(enabledSuites);
+        } catch (IllegalArgumentException iae) {
+            // ignore the exception a cipher suite is unsupported.
+        }
+
+        InputStream sslIS = sslSocket.getInputStream();
+        OutputStream sslOS = sslSocket.getOutputStream();
+
+        sslOS.write(280);
+        sslOS.flush();
+        sslIS.read();
+
+        sslSocket.close();
+    }
+
+    /*
+     * =============================================================
+     * 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 RSAExport();
+    }
+
+    Thread clientThread = null;
+    Thread serverThread = null;
+
+    /*
+     * Primary constructor, used to drive remainder of the test.
+     *
+     * Fork off the other side, then do your work.
+     */
+    RSAExport() 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..." + e);
+                        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();
+        }
+    }
+
+    // Get the SSL context
+    private SSLContext getSSLContext(boolean authnRequired) throws Exception {
+        // generate certificate from cert string
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+        ByteArrayInputStream is =
+                    new ByteArrayInputStream(trusedCertStr.getBytes());
+        Certificate trustedCert = cf.generateCertificate(is);
+
+        // create a key store
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(null, null);
+
+        // import the trusted cert
+        ks.setCertificateEntry("RSA Export Signer", trustedCert);
+
+        if (authnRequired) {
+            // generate the private key.
+            RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(
+                                            new BigInteger(modulus),
+                                            new BigInteger(privateExponent));
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            RSAPrivateKey priKey =
+                    (RSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+            // generate certificate chain
+            is = new ByteArrayInputStream(serverCertStr.getBytes());
+            Certificate serverCert = cf.generateCertificate(is);
+
+            Certificate[] chain = new Certificate[2];
+            chain[0] = serverCert;
+            chain[1] = trustedCert;
+
+            // import the key entry.
+            ks.setKeyEntry("RSA Export", priKey, passphrase, chain);
+        }
+
+        // create SSL context
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+        tmf.init(ks);
+
+        SSLContext ctx = SSLContext.getInstance("TLS");
+        if (authnRequired) {
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, passphrase);
+
+            ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        } else {
+            ctx.init(null, tmf.getTrustManagers(), null);
+        }
+
+        return ctx;
+    }
+
+}
--- a/jdk/test/sun/security/tools/keytool/console.sh	Sat Jun 14 09:30:20 2008 -0700
+++ b/jdk/test/sun/security/tools/keytool/console.sh	Mon Jun 16 10:46:22 2008 -0700
@@ -30,7 +30,7 @@
 #
 # @run shell/manual console.sh
 
-if [ "$ALT_PASS" == "" ]; then
+if [ "$ALT_PASS" = "" ]; then
   export PASS=äöäöäöäö
 else
   export PASS=$ALT_PASS
@@ -54,7 +54,7 @@
 echo "   Enter key password for <mykey>"
 echo "         (RETURN if same as keystore password):  Enter keystore password:"
 echo "only response to the last prompt by typing $PASS and press ENTER"
-echo 
+echo
 echo "Only if all the command run correctly without showing any error "
 echo "or warning, this test passes."
 echo
@@ -87,3 +87,6 @@
 $JM/bin/keytool -keystore kkk -list
 echo $PASS| $J5/bin/keytool -keystore kkk -list
 echo $PASS| $JM/bin/keytool -keystore kkk -list
+rm kkk
+
+exit 0