Hello,
I developed a very easy application using RMI, it works great.
Now I try to use RMI over SSL to make the communication secure. I'm very new to RMI and SSL, but for what I've read there's a package SslRMIClientSocketFactory and SslRMIServerSocketFactory, and try to use them within my previous RMI code. I read about the Keystore and Truststore, I follow the steps on these tutorials for creating the keyes and all that stuff (at least is the tutorial says is all I need)
http://today.java.net/pub/a/today/2005/10/06/the-new-rmi.html
http://download.oracle.com/javase/tutorial/security/toolsign/step3.html
Then I used
System.setProperty(......);
to set the Keystore, the Keystore pass and the Truststore, so my code is as follows
THE SERVER
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
import java.rmi.*;
import javax.rmi.ssl.*;
public class MessageServer implements Message{
public static void main(String args[]){
try{
System.setProperty("javax.net.ssl.keyStore", "./store");
System.setProperty("javax.net.ssl.keyStorePassword", "prueba");
Message server = new MessageServer();
Message stub = (Message) UnicastRemoteObject.exportObject(server, 0,
new SslRMIClientSocketFactory(),
new SslRMIServerSocketFactory());
Registry registry = LocateRegistry.getRegistry();
/*I try to create from within the application the registry but still got erros.
Registry registry = LocateRegistry.createRegistry(0 ,
new SslRMIClientSocketFactory(),
new SslRMIServerSocketFactory());
*/
registry.rebind("Mensaje", stub);
System.out.println("MensajeCall bound");
}catch (Exception error){
System.err.println("MessageServer exception:");
error.printStackTrace();
}
}
public void connect(MessageC c){
try {
System.out.println("Client " + c.getName() + " connected.");
c.connected();
}
catch (RemoteException re) {
System.out.println("Remote Exception: " + re.getMessage());
}
}
public void disconnect(MessageC c){
try {
System.out.println("Client " + c.getName() + " disconnected.");
c.disconnected();
}
catch (RemoteException re) {
System.out.println("Remote Exception: " + re.getMessage());
}
}
}
MY CLIENT CODE
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.io.Serializable;
import java.rmi.*;
import java.rmi.server.*;
import javax.rmi.ssl.SslRMIClientSocketFactory;
public class MessageClient implements MessageC, Serializable{
String clientName;
public MessageClient(){
clientName = "Objeto!";
}
public String getName(){
return clientName;
}
public static void main(String args[]) {
String name = "Mensaje";
try {
System.setProperty("javax.net.ssl.trustStore", "./truststore");
MessageClient mc = new MessageClient();
//The next line is to enable callbacks from Server ->(to)-> Client
UnicastRemoteObject.exportObject(mc);
Registry registry = LocateRegistry.getRegistry("localhost", 0,
new SslRMIClientSocketFactory());
Message comp = (Message) registry.lookup(name);
comp.connect(mc);
comp.disconnect(mc);
} catch (Exception e) {
System.err.println("MessageClient exception:");
e.printStackTrace();
}
}
public void connected(){
System.out.println("Connection established.");
}
public void disconnected(){
System.out.println("Connection ended.");
}
}
And that's my code, now the error is:
MessageClient exception:
java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is:
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:286)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:184)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:322)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at MessageClient.main(MessageClient.java:28)
Caused by: javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:817)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at java.io.DataOutputStream.flush(DataOutputStream.java:106)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:211)
... 4 more
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:333)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
... 11 more
Now I put the debug property on the Server side and this is what happens:
keyStore is : ./store
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : duke
chain [0] = [
[
Version: V3
Subject: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 135626715750840614278824185856036897813820093245374359954755429612877478476274818522079817238645726794949030274625255360008643595083686709777082893625454674176247197001792363060763462821576652164847203557743502753509633742595397731689005213582625932014809494516457085121814667440087131916457036468357018116877
public exponent: 65537
Validity: [From: Thu Nov 25 08:40:06 CET 2010,
To: Fri Nov 25 08:40:06 CET 2011]
Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US
SerialNumber: [ 4cee12d6]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 37 71 76 55 4C 19 2F 24 50 71 17 A7 E9 00 DE 98 7qvUL./$Pq......
0010: 4E 15 9C C2 50 F5 A4 BA A7 81 13 9E 17 A7 7B E6 N...P...........
0020: 43 52 43 C5 0A 0C AB 68 8A CB 72 77 D6 B2 5A AF CRC....h..rw..Z.
0030: 14 A6 76 3E F3 6F 3E F4 E6 75 76 77 6B 0A 18 CA ..v>.o>..uvwk...
0040: 60 0A A2 8D DD 89 0F BE A9 FF 3A 1D 70 F7 80 B1 `.........:.p...
0050: BB 83 F1 58 15 AD 7E C7 35 D6 70 2A D0 24 4C 85 ...X....5.p*.$L.
0060: 31 65 FE 6F 11 47 FF 07 D0 F3 ED 5D 82 E8 65 2D 1e.o.G.....]..e-
0070: 43 62 08 E5 B2 FD E9 BA 98 32 F5 70 80 D6 CF 4C Cb.......2.p...L
]
***
trustStore is: /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/cacerts
trustStore type is : jks
trustStore provider is :
init truststore
adding as trusted cert:
Subject: CN=Secure Global CA, O=SecureTrust Corporation, C=US
Issuer: CN=Secure Global CA, O=SecureTrust Corporation, C=US
Algorithm: RSA; Serial number: 0x75622a4e8d48a894df413c8f0f8eaa5
Valid from Tue Nov 07 20:42:28 CET 2006 until Mon Dec 31 20:52:06 CET 2029
adding as trusted cert:
Subject: EMAILADDRESS=personal-freemail@thawte.com, CN=Thawte Personal Freemail CA, OU=Certification Services Division, O=Thawte Consulting, L=Cape Town, ST=Western Cape, C=ZA
Issuer: EMAILADDRESS=personal-freemail@thawte.com, CN=Thawte Personal Freemail CA, OU=Certification Services Division, O=Thawte Consulting, L=Cape Town, ST=Western Cape, C=ZA
Algorithm: RSA; Serial number: 0x0
Valid from Mon Jan 01 01:00:00 CET 1996 until Fri Jan 01 00:59:59 CET 2021
//LOTS OF "adding as trusted cert"
trigger seeding of SecureRandom
done seeding SecureRandom
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
RMI TCP Connection(1)-192.168.1.2, setSoTimeout(7200000) called
RMI TCP Connection(1)-192.168.1.2, READ: SSL v2, contentType = Handshake, translated length = 81
*** ClientHello, TLSv1
RandomCookie: GMT: 1273948573 bytes = { 46, 211, 218, 200, 113, 172, 201, 187, 13, 183, 90, 107, 102, 146, 241, 174, 0, 39, 96, 3, 6, 175, 34, 165, 103, 23, 242, 129 }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
***
matching alias: duke
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
*** ServerHello, TLSv1
RandomCookie: GMT: 1273948573 bytes = { 154, 145, 97, 56, 171, 238, 131, 169, 77, 111, 55, 61, 163, 237, 202, 118, 231, 68, 78, 243, 22, 225, 196, 50, 243, 181, 179, 98 }
Session ID: {76, 239, 234, 157, 90, 116, 138, 8, 188, 114, 179, 78, 31, 56, 12, 127, 168, 117, 19, 13, 80, 83, 83, 218, 22, 95, 133, 13, 155, 66, 151, 32}
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
Extension renegotiation_info, renegotiated_connection: <empty>
***
Cipher suite: SSL_RSA_WITH_RC4_128_MD5
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 1024 bits
modulus: 135626715750840614278824185856036897813820093245374359954755429612877478476274818522079817238645726794949030274625255360008643595083686709777082893625454674176247197001792363060763462821576652164847203557743502753509633742595397731689005213582625932014809494516457085121814667440087131916457036468357018116877
public exponent: 65537
Validity: [From: Thu Nov 25 08:40:06 CET 2010,
To: Fri Nov 25 08:40:06 CET 2011]
Issuer: CN=Duke, OU=Java Software, O="Sun Microsystems, Inc.", L=Palo Alto, ST=CA, C=US
SerialNumber: [ 4cee12d6]
]
Algorithm: [SHA1withRSA]
Signature:
0000: 37 71 76 55 4C 19 2F 24 50 71 17 A7 E9 00 DE 98 7qvUL./$Pq......
0010: 4E 15 9C C2 50 F5 A4 BA A7 81 13 9E 17 A7 7B E6 N...P...........
0020: 43 52 43 C5 0A 0C AB 68 8A CB 72 77 D6 B2 5A AF CRC....h..rw..Z.
0030: 14 A6 76 3E F3 6F 3E F4 E6 75 76 77 6B 0A 18 CA ..v>.o>..uvwk...
0040: 60 0A A2 8D DD 89 0F BE A9 FF 3A 1D 70 F7 80 B1 `.........:.p...
0050: BB 83 F1 58 15 AD 7E C7 35 D6 70 2A D0 24 4C 85 ...X....5.p*.$L.
0060: 31 65 FE 6F 11 47 FF 07 D0 F3 ED 5D 82 E8 65 2D 1e.o.G.....]..e-
0070: 43 62 08 E5 B2 FD E9 BA 98 32 F5 70 80 D6 CF 4C Cb.......2.p...L
]
***
*** ServerHelloDone
RMI TCP Connection(1)-192.168.1.2, WRITE: TLSv1 Handshake, length = 710
RMI TCP Connection(1)-192.168.1.2, READ: TLSv1 Alert, length = 2
RMI TCP Connection(1)-192.168.1.2, RECV TLSv1 ALERT: fatal, certificate_unknown
RMI TCP Connection(1)-192.168.1.2, called closeSocket()
RMI TCP Connection(1)-192.168.1.2, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
RMI TCP Connection(1)-192.168.1.2, called close()
RMI TCP Connection(1)-192.168.1.2, called closeInternal(true)
MensajeCall bound
//AND THE SAME THING REPEATS LIKE 5 OR 6 TIMES
I'm very confused, I follow the tutorials and always fails. What do you think or what am I doing wrong? Is it my code? Is it the keys? Can you tell me the best way to create the keystore and truststore and certs.
Thanks !