Apr 7, 2009 6:36 AM
Openfire+Spark - Client X.509/PKI Certificate Support
-
Like (0)
Hi-
How does the Spark client support Client-side X.509. E.g., what properties do I need to set to get it to recognize a keystore and keystorePassword or prompt for keystore password? (I'm running Spark 2.5.8 against Openfire 3.6.3.)
Server-side SSL Certification is working fine. I have the (self-issued) CA Certificate in both /opt/openfire/resources/security/truststore and /opt/openfire/resources/security/client.truststore; this CA issues both the server and client certificates. I have a user-based keystore in ~/.keystore (contains mykey and the CA certificate).
This: http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/ssl-guid e.html
deals with openfire (server-side) configuration and not client-side configuration, so is not of much help w/r/t Spark.
I have set the various system properties on the server:
Other posts have posed the question, but there's no complete guide on HOW TO do this.
E.g.,
- http://www.igniterealtime.org/community/message/137320#137320
- http://www.igniterealtime.org/community/message/176779#176779
- http://www.igniterealtime.org/community/message/113186#113186
- http://www.igniterealtime.org/community/message/168691#168691
- http://www.igniterealtime.org/community/message/186321#186321
- http://www.igniterealtime.org/community/message/157890#157890
- http://www.igniterealtime.org/community/message/158460#158460
Would it be possible to put together an end-to-end HOW TO on this? For both Server-side and Client-side configuration?
Thanks,
Kevin
Forgot to note that 'xmpp.socket.ssl.client.truststore' was set. - vargok
First off, The 2.5.8 release dosnt have PKI support, I added that support after the release, so its in SVN. When Jive does the next release the code will be there. I think the 2.6.0 beta has everything needed in there. There is a tab in preferences for setting up PKI stuff. Not many people (read: close to 0) are using it, so there might be some bugs lurking in there. I never did much with the keystore format, but there is some basic support for it (I use the PKCS#11 modules)
OK, I pulled down the beta2 of Spark, and still having pretty much the same issue. I've set things in the UI for PKI, and verified that it is reading the keystore -- wrong value for password shows:
$ /opt/spark/Spark
ls: /opt/spark/lib/windows: No such file or directory
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:768)
at java.security.KeyStore.load(KeyStore.java:1150)
at org.jivesoftware.smack.ServerTrustManager.<init>(ServerTrustManager.java:63)
at org.jivesoftware.smack.XMPPConnection.proceedTLSReceived(XMPPConnection.java:13 67)
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)
Whereas the correct value gives no errors. I've got the right certificates marked the right way in all the keystores -- client side key/trust store uses same file, has the CA certificate (trusted) and the client certificate as 'mykey'. The server keystore and truststores have the CA certificate (trusted).
However, when I try to connect, I end up with an odd handshake error on the server side:
SocketAcceptorIoProcessor-0.0, fatal error: 80: problem unwrapping net record
java.lang.RuntimeException: Delegated task threw Exception/Error
SocketAcceptorIoProcessor-0.0, SEND TLSv1 ALERT: fatal, description = internal_error
SocketAcceptorIoProcessor-0.0, WRITE: TLSv1 Alert, length = 2
java.lang.RuntimeException: Delegated task threw Exception/Error
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(Unknown Source)
at javax.net.ssl.SSLEngine.unwrap(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.unwrap0(SSLHandler.java:658)
at org.apache.mina.filter.support.SSLHandler.unwrapHandshake(SSLHandler.java:614)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:493)
at org.apache.mina.filter.support.SSLHandler.messageReceived(SSLHandler.java:306)
at org.apache.mina.filter.SSLFilter.messageReceived(SSLFilter.java:392)
[...]
Caused by: java.lang.NullPointerException
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateRequest.<init>(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientHello(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.doTasks(SSLHandler.java:686)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:486)
... 16 more
I added the end-entity client certificate explicitly on the server-side (and restarted), but that changed nothing.
I've attached various logging and other information (slightly redacted) to this post. Any help would be most appreciated. I've turned on SSL debug, but nothing of value is really provided. The only thing I note is that I never see the client'certificate's Subject appear anywhere. However, it doesn't appear to be a trust issue -- that's usually pretty obvious in my experience thus far anyway.
Even setting client certification to Optional, I'm still getting handhake failures:
xmpp.client.cert.policy | wanted |
xmpp.client.certificate.verify | false |
xmpp.client.certificate.verify.chain | false |
xmpp.client.certificate.verify.root | false |
xmpp.client.certificate.verify.validity | false |
==> error.log <==
2009.04.08 15:29:00 [org.jivesoftware.openfire.nio.ConnectionHandler.exceptionCaught(ConnectionHand ler.java:111)]
java.lang.RuntimeException: Delegated task threw Exception/Error
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(Unknown Source)
at javax.net.ssl.SSLEngine.unwrap(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.unwrap0(SSLHandler.java:658)
at org.apache.mina.filter.support.SSLHandler.unwrapHandshake(SSLHandler.java:614)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:493)
at org.apache.mina.filter.support.SSLHandler.messageReceived(SSLHandler.java:306)
at org.apache.mina.filter.SSLFilter.messageReceived(SSLFilter.java:392)
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.common.support.AbstractIoFilterChain$HeadFilter.messageReceived (AbstractIoFilterChain.java:499)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.fireMessageReceived(Abstra ctIoFilterChain.java:293)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.read(SocketIoProcessor.j ava:228)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.process(SocketIoProcesso r.java:198)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.access$400(SocketIoProce ssor.java:45)
at org.apache.mina.transport.socket.nio.SocketIoProcessor$Worker.run(SocketIoProce ssor.java:485)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateRequest.<init>(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientHello(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.doTasks(SSLHandler.java:686)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:486)
... 16 more
This was triggered via 3.10 of Smack with a simple connection test client:
XMPPConnection conn1 = new XMPPConnection(server);
conn1.connect();
conn1.login(username, password);
System.out.println("Logged " + username + "@" + server + " in.");
Thread.sleep(15 * 1000);
conn1.disconnect();
Disabling client cert totally, allows the handshake to proceed.
I also injected a stack trace into the server code (downloaded source, added a (new Exception()).printStackTrace()), but that doesn't show anything of any more use (but that's why the above ConnectionHandler shows line 111 instead of 110):
java.lang.Exception: Debugging SSL/TLS Client-Cert con problems.
at org.jivesoftware.openfire.nio.ConnectionHandler.exceptionCaught(ConnectionHandl er.java:110)
at org.apache.mina.common.support.AbstractIoFilterChain$TailFilter.exceptionCaught (AbstractIoFilterChain.java:564)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextExceptionCaught(Ab stractIoFilterChain.java:345)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1000(AbstractIoFilt erChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.exceptionCaugh t(AbstractIoFilterChain.java:643)
at org.apache.mina.common.IoFilterAdapter.exceptionCaught(IoFilterAdapter.java:75)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextExceptionCaught(Ab stractIoFilterChain.java:345)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1000(AbstractIoFilt erChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.exceptionCaugh t(AbstractIoFilterChain.java:643)
at org.apache.mina.common.IoFilterAdapter.exceptionCaught(IoFilterAdapter.java:75)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextExceptionCaught(Ab stractIoFilterChain.java:345)
at org.apache.mina.common.support.AbstractIoFilterChain.access$1000(AbstractIoFilt erChain.java:53)
at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.exceptionCaugh t(AbstractIoFilterChain.java:643)
at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java :243)
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)
I've not yet tried the SVN branches.
I'm totally lost on what's mis-configured. If it matters, i'm using embedded DB.
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.)
Debugging SSL is hard to do, since you cant easily snoop the traffic. A very helpful tool Ive used for this is ssldump (a friend of the tcpdump utility). It will give you details of the SSL handshake (as much as it can). If you have the private keys invovled it can even do decryption for certain types of connections.
Also, this page is very helpful: http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/ReadDebug.html In essence, set the java commandline option -Djavax.net.debug=all and you will see LOTS of output. But it shows the certificate selection process, etc. Try that with Spark, and see if there is anything useful there. Its possible the server certificate issuer (itself, if self-signed) is not trusted by the client. If the client does not trust the server cert, it will not attempt to continue the SSL handshake. Sadly the error handling/reporting in spark isnt great- I never really perfected it since no one ended up using my changes.
I had been using the SSL debug portion of javax.net.debug, but that hadn't given me really anything different. It still results, at the end with:
Smack Packet Reader (0), READ: TLSv1 Handshake, length = 1836
Smack Packet Reader (0), handling exception: javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 2
Smack Packet Reader (0), SEND TLSv1 ALERT: fatal, description = unexpected_message
Padded plaintext before ENCRYPTION: len = 18
0000: 02 0A 36 C0 76 94 53 E7 E9 88 ED C2 86 5F 24 19 ..6.v.S......_$.
0010: F1 EC ..
Smack Packet Reader (0), WRITE: TLSv1 Alert, length = 18
[Raw write]: length = 23
0000: 15 03 01 00 12 4C 7A 7F 67 57 A5 1E DC A2 A8 BE .....Lz.gW......
0010: A3 B2 08 9D 48 0F 17 ....H..
Smack Packet Reader (0), called closeSocket()
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.writeBytes(StreamEncoder.java:202)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
at java.io.BufferedWriter.flush(BufferedWriter.java:236)
at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:274)
at org.jivesoftware.smack.PacketWriter.access$000(PacketWriter.java:40)
at org.jivesoftware.smack.PacketWriter$1.run(PacketWriter.java:87)
On the Spark side, and:
2009.04.14 07:36:25 Closing session due to exception: (SOCKET, R: /10.10.10.179:48286, L: /10.10.10.179:5222, S: 0.0.0.0/0.0.0.0:5222)
org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.Exception: Disallowed character (Hexdump: 16 03 01 00 20 78 5F 5C 9F E7 90 A5 30 00 BE 6F 33 8C 14 6B 77 D4 FE A1 EB 2C D7 75 A2 A1 A3 CA 41 0E 96 BA 81)
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
on the openfire side.
I've tried JVMs 1.5 and 1.6 to the same result.
How does Spark choose what key to use from the keystore? It just defaults to (only) use the "mykey" entry? Does it attempt to find an alias based on the username of the jabber user? I've tried various aliases, but I still don't see any client certificates being sent across the wire anywhere.
The server certificate is issued by the same CA sa the client certificate, so all the crypto works out. And the non-Client-X509-Required handshake works just fine, so I don't think it's a trust issue -- the PKIX trust errors are pretty clear (as far as they go).
(I did just try to pull down the Spark SVN source, but the buld script isn't working for some reason. The source/target for 1.6 were refused by `javac' for some reason; removing those allowed the compile to proceed, but still results in lots of class resolution issues. There doesn't appear to be a "how_to_build" for the top level, only the plugins.)
OK, here we go. I finally got ssldump running:
09:15 root ssldump-0.9b3> ./ssldump -i lo
New TCP connection #1: host1(62499) <-> host1(5222)
1 1 1.1957 (1.1957) C>S SSLv2 compatible client hello
Version 3.1
cipher suites
TLS_RSA_WITH_RC4_128_MD5
SSL2_CK_RC4
TLS_RSA_WITH_RC4_128_SHA
Unknown value 0x2f
Unknown value 0x33
Unknown value 0x32
TLS_RSA_WITH_3DES_EDE_CBC_SHA
SSL2_CK_3DES
TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_DES_CBC_SHA
SSL2_CK_DES
TLS_DHE_RSA_WITH_DES_CBC_SHA
TLS_DHE_DSS_WITH_DES_CBC_SHA
TLS_RSA_EXPORT_WITH_RC4_40_MD5
SSL2_CK_RC4_EXPORT40
TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
1 2 1.1986 (0.0028) S>C Handshake
ServerHello
Version 3.1
session_id[32]=
49 e4 8c af d9 98 09 e8 92 15 06 95 62 ab 38 b0
d9 17 4c df 0c de df de 8f a5 ca 00 33 df 2d 27
cipherSuite TLS_RSA_WITH_RC4_128_MD5
compressionMethod NULL
Certificate
CertificateRequest
certificate_types rsa_sign
certificate_types dss_sign
ServerHelloDone
1 3 1.3083 (0.1096) C>S Handshake
Certificate
ClientKeyExchange
1 4 1.3488 (0.0405) C>S ChangeCipherSpec
ERROR: Length mismatch
Length mismatch? Could the client certificate not be "valid" for the right "purpose"?
Certificate purposes:
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
Netscape SSL server : Yes
Netscape SSL server CA : No
S/MIME signing : Yes
S/MIME signing CA : No
S/MIME encryption : Yes
S/MIME encryption CA : No
CRL signing : Yes
CRL signing CA : No
Any Purpose : Yes
Any Purpose CA : Yes
OCSP helper : Yes
OCSP helper CA : No
Key type/length OK?
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (2048 bit)
Modulus (2048 bit):
I'm guessing it all results from something in:
2009.04.14 09:16:32 Closing session due to exception: (SOCKET, R: /10.10.10.179:62501, L: /10.10.10.179:5222, S: 0.0.0.0/0.0.0.0:5222)
org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.Exception: Disallowed character (Hexdump: 15 03 01 00 12 27 1A 48 AF D4 54 8E 76 AC 4E 72 89 1B A0 9C E0 1A D2)
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
but I can't figure out where that's coming from, exactly. And much less so how to resolve it. Presumably the '00' is the invalid character, but...
Turning on full debugging on the server-side shows that it is the "null cert chain" error:
SocketAcceptorIoProcessor-0.0, READ: TLSv1 Handshake, length = 269
*** Certificate chain
***
SocketAcceptorIoProcessor-0.0, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
SocketAcceptorIoProcessor-0.0, SEND TLSv1 ALERT: fatal, description = bad_certificate
SocketAcceptorIoProcessor-0.0, WRITE: TLSv1 Alert, length = 2
SocketAcceptorIoProcessor-0.0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
SocketAcceptorIoProcessor-0.0, called closeOutbound()
SocketAcceptorIoProcessor-0.0, closeOutboundInternal()
[Raw write]: length = 7
0000: 15 03 01 00 02 02 2A ......*
SocketAcceptorIoProcessor-0.0, called closeInbound()
SocketAcceptorIoProcessor-0.0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
SocketAcceptorIoProcessor-0.0, called closeOutbound()
SocketAcceptorIoProcessor-0.0, closeOutboundInternal()
But, again, I don't know how the client is working to access the keystore. There is no place to set a 'keystore password' in the client UI the way there is for a truststore password. Obviously setting the default parameters via -Djavax.net.ssl.keyStore and so on aren't doing much.
Access to the keystore is handled via callback handler, so it would prompt the user when logging in (it was designed for smartcards, so it would say "Enter pin for your smartcard" or something like it).
Then java decides which client cert to use based on the list of CA's presented from the server. So if the server provides no acceptable CA's, the client wont know which cert to use.
Then the fact that I'm not seeing any sort of callback UI to enter the password implies that the *server* isn't doing the right thing? Even though I have CA Certificate(s) installed in the client.truststore?
Is there anything missing from this:
http://www.igniterealtime.org/community/thread/32759
that needs to be done on the server-side?
Are there any specific bits that need to be set in the CA certificate that might not ordinarily be set in an `OpenSSL' generated CA Certificate?
I dont think so, but lets try something.
Please run this command:
openssl s_client -prexit -connect yourjabberserverhostname:5223
When this connects, it should do several things:
Display the certificate subject name the server is using
Show the certificate chain the server is using
Show the server certificate
Show the list of acceptable client certificate CAs
Show some info about the specific connection
See if the server is actually sending a list of client CA's.
Hi Slushpuppie. Thanks for continuing to work with me on this. I'm prettymuch stumped at this point.
But yeah, that's basically what I'm suggesting -- there's no client-CA list being offered by the server, so the TLS is server-only.
I'm not running 5223, only TLS on 5222, but:
$ openssl s_client -prexit -connect localhost:5222
CONNECTED(00000003)
6550:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:188:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 124 bytes
---
New, (NONE), Cipher is (NONE)
Compression: NONE
Expansion: NONE
---
I have two CAs listed in the client.truststore, both "trustedCertEntry"s. I've tried both leaving the sys prop for client.trustore blank, and explicitly setting it to: /opt/openfire/resources/security/client.truststore.
Running `s_client' in `-starttls xmpp' mode yields a successful (non-client) handshake from all appearances/no errors on the server side:
$ openssl s_client -prexit -connect localhost:5222 -starttls xmpp
CONNECTED(00000003)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 455 bytes and written 114 bytes
---
New, (NONE), Cipher is (NONE)
Compression: NONE
Expansion: NONE
---
In any event, i'm certainly not getting prompted for a call-back password box, as I've seen from Java on other client SSL-enabled apps.
--------
I switched on :5223, and tried to connect with both `s_client' and spark 2.6.0b2, and while the behavior was slightly different, it didn't work, and I still get:
---
No client certificate CA names sent
---
SSL handshake has read 2645 bytes and written 1446 bytes
---
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 2048 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : EDH-RSA-DES-CBC3-SHA
Session-ID: 49EC71B1A0D238E05CEABF61C23F1F9D019CDE93E404EBD90B7BD3C032F289C3
Session-ID-ctx:
Master-Key: 9118A0114F22471F0C83C839E48BEE8DA0BD0379E9863C013BA4CDDB79BB222E7FFE980B7FC9989 6F1420E0B55EFD627
Key-Arg : None
Start Time: 1240232369
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
However, on :5223, I do get the following error in the server logs, presumably it's not finding/opening the "client.truststore" properly:
[...]
Caused by: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at sun.security.validator.PKIXValidator.<init>(Unknown Source)
at sun.security.validator.Validator.getInstance(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.getValidator(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ServerHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.doTasks(SSLHandler.java:686)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:486)
... 16 more
Caused by: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at java.security.cert.PKIXParameters.setTrustAnchors(Unknown Source)
at java.security.cert.PKIXParameters.<init>(Unknown Source)
at java.security.cert.PKIXBuilderParameters.<init>(Unknown Source)
... 29 more
Thanks,
Kevin
(grr... the system ate my first attempt at this reply -- some sort of authentication mix-up.)
The openssl s_client command wont work with starttls on xmpp (it dosnt really understand the protocol) so you will want to have port 5223 (SSL) enabled to test with it. Your output confirms my suspicion, that the server is not reading the list of CA's needed.
So lets make sure we have it all right:
You have the CA you wish to authenticate clients with in the client.truststore file (imported using the keytool command)
The location of this file is specified in the property xmpp.socket.ssl.client.truststore
The password to the client.truststore file is either "changeit" or specified in xmpp.socket.ssl.client.trustpass
The property xmpp.client.tls.policy is set to either "wanted" or "needed" (anything else sets it to "disabled")
The property xmpp.client.certificate.crl is set, and points to a file with all the PEM encoded CRL's of every CA in client.truststore
If the crl file specified, they
- They *must* be there
- They *must* be valid (not expired)
If the file is not found (or the property is null, etc) then CRLs will not be used. Debug output will say whats going on, just look for the lines prefixed with "ClientTrustManager: "
OCSP is also possible if you have an OCSP responder.
Hi. Yes, those properties have always been set (except CRL; I've tried that, though, and it doesn't have much effect... I'll try it again):
xmpp.socket.ssl.client.trustpass | changeit |
xmpp.socket.ssl.client.truststore | /opt/openfire/resources/security/client.truststore |
and
xmpp.client.cert.policy | needed |
xmpp.client.certificate.accept-selfsigned | true |
xmpp.client.certificate.verify | true |
xmpp.client.certificate.verify.chain | true |
xmpp.client.certificate.verify.root | true |
xmpp.client.certificate.verify.validity | true |
xmpp.client.tls.policy | required |
just to be sure, I went ahead and generated it again:
xmpp.client.certificate.crl | /opt/openfire/resources/security/CRLs.pem |
But still:
---
No client certificate CA names sent
---
SSL handshake has read 2645 bytes and written 1446 bytes
---
I even turned on accept-selfsigned, as you see, just to make it easier.
The truststore is valid and populated:
$ ls -ltr /opt/openfire/resources/security/client.truststore
-rw-r--r-- 1 daemon daemon 1772 Apr 14 10:41 /opt/openfire/resources/security/client.truststore
--
$ keytool -keystore /opt/openfire/resources/security/client.truststore -list -storepass changeit
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 2 entries
test_ca, Apr 9, 2009, trustedCertEntry,
Certificate fingerprint (MD5): 47:D2:6C:5E:B3:20:4C:8A:2B:62:6F:8C:A8:4D:30:F2
test_ca_2, Apr 14, 2009, trustedCertEntry,
Certificate fingerprint (MD5): 76:63:3B:28:57:0A:DC:77:A0:E2:3A:EF:1C:18:39:3A
have you enabled the debug log? Please look for anything from the ClientTrustManager. Often some of these messages will only happen on the first SSL/TLS session since the server started up- so perhaps shut the server down, clear the logs, start it up, and watch from the beginning.
You mean this in conf/openfire.xml, right?
<log>
<debug>true</debug>
</log>
If so, then yes. All I'm getting after normal startup:
2009.04.20 11:17:09 Started server (unencrypted) socket on port: 5269
2009.04.20 11:17:09 Started plain (unencrypted) socket on port: 5222
2009.04.20 11:17:09 Started SSL (encrypted) socket on port: 5223
is:
==> /opt/openfire/logs/error.log <==
2009.04.20 11:18:07 [org.jivesoftware.openfire.nio.ConnectionHandler.exceptionCaught(ConnectionHand ler.java:110)]
java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(Unknown Source)
at javax.net.ssl.SSLEngine.unwrap(Unknown Source)
at org.apache.mina.filter.support.SSLHandler.unwrap0(SSLHandler.java:658)
at org.apache.mina.filter.support.SSLHandler.unwrapHandshake(SSLHandler.java:614)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:493)
[...]
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)
... 8 more
from an `s_client' connect.
There is a separate log file for debug messages. Same directory, named debug.log
I missed the <enabled .../>. However, nothing about ClientTrustManager:
$ grep -i ClientTrustManager *.log
$ grep -i Client *.log
Binary file debug.log matches
error.log: at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
error.log: at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
error.log: at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientCertificate(Unknown Source)
error.log: at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
error.log: at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkClientTrusted(Unknown Source)
error.log: at com.sun.net.ssl.internal.ssl.ServerHandshaker.clientCertificate(Unknown Source)
debug.log got binary data after attempted `s_client' connect. The line from debug.log that matches is just:
2009.04.20 11:31:11 Set parameter http.useragent = Jakarta Commons-HttpClient/3.1
I do see the null cert chain in the debug log now, though:
[...]
Caused by: javax.net.ssl.SSLHandshakeException: null cert chain
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
[...]
Hi,
I got exactly the same problem. Well I'm using Smack in Version 3.1.0 instead of Spark, but i think this is not of any relevance.
I've debuged the TLS Handshake with -Djavax.net.debug=all.
There I was able to see that the Handshake aborts at the very end of the Handshake, they even have the Mastersecret.
I've appended the debug log, maybe its helpfull.
Server quits with:
2009.04.21 15:03:26 NIOConnection: startTLS: using c2s ...
|
The crl File is right in place. I don't know why Openfire doesn't find it.
regards Daniel
Hi Daniel,
Note that Java expects DER-encoded CRLs, not PEM-encoded. I note your file is .pem (mine was originally... somewhere it complained about invalid CRL file and I was reminded). You can convert easily with `openssl x509'... something like `openssl x509 -inform pem -in crl.pem -outform der -out crl.der'. Also, make sure that the file is properly 'chown'd or 'chgrp'd to the right user -- i.e., if it's root:root 400, then the jabber server user probably can't read it. If that's all in place, not sure what else, except make sure the CRL file system property is correct.
Kevin
Hi Kevin,
Thank you for your advice, I finally managed to implement the CRL. But the problem is still there. The same one I've metioned above. In another thread I read that the "null certificate chain error" occurs, because the client does not send his certificate. Maybe slushpupie knows how to handle that?
regards
Daniel
Glad to hear you got a bit further, but yeah, the CRL isn't the only problem.
Based on his advice, I could confirm that the server is not "offering" any CA Certificates on the connection. I'm presuming there's some mis-configuraiton that is not allowing the Java SSL stack to trigger the client certificate portion, but I can't figure out what it is. I have to guess that it's some combination of settings that others have enabled and I'm missing, but I don't know _which_ ones they are.
I have been seeing the error about "no trustAnchors" (the trustAnchors parameter must be non-empty), which seems to imply it's not actually reading the client.truststore file properly. But I haven't had time to get back to it over the past couple of days. I'm afraid it'll come down to further instrumenting the openfire server, or attempting to run it from a debugger.
Out of curiosity, what deployment package are you using? I'm deploying to RedHat EL5 via the RPM. I doubt that would be the problem, but...
So, I just installed the .deb on a debian system (obviously), and reconfigured things from scratch using Openfire 3.6.3 and the beta2 of Spark 2.6.0. There's nothing really all that different from an end-point situation, but I do see the server indicating acceptible client CA certificates when using `openssl s_client':
openssl s_client -connect localhost:5223 -prexit -showcerts -debug -CAfile ~/certificates/ca/cacert.pem
[...]
---
Acceptable client certificate CA names
[***CA 1***]
[***CA 2***]
---
SSL handshake has read 2494 bytes and written 231 bytes
---
So maybe I'll go back and try to not use the RPM on the other system and see if the .tar.gz, for instance works better, although clearly there are bigger system differences in play as well.
Again, Spark never tried anything with the keystore as far as I could tell, no UI-based callback or anything. I don't have my simple Smack test-client here, so I can't play around with that, but at least the server is offering.
Well I'm using Windows and a simple .exe file to install Openfire. I thing you're right, the server offers his certificate properly the only thing which is missing is the client's certificate which likely is not offered by the client. At least I think this is the problem. On client side the TLS Handshake works fine until the server closes the socket. So obviously the server doesn't get something he needs to have.
I forgot, right befor the socket gets closed, on server side (Closing session due to exception: (SOCKET, R: /192.168.0.135:2395, L: /192.168.0.135:5222, S: 0.0.0.0/0.0.0.0:5222)), there is an disallowed character exception in the warnlog.
| 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 |
So maybe the client trys to send something which the server doesn't understand?
By the way is there a way to display the ... 9 more error lines?
The server must say which CA's it will accept before the client offers any certificates. So when the server gets no certificate from the client during the handshake, it closes the connection.
However, the errors you posted seem different. Its like someone is trying SSL on a non-SSL port. Is your client set to use SSL or TLS? And what port number is it connecting to?
Well, on port 5223 of the Openfire Sever the OpenSSL connection test says:
openssl s_client -prexit -connect localhost:5223
CONNECTED(00000778)
depth=1 /C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
verify error:num=19:self signed certificate in certificate chain
verify return:0
---
Certificate chain
0 s:/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=server
i:/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
1 s:/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
i:/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
---
Server certificate
-----BEGIN CERTIFICATE-----
<Hash>
-----END CERTIFICATE-----
subject=/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=server
issuer=/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
---
No client certificate CA names sent
---
SSL handshake has read 2819 bytes and written 282 bytes
---
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : EDH-RSA-DES-CBC3-SHA
Session-ID: 49F5566FAD6B64E016B2577ABEA283CFB759583D564F8A1115D4476B8C92CB4
Session-ID-ctx:
Master-Key: CCB3E58B0F8A7FF98B9E7404C595BB8C2B45B8ADDBC717C93A5EECB31F4DDD73
3D7E89C7E480B6C75099FAC632DE06DA
Key-Arg : None
Start Time: 1240815215
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
</stream:stream>closed
---
Certificate chain
0 s:/C=DE/ST=State/L=Country/O=Organisation/OU=DANE/CN=pc03
i:/C=DE/ST=State/L=Country/O=Organisation/OU=DANE/CN=xmpp-ca/emailAddress=none
1 s:/C=DE/ST=State/L=Country/O=Organisation/OU=DANE/CN=xmpp-ca/emailAddress=none
i:/C=DE/ST=State/L=Country/O=Organisation/OU=DANE/CN=xmpp-ca/emailAddress=none
---
Server certificate
-----BEGIN CERTIFICATE-----
<Hash>
-----END CERTIFICATE-----
subject=/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=server
issuer=/C=DE/ST=State/L=Country/O=Organisation/OU=OU/CN=ca/emailAddress=none
---
No client certificate CA names sent
---
SSL handshake has read 2893 bytes and written 311 bytes
---
New, TLSv1/SSLv3, Cipher is EDH-RSA-DES-CBC3-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : EDH-RSA-DES-CBC3-SHA
Session-ID: 49F5566FAD6B64E016B2577ABEA283CFB759583D564F8A1115D4476B8C92CB41
Session-ID-ctx:
Master-Key: CCB3E58B0F8A7FF98B9E7404C595BB8C2B45B8ADDBC717C93A5EECB31F4DDD73
3D7E89C7E480B6C75099FAC632DE06DA
Key-Arg : None
Start Time: 1240815215
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
on port 5222 no certificates are offered:
openssl s_client -prexit -connect localho
st:5222
Loading 'screen' into random state - done
CONNECTED(00000778)
2052:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:.\ssl\s23_lib.c:188:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 124 bytes
---
New, (NONE), Cipher is (NONE)
Compression: NONE
Expansion: NONE
---
Anyway on both ports I'm not able to connect to the Server. I've already postet the Errors on port 5222, here are the errors on port 5223:
Server debug:
2009.04.27 09:07:39 ConnectionHandler: ... Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection? |
Client (Smack):
Connection failed. No response from server.
Is there a way to tell Smack to connect via TLS or SSL? I thought the SASLMechanism handles that?
Daniel
My experience has seen similar on the 'regular' TLS (5222) -- it doesn't actually do proper TLS as far as client auth at all, even when the SSL (5223) side does. That seems pretty odd, but I'm sure there are reasons for it the way the code is structured.
However, again, the client-side never realizes it and responds with anything. I've tried to use smack and spark both, to no avail. Trying smack on :5223 yeilds the same two errors you were seeing:
==> logs/debug.log <==
2009.04.27 09:13:12 ConnectionHandler:
javax.net.ssl.SSLHandshakeException: SSL handshake failed.
at org.apache.mina.filter.SSLFilter.messageReceived(SSLFilter.java:416)
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.common.support.AbstractIoFilterChain$HeadFilter.messageReceived (AbstractIoFilterChain.java:499)
at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:299)
at org.apache.mina.common.support.AbstractIoFilterChain.fireMessageReceived(Abstra ctIoFilterChain.java:293)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.read(SocketIoProcessor.j ava:228)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.process(SocketIoProcesso r.java:198)
at org.apache.mina.transport.socket.nio.SocketIoProcessor.access$400(SocketIoProce ssor.java:45)
at org.apache.mina.transport.socket.nio.SocketIoProcessor$Worker.run(SocketIoProce ssor.java:485)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java: 886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.EngineInputRecord.bytesInCompletePacket(EngineInpu tRecord.java:152)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:771 )
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:686)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:607)
at org.apache.mina.filter.support.SSLHandler.unwrap0(SSLHandler.java:658)
at org.apache.mina.filter.support.SSLHandler.unwrapHandshake(SSLHandler.java:614)
at org.apache.mina.filter.support.SSLHandler.handshake(SSLHandler.java:493)
at org.apache.mina.filter.support.SSLHandler.messageReceived(SSLHandler.java:306)
at org.apache.mina.filter.SSLFilter.messageReceived(SSLFilter.java:392)
... 14 more
I have:
config.setSecurityMode(SecurityMode.enabled);
and I tried:
config.setSecurityMode(SecurityMode.required);
with no change.
Just a note on SASL -- as I understand it, SASL is just authentication, which doesn't /really/ include the SSL/TLS stuff. I.e., SASL can be made to look at the results of the Handshake and use information from the client-authentication portion, but the TLS stuff all happens before SASL gets invoked. I could _easily_ be wrong.
If you got it to work with Debian, then I would take a very careful look at your settings in the database and config file. The only difference between the two packages is the packaging (the code dosnt change based on distro or anything).
Again, Spark will not prompt for any certs/keystores if the server dosnt say which CA's are acceptable. Thats not a bug in Spark (what is arguably a bug is not giving a useful message to the user, however, but thats different)
Right, but i got the debian-based installation to advertise CA's -- the same one I have a key/certificate in my keystore (under 'mykey' alias), but I do not get any sort of prompting. So, the server is definititely advertising (at least to s_client), but no callback is showing up.
And actually, I'm not sure if it matters if the keystore has a certificate signed by an advertised CA in terms of getting the callback... in theory the keystore isn't opened until the passphrase is provided, so the code can't know whether there is/n't a reasonable candidate until after such a callback happens, right?
Did anybody found something out? I'm still trying to fix this problem up. In case this will not work, does anybody have alternative ideas? I need to implement an encrpted and authenticated connection.
Thanks in advance
Daniel
OK, it's hard to be sure, but I *think* I've got it "working."
I could not get my simple login smack client working on :5223. Scanning through other forum postings noted that the Socket might not be right -- try using the default SSL Socket:
config.setSocketFactory(SSLSocketFactory.getDefault());
This moved me forward. However, the
So, with an empty client.truststore:
SocketAcceptorIoProcessor-1.0, fatal error: 80: problem unwrapping net record
java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
SocketAcceptorIoProcessor-1.0, SEND TLSv1 ALERT: fatal, description = internal_error
SocketAcceptorIoProcessor-1.0, WRITE: TLSv1 Alert, length = 2
valid client.truststore:
successful login; see client certificate in server's debug output
*HOWEVER* The callback stuff appears not to be working -- if I disable setting the default keystorePassword property, but have a CallbackHandler set, I still get:
Logging into tester@localhost
XMPPError connecting to localhost:5223.: remote-server-error(502) XMPPError connecting to localhost:5223.
-- caused by: java.net.SocketException: password can't be null
at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection. java:900)
at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1415)
at TestClient.main(TestClient.java:60)
Nested Exception:
java.net.SocketException: password can't be null
at javax.net.ssl.DefaultSSLSocketFactory.createSocket(SSLSocketFactory.java:156)
at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection. java:888)
at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1415)
at TestClient.main(TestClient.java:60)
Presumably this is because the default SSLSocketFactory is not passing out to callbacks. However, I've been completely unsuccessful finding any more useful documentation regarding what SSLSocketFactory to use with Smack. Is there an openfire specific SocketFactory? One that works with TLS as well?
Likewise, trying to use TLS (instead of SSL) on :5222 (or even :5223, which probably isn't expected to work) totally as we've seen before:
javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 2
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.j ava:86)
So, at this point, nothing has really worked:
o The RPM installed a somehow-broken implementation such that the server would not even advertize valid CAs;
- the tar.gz (and .deb) *did*, but
o none of the clients really work with the callback stuff.
- since there's some other stuff going on in Spark, it seems impossible to do anything but rely on the (broken?) callback handling.
o Of course, none of it works with TLS, only old-style SSL on :5223.
I still have to believe there is some other trick going on -- or are the PCKS#11 handling class(es) different from the JKS handling ones? I.e., could there be a difference in the callback propogation code in the JKS-handling one(s)?
--------------
Also: why it's trying to dial home:
2009.05.01 07:33:59 Retrying request
2009.05.01 07:33:59 Open connection to www.igniterealtime.org:80
2009.05.01 07:33:59 Closing the connection.
2009.05.01 07:33:59 Method retry handler returned false. Automatic recovery will not be attempted
I'm not sure. Can this be killed? Is it just the 'check for updates' piece?
-------------
My client is as follows, minus setting the properties to things like 'tester' and 'localhost':
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.setSASLAuthenticationEnabled(true);
// config.setSASLAuthenticationEnabled(false);
config.setKeystorePath(KEYSTORE_PATH);
config.setKeystoreType("jks");
config.setTruststorePath(TRUSTSTORE_PATH);
config.setTruststorePassword(TRUSTSTORE_PASSWORD);
config.setTruststoreType("jks");
config.setCallbackHandler(new CallbackHandler());
config.setSecurityMode(SecurityMode.enabled);
// config.setSecurityMode(SecurityMode.required);
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 1);
SASLAuthentication.supportSASLMechanism("EXTERNAL", 2);
// config.setSocketFactory(SSLSocketFactory.getDefault());
System.out.println("Logging into " + USERNAME + "@" + SERVER);
try {
XMPPConnection conn1 = new XMPPConnection(config, new CallbackHandler());
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();
}
}
Ive not done any work on Spark/Smack in quite a while, and others have. Its entirely possible the changes others have made broke the callback handling. Ive been pretty busy lately so I dont know if Ill have time to look at it soon either. As far as SSL vs TLS goes, its the same path through the code as far as the SSL negotiation is, so there should be no difference.
The difference between a JKS and a PKCS11 keystore to the client is none, since its using the pure keystore interface. The only real difference is where you get it from.
Sorry Ive not been much help lately, I just have not had the time to work on any of this.
I pulled down SVN an hour ago. I think the problem comes in around here:
[PacketReader:467]
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("starttls")) {
// Confirm the server that we want to use TLS
*I added this---> startTLSRequired = true;
connection.startTLSReceived(startTLSRequired);
}
else if (parser.getName().equals("required") && startTLSReceived) {
startTLSRequired = true;
}
I'm betting 'starttls' comes in as '<starttls/>' not '<starttls required="ture">' -- or some other similar construction that doesn't kick startTLSRequired 'high' before proceeding. Thus TLS never gets initialized. Presumably that's a bug: either the server isn't sending the right thing, or the client isn't implementing spec. `s_client' tells me that the server isn't *sending* anything inside <starttls/>:
[...]
00c0 - 74 72 65 61 6d 3a 66 65-61 74 75 72 65 73 3e 3c tream:features><
00d0 - 73 74 61 72 74 74 6c 73-20 78 6d 6c 6e 73 3d 22 starttls xmlns="
00e0 - 75 72 6e 3a 69 65 74 66-3a 70 61 72 61 6d 73 3a urn:ietf:params:
00f0 - 78 6d 6c 3a 6e 73 3a 78-6d 70 70 2d 74 6c 73 22 xml:ns:xmpp-tls"
0100 - 3e 3c 2f 73 74 61 72 74-74 6c 73 3e 3c 6d 65 63 ></starttls><mec
[...]
So, somewhere down the line things were adjusted. In any event, it finally gets into the Callback Code in XMPPConnection! It doesn't *work*, but it gets there! For some reason, it's invoking PasswordCallback#getPassword(); which has nothing to do with the CallbackHandler I set with #setCallbackHandler -- is in, my callbackHandler doesn't get invoked.
And it turns out that's because... yup; that's reverse ordered, too:
[XMPPClient:1221]
ks = KeyStore.getInstance(configuration.getKeystoreType());
try {
ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
pcb = new PasswordCallback("Keystore Password: ",false);
callbackHandler.handle(new Callback[]{pcb});
reversing the order -- so the Callback actually *gets called*:
callbackHandler.handle(new Callback[]{pcb});
ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
pcb = new PasswordCallback("Keystore Password: ",false);
fires off my CallbackHandler as expected.
I'm going to see if i can build a .jar and push this out into Spark as a replacement smack.jar and see what happens. I'm thinking it'll go better now, though.
Err, sorry this is the right ordering for the callback. The first shall be last...
smack> svn diff source/org/jivesoftware/smack/XMPPConnection.java
Index: source/org/jivesoftware/smack/XMPPConnection.java
===================================================================
--- source/org/jivesoftware/smack/XMPPConnection.java (revision 11005)
+++ source/org/jivesoftware/smack/XMPPConnection.java (working copy)
@@ -1219,9 +1219,9 @@
else {
ks = KeyStore.getInstance(configuration.getKeystoreType());
try {
- ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
pcb = new PasswordCallback("Keystore Password: ",false);
callbackHandler.handle(new Callback[]{pcb});
+ ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
}
catch(Exception e) {
ks = null;
Still no joy with Spark, though. But my Smack client is doing everything right and getting in under TLS on :5222
Logging into tester@localhost:5222
Callbacks: [Ljavax.security.auth.callback.Callback;@1f6f0bf
!!!!!!!!! Callback invoked!!!!!!!!!!!!!
Connection is using TLS and therefore is: secure.
Logged tester@localhost in.
Disconnected tester@localhost
Not sure why Spark isn't doing the right thing with an updated smack.jar.
Some other things I forgot to mention:
o config.setCallbackHandler() doesn't work; you have to provide it on the connect() for it to work. ![]()
So the real patch for XMPPConnection is:
smack> svn diff source/org/jivesoftware/smack/XMPPConnection.java
Index: source/org/jivesoftware/smack/XMPPConnection.java
===================================================================
--- source/org/jivesoftware/smack/XMPPConnection.java (revision 11005)
+++ source/org/jivesoftware/smack/XMPPConnection.java (working copy)
@@ -226,7 +226,7 @@
config.setSASLAuthenticationEnabled(true);
config.setDebuggerEnabled(DEBUG_ENABLED);
this.configuration = config;
- this.callbackHandler = null;
+ this.callbackHandler = config.getCallbackHandler();
}
/**
@@ -240,7 +240,7 @@
*/
public XMPPConnection(ConnectionConfiguration config) {
this.configuration = config;
- this.callbackHandler = null;
+ this.callbackHandler = config.getCallbackHandler();
}
/**
@@ -1219,9 +1219,9 @@
else {
ks = KeyStore.getInstance(configuration.getKeystoreType());
try {
- ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
pcb = new PasswordCallback("Keystore Password: ",false);
callbackHandler.handle(new Callback[]{pcb});
+ ks.load(new FileInputStream(configuration.getKeystorePath()), pcb.getPassword());
}
catch(Exception e) {
ks = null;
And it looks like the CallbackHandler isn't set right in any event:
[XMPPConnection(Config,CBH)] Callback handler: org.jivesoftware.LoginDialog$LoginPanel[,0,188,244x200,layout=java.awt.GridBagL ayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777217,maximumSize=,minimumS ize=,preferredSize=]
OOOOOOOOOOH. I bet... Yup. That's pointing to the PasswordCallback/CallbackHandler in the login pane... meaning they're assuming that the *keystore* and the *account* have the same password!
Mmmhmm. That *works*. Completely invalid assumption, but it works when I make them the same. Of course the other hidden caveat is that they're looking for key under the alias of the username. I haven't checked fall-back -- i.e., does it try "<username>" then "mykey", but one might presume. So that's a reasonable thing to do but setting the passwords the same is probably not. There should be a pop-up dialog.... or try the original, then pop-up, would be best.
However, now:
Exception in thread "Thread-1" java.lang.NoSuchMethodError: org.jivesoftware.smack.XMPPConnection.login(Ljava/lang/String;Ljava/lang/String ;Ljava/lang/String;Z)V
at org.jivesoftware.LoginDialog$LoginPanel.login(LoginDialog.java:860)
at org.jivesoftware.LoginDialog$LoginPanel.access$400(LoginDialog.java:200)
at org.jivesoftware.LoginDialog$LoginPanel$1.construct(LoginDialog.java:606)
at org.jivesoftware.spark.util.SwingWorker$2.run(SwingWorker.java:131)
at java.lang.Thread.run(Thread.java:595)
But I presume that's an SVN vs. RC/Beta-2 versioning thing:
------------------------------------------------------------------------
r10846 | gato | 2008-10-24 01:17:50 -0400 (Fri, 24 Oct 2008) | 1 line
Simplified list of #login methods in XMPPConnection.
Once i point #login(String,String,String,boolean) -> #login(String,String,String); it logs in perfectly!
That's with the latest 2.6.0-beta, not using the provided JRE. With another copy of the stock Spark (I think?), the certificate gets sent without the extra login(S,S,S,b) in there, but it gets "stuck" right here:
01E0: 72 65 73 73 69 6F 6E 3E 3C 61 75 74 68 20 78 6D ression><auth xm
01F0: 6C 6E 73 3D 22 68 74 74 70 3A 2F 2F 6A 61 62 62 lns="http://jabb
0200: 65 72 2E 6F 72 67 2F 66 65 61 74 75 72 65 73 2F er.org/features/
0210: 69 71 2D 61 75 74 68 22 2F 3E 3C 72 65 67 69 73 iq-auth"/><regis
0220: 74 65 72 20 78 6D 6C 6E 73 3D 22 68 74 74 70 3A ter xmlns="http:
0230: 2F 2F 6A 61 62 62 65 72 2E 6F 72 67 2F 66 65 61 //jabber.org/fea
0240: 74 75 72 65 73 2F 69 71 2D 72 65 67 69 73 74 65 tures/iq-registe
0250: 72 22 2F 3E 3C 2F 73 74 72 65 61 6D 3A 66 65 61 r"/></stream:fea
0260: 74 75 72 65 73 3E 98 E4 3B 39 92 A1 70 90 38 2D tures>..;9..p.8-
0270: FB 9D 16 18 4B 74 ....Kt
and eventually disconnects.
---------------
The other change was:
smack> svn diff source/org/jivesoftware/smack/PacketReader.java
Index: source/org/jivesoftware/smack/PacketReader.java
===================================================================
--- source/org/jivesoftware/smack/PacketReader.java (revision 11005)
+++ source/org/jivesoftware/smack/PacketReader.java (working copy)
@@ -467,6 +467,7 @@
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("starttls")) {
// Confirm the server that we want to use TLS
+ startTLSRequired = true;
connection.startTLSReceived(startTLSRequired);
}
else if (parser.getName().equals("required") && startTLSReceived) {
which isn't very robust, but at least it does the right thing.
So the end of the day:
1) Spark 2.6.0-beta2 -- stock -- might still be broken, but for some other random reason where the connection hangs (provided JRE?)
2) After applying the above patches to smack (also attached), and redeploying an updated lib/smack.jar, Spark 2.6.0b2 (1.5 JRE) should work for you provided:
3) Your keystore's password has:
a) a key+certificate with an alias the same as the user logging in
b) the password for the keystore *and* the key are the same,
c) the password you enter to login in the dialog is the same as (3.b).
I think that's all the non-obvious required conditions -- in addition to all of the regular openfire setup, and not to use the RPM, which apparently is broken. I've not even thought about looking at the diff between .tar.gz and rpm-based installations.
Can these patches be applied to SVN, please? And maybe a document defining everything put together separate from the forums?
If i get some time -- and I don't think I will -- I'll look into what's breaking beta2
Thanks!
Well this isn't the best solution, but at least it's kind of working.
@slushpupie: Is this Problem scheduled to be fixed?
Daniel
I doubt any of the other people with svn access understand this well enough to fix it (anyone who does dev work in PKI certainly understands how rare it is) and Im stretched a bit thin with other commitments at the moment. So no, its not really in a timeline anywhere. Ill try to get on the community group chat today- perhaps we can all discuss it then.
Thanks slushpuppie. The patches are quite limited, so applying them should be very obvious, I don't think it's going to require any PKI-specific knowledge to see, e.g., that you must register the callback handler, before calling it back. ![]()
However, I do have more to report: apparently I was mistaken regarding the RPM -- you were right, there was no difference.
Apparently the crl and client truststore properties (xmpp.client.certificate.crl and xmpp.socket.ssl.client.truststore) only admit of *relative URLs*. I.e., "/opt/openfire/resources/security/client.truststore" won't work.... "resources/security/client.truststore" will work. That's a tidy bit of info. Of course, I could not ever verify until I'd patched my Spark client per the above, but that's probably a critical piece of information for folks to be aware of. I'll try to add a note to the other thread where you laid out the basic properties.
Anyway, I'd be happy to file a ticket in JIRA, but it's not open to the public. Could you at least create a ticket, if you have access? And attach the patches, etc? Oddly, I do see that the RPM-based 3.6.3 server is showing <starttls><required="true"></starttls>, so I'm not sure what the deal is there, or if I'm looking in the wrong place.
Okay, im getting closer. Your solution seems to work. The only thing which prevents me from connection to the Server is this error:
| 2009.05.07 10:30:18 Closing session due to exception: (SOCKET, R: /192.168.0.135:2003, L: /192.168.0.135:5222, S: 0.0.0.0/0.0.0.0:5222) org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.Exception: Disallowed character (Hexdump: 80 62 01 03 01 00 39 00 00 00 20 00 00 04 01 00 80 00 00 05 00 00 2F 00 00 33 00 00 32 00 00 0A 07 00 C0 00 00 16 00 00 13 00 00 09 06 00 40 00 00 15 00 00 12 00 00 03 02 00 80 00 00 08 00 00 14 00 00 11 4A 02 9C 1A 68 7A 1F 9D 31 7C DC DD 0D FF FF 1E E5 52 5F 47 0A 50 7F 13 E5 60 84 F4 EA 0E 19 52) |
This occures while TLS handshaking. i think theres someting wrong with my certificates but i dont know what, any idea? is the character '-' disallowed in certificate names?
Daniel
What's your value for tls -- optional? required? And, you've replaced the original smack.jar with the updated one? And your keystore contains a key that matches, username and password, against what the jabber server is expecting? I.e., the alias on a key in the keystore matches your jabber userid, and the password to the keystore, aliased key, and jabber account all match?
TLS is set to required. Keys and aliases are all the same, Ive double checked it.
client.truststore, etc. properties are relative path-based and owned by the openfire daemon user?
if you're using the default client.truststore, just try removing the properties for that and crl, that seemed to help on mine. Make sure the truststore shows that you're trusting the right CA.
And that the client's truststore/keystore has the server's CA certificate (trusted) in it (and aliased different from 'mykey' probably).
And you're sure you're using the patched .jar file for smack.jar?
I can't think of anything else to check, sorry ![]()
Yes API is patched but, I'll check those relativ paths. Im confident, this will work soon. I'll check the whole stuff again maybe Ive missed something. Thanks for the help anyway.
Daniel
Okay, Im still stuck. Ive created those openssl certificates once again using only letters. Imported them into the keystore and truststore of the client with all the same password. The same on the server side. Smack api is fixed with the diff patches which where posted above and repacked with ant.
Ive tried to connect on port 5222 with config.setSocketFactory(SSLSocketFactory.getDefault()); and without it. In both configurations I get "Closing session due to excpetion"and java.lang.Exception: Disallowed character. Openssl client test says that there still arent any certificates offered.
openssl s_client -prexit -connect localhost:5222
Loading 'screen' into random state - done
CONNECTED(00000778)
3440:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:.\ssl\s23_lib.c:188:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 124 bytes
---
New, (NONE), Cipher is (NONE)
Compression: NONE
Expansion: NONE
---
Is this an indication for this problem?
Port 5223 offers certificates, but im not able to connect.
With config.setSocketFactory(SSLSocketFactory.getDefault()); i get sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target and without it get javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Im grateful for any help ![]()
EDIT: I found out that, when using config.setSocketFactory(SSLSocketFactory.getDefault()); on port 5223 Smack uses the cacerts keystore in the jre folder. If I add my root certificate into that keystore i get javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: Netscape cert type does not permit use for SSL server.
EDIT2: Ive removed all Netscape comments an attributes from those openssl certificates to fix the "Netscape cert type does not permit use for SSL server" problem, but Im ending up in a "null certificate chain". So, back to the beginning. Im getting mad ![]()
Yes; the default SSL context is to use the system-property-based key/trust stores. Openfire does something different by using specific ssl context, which you can set up per my simple client code.
Null cert chain, i'm pretty confident means that the client is not sending CAs. If you can't get s_client to show any advertised CAs, it means almost definitely that none are being offered. I think this points to an issue with Openfire finding the client.truststore -- to what is your client.truststore property set? And navigation to that path is accessible to the user as whom the openfire service is running, correct?
Client.truststore has default settings, I didnt change them. Im using Windows, so the server is running with my user which is administrator. I think if there would be no access to the client.trusstore, an error would be listed in the debug log.Obviously on Port 5223 my certificates are offered, so I think openfire is able to access the client.truststore.
The CallbackHandler, which you are using in your client code, which package is it from? If I import the class which eclipse proposes to me(javax.security.auth.callback.CallbackHandler). It cant be instantiated because it is an Interface. Did you write a callbackhandler by yourself?
EDIT: Obviousely connection via port 5223 is working. Setting those systems propertys made my day
But I want to find out, why there are no certificates offerd on port 5222
Yes, I implemented my own basic callbackhandler. That's how I was able to see that the CallbackHandler was never being invoked -- someone had screwed up the ordering of the callback handling statements in the Smack library. It's really quite simple, I just created a new class implementing the interface and it was:
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
System.err.println("Callbacks: " + callbacks);
System.err.println("!!!!!!!!! Callback invoked!!!!!!!!!!!!!");
if (callbacks != null && callbacks[0] != null) {
PasswordCallback callback = (PasswordCallback) callbacks[0];
callback.setPassword("password".toCharArray());
} else {
System.err.println("Invalid Callback: callbacks[] as null/empty.");
}
return;
}
When I never saw the "Callback invoked" line, I knew something was messed up.
As far as why no CA certs are shown on :5222, I think it's because of how the TLS negotiation works. I don't see any either. However, it still works to require a valid client certificate. I think there's some issue with the 'required="true"' being set properly, although it's possible that on those tests I never set tls.required... can't be sure.. too many tries at it. In any event, it doesn't appear that Smack will speak TLS if it's not _required_, which isn't wrong, IMO -- but I've not read the spec. I think if it supports it, and the server supports it, it should be negotiated. My patch just sets TLS if it sees a starttls tag, required or not -- not perfect, but it gets the job done, and I'm not familiar enough with the code to fix it The Right Way [tm].
But you're saying it's working for you on :5223? It's probably working on :5222, as long as you have the TLS patch in place, too.
Hm, TLS isnt working, your patch is n place. Ive implemented a callbackhandler but the error occurs befor the callbackhandler gets invoked. Its still "the disallowed character" exception on server side. Anyway its working with SSL. Which Version of SSL does smack/openfire implement? 3.0?
What is Spark's debug telling you in Raw Sent/Received Packets?
Callback handler patch has been applied to trunk.
Hello!
First of all, let me introduce myself. I'm a student at the University of Girona (Catalonia, Spain) and doing my master thesis about an application that uses XMPP. So, recently my tutor told me that it would be great to implement an authentification using X.509, and that's why I have ended in this post.
Well, I follow this topic trying to make it work, but I'm having the similar problems that are describing some posts earlier.
Problems (i'm using 5222 TLS port):
- At client side the error is: "handshake message sequence violation,2" if i'm not using setSocketFactory.
- Using socketfactory: SocketException: coonection is closed ... Remote host closed connection during handshake.
- At server side: Warn: java.lang.Exception: Disallowed character
Debug: SSL Handshake failed .... SSLHandshakeException: null cert chain
If I use 5223 on Debug: SSLException: Unrecognized SSL message, plaintext connection?
There are a few things that I'm not sure if I had done ok, so let me explain what I'm using:
- I followed the instructions of the first posts (create the system preferences in OpenFire).
- I'm using the SMACK API 3.1.0 and patched with the last patch of vargok.
- The callback is called but before doing any SSL connection. Normal?
- I'm not sure if the client is accessing to the client certificate...
- On server side, I added my CA to client.trustore (it appears as trustedCertEntry), in trustore also. The private key of the server was added in keystore (and it appears as a PrivateKeyEntry).
- Openfire complains about pending validation of my private key, althought it was validated by my CA. Does it affect it?
- On client side, I created a keystore and truststore and added the client cert and the CA. But when I checked in keytool about keystore file, it shows the client cert but it says: trustedCertEntry. Is that normal?
- When I do a openssl s_client on 5223, it prints the next output:
xavi@songohan:~/openfire/resources/security$ openssl s_client -prexit -connect localhost:5223CONNECTED(00000003)
depth=0 /C=ES/ST=Catalunya/L=Girona/O=Universitat de Girona/OU=Broadband Communications and Distributed Systems/CN=songohan.udg.edu/emailAddress=contacte@triem.org
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=ES/ST=Catalunya/L=Girona/O=Universitat de Girona/OU=Broadband Communications and Distributed Systems/CN=songohan.udg.edu/emailAddress=contacte@triem.org
verify error:num=7:certificate signature failure
verify return:1
depth=0 /C=ES/ST=Catalunya/L=Girona/O=Universitat de Girona/OU=Broadband Communications and Distributed Systems/CN=songohan.udg.edu/emailAddress=contacte@triem.org
verify return:1
Why it gives me three outputs?
I think that it would be very helpful if anyone could attach a fake CA, Server Key and Client Key that works with X.509 auth on OpenFire (or also, a good tutorial to generate it).
Finally, I put some of my code that I'm using to connect in case anything is wrong.
ConnectionConfiguration cc = new ConnectionConfiguration(server,port,server);
String KEYSTORE_PATH=... //absolute path to the keystore file
String KEYSTORE_PASSWORD="changeit"
String TRUSTSTORE_PATH=...
String TRUSTSTORE_PASSWORD="changeit"
cc.setKeystorePath(KEYSTORE_PATH);
cc.setKeystoreType("jks");
cc.setTruststorePath(TRUSTSTORE_PATH);
cc.setTruststoreType("jks");
cc.setTruststorePassword(TRUSTSTORE_PASSWORD);
cc.setCallbackHandler(new myCallbackHandler()); //I'm using vargok callback
//cc.setSocketFactory(SSLSocketFactory.getDefault());
XMPPConnection connection = new XMPPConnection(cc);
//System.setProperty("javax.net.debug","ALL");
SASLAuthentication.supportSASLMechanism("PLAIN",0);
connection.connect();
connection.login(username,password,resource); //hope to remove if it works!
I'm willing to help as much as possible in this aspect. If needed, I'll join the next chat and be avaiable to do as many tests I can. Please, help me ![]()
Thanks for advance!
----------------------------------------------------------
Update: Yay! Finally I made it work! As I suspected, the problem is that my client didn't get the client key, so there was no avaiable keys and that's why the server closed the connections.
The openssl output is ok, and the pending validation is not a problem. My real problem is in the client keystore.
There is a little problem adding certs to the keystore using keytool. At the following webpage it explains this problem and how to solve it:
http://www.agentbob.info/agentbob/79-AB.html
To check that the client cert was insered correctly, when you do a :
>>keytool -list -keystore keystore
And it should appear as a KeyEntry instead of CertEntry
After do that, all started to work magicly. The callback detected the client cert and so on ![]()
If I try to use the default SocketFactory, it seems that it doesn't work.
One last question: I'm using EXTERNAL auth and works, but is it necessary that the client executes the login method? (e.g. login("","")).
So, here is the needed code to make it work for me:
ConnectionConfiguration cc = new ConnectionConfiguration(server, port, server);
cc.setKeystorePath("....");
cc.setKeystoreType("jks"); //not needed, by default jks
cc.setCallbackHandler(new myCallbackHandler());
connection = new XMPPConnection(cc);
//System.setProperty("javax.net.debug","ALL");
SASLAuthentication.supportSASLMechanism("PLAIN", 2);
SASLAuthentication.supportSASLMechanism("DIGEST-MD5", 1);
SASLAuthentication.supportSASLMechanism("EXTERNAL", 0);
connection.connect();
connection.login("", "");
FTR, the fix for the callback processing was applied to trunk today under r11018.