I beefed up the Smack 3.1.0-based test client a bit, reinstalled openfire completely, properly certificate the server’s certificature (via external CA), but now I’m getting:
==> warn.log <==
2009.04.09 12:39:38 Closing session due to exception: (SOCKET, R: /127.0.0.1:39855, L: /127.0.0.1:5222, S: 0.0.0.0/0.0.0.0:5222)
org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.Exception: Disallowed character (Hexdump: 14 03 01 00 01 01 16 03 01 00 20 B6 39 30 79 68 02 07 8F 6F 4B 29 58 37 C8 87 2B 45 35 9E BC F5 CA 3D 41 9B 9D 66 03 2E 8E BE B8)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecF ilter.java:170)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilt erChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceive d(AbstractIoFilterChain.java:648)
at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java :239)
at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(Execut orFilter.java:283)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.Exception: Disallowed character
at org.jivesoftware.openfire.nio.XMLLightweightParser.read(XMLLightweightParser.ja va:211)
at org.jivesoftware.openfire.nio.XMPPDecoder.doDecode(XMPPDecoder.java:32)
at org.apache.mina.filter.codec.CumulativeProtocolDecoder.decode(CumulativeProtoco lDecoder.java:133)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecF ilter.java:163)
… 9 more
And the client complains that:
Logging into tester@localhost
java.net.SocketException: Socket closed
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:99)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at sun.nio.cs.StreamEncoder$CharsetSE.writeBytes(StreamEncoder.java:336)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlushBuffer(StreamEncoder.java:404)
at sun.nio.cs.StreamEncoder$CharsetSE.implFlush(StreamEncoder.java:408)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:152)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:213)
at java.io.BufferedWriter.flush(BufferedWriter.java:236)
at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:259)
at org.jivesoftware.smack.PacketWriter.access$000(PacketWriter.java:40)
at org.jivesoftware.smack.PacketWriter$1.run(PacketWriter.java:87)
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 2
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.j ava:86)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:495)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:433)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:877)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImp l.java:1089)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:11 16)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:11 00)
at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:12 58)
at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:313)
at org.jivesoftware.smack.PacketReader.access$000(PacketReader.java:44)
at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:76)
Connection is NOT using TLS and therefore is: NOT secure.
java.lang.NullPointerException
at org.jivesoftware.smack.SASLAuthentication.send(SASLAuthentication.java:532)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:130)
at org.jivesoftware.smack.sasl.SASLMechanism.authenticate(SASLMechanism.java:92)
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java: 308)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
at TestClient.main(TestClient.java:56)
No response from the server.:
at org.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication .java:74)
at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java: 345)
at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:395)
at TestClient.main(TestClient.java:56)
The Test Client is:
public static void main(String[] args) {
System.setProperty("javax.net.ssl.keyStore", KEYSTORE_PATH);
System.setProperty("javax.net.ssl.trustStore", TRUSTSTORE_PATH);
System.setProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD);
System.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD);
ConnectionConfiguration config = new ConnectionConfiguration(SERVER, 5222);
// config.setCompressionEnabled(true);
config.setCompressionEnabled(false);
config.setSecurityMode(SecurityMode.enabled);
config.setSASLAuthenticationEnabled(true);
// config.setSASLAuthenticationEnabled(false);
config.setKeystorePath(KEYSTORE_PATH);
config.setKeystoreType(“jks”);
config.setTruststorePath(TRUSTSTORE_PATH);
config.setTruststorePassword(TRUSTSTORE_PASSWORD);
config.setTruststoreType(“jks”);
config.setSecurityMode(SecurityMode.required);
SASLAuthentication.supportSASLMechanism(“PLAIN”, 2);
SASLAuthentication.supportSASLMechanism(“DIGEST-MD5”, 1);
SASLAuthentication.supportSASLMechanism(“EXTERNAL”, 0);
System.out.println("Logging into " + USERNAME + “@” + SERVER);
try {
XMPPConnection conn1 = new XMPPConnection(config);
conn1.connect();
String usingTLS = (conn1.isUsingTLS() == true) ? “” : " NOT ";
String secure = (conn1.isSecureConnection() == true) ? “” : " NOT ";
System.out.println("Connection is "
+ usingTLS
+ "using TLS and therefore is: "
+ secure
+ “secure.”);
Thread.sleep(3 * 1000); // Something about timing in the forums
conn1.login(USERNAME, PASSWORD, “smack test client”);
System.out.println(“Logged " + USERNAME + “@” + SERVER + " in.”);
Thread.sleep(15 * 1000); //leave it connected for a bit, then disconnect.
conn1.disconnect();
System.out.println("Disconnected " + USERNAME + “@” + SERVER);
} catch (XMPPException xe) {
// TODO Auto-generated catch block
xe.printStackTrace();
} catch (InterruptedException ie) {
// TODO Auto-generated catch block
ie.printStackTrace();
}
}
Again, everything works as expected against the server when not configured to require Client X.509 Certificates. I even went through the effort of installing jabberd and configuring it under ‘verify-mode: 7’, which, near as I can tell, is the same thing as ‘xmpp.client.cert.policy’=‘needed’.
In this case, jabberd complains that:
Apr 9 13:12:11 jabberd/c2s[29547]: [8] [10.10.10.10, port=40668] connect
Apr 9 13:12:13 jabberd/c2s[29547]: [8] [10.10.10.10, port=40668] error: SSL handshake error (error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not return a certificate)
Apr 9 13:12:13 jabberd/c2s[29547]: [8] [10.10.10.10, port=40668] disconnect jid=unbound, packets: 0
Is there some other setting that’s required to make sure that the certificate is being sent over the wire? It doesn’t look like it is. (If the handshake debug messages could be beefed up that would be helpful, too.)