OpenFire PKI Question

Does anyone know of a problem with the Open Fire server not handling PKI certificates correctly. I’m just starting to get into this (newbie) and could use some help. I’ve been told that if you’re trying to authenticate with PKI, the client handles it correctly…but you can put an expired certificate on the server and when the server tries to authenticate, it will still work with an expired certificate.

Anyone know if this is true or not or have any experience with PKI authentication?

Alex

I added the PKI support in, but it never got well documented. So here we go:

First, set these server properties:

xmpp.client.cert.policy : needed

xmpp.client.certificate.crl : path to CRLs in a single file in PEM format.

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.certificate.accept-selfsigned : false (or set to true, and make sure the cert itself is in the CA list described below)

Next, you need to add the CA’s (and any intermediate CA’s) to the client truststore. The client truststore is only used for verifying clients, and has no impact on the normal s2s verifications, so its ok to keep it limited to just CA’s you trust. In fact, you dont want any CA’s listed that you dont trust. This file is defined in the property xmpp.socket.ssl.client.truststore or defaults to resources/security/client.truststore (it should exist and be empty by default). If you want to use your own file located elsewhere (say from a tomcat install, or whatever) make sure you update both that property, and xmpp.socket.ssl.client.trustpass with the password to the truststore.

After the above config changes, restart openfire. It will require c2s connections present a cert from the known CA’s. Normal authentication will still be in effect, though. If you have a client that supports it, you can enable EXTERNAL authentication to skip the password requirement of logins. At the moment, I think only Spark from svn supports this- if you know of another version let me know. To enable EXTERNAL auth in openfire, you need to edit the openfire.xml, and add (or modify) the sasl section so it looks like this:

(you can add others in there too, if you want to allow them; such as PLAIN, CRAM-MD5, etc)

This means the CN of the client cert must exactly match the JID of the user. At the moment we dont have any good mapping methods.

If you need help with any of this, just speak up. I dont think Ill be writing a document anytime soon since there are not many (any?) people using this besides me right now. This post might just become the documentation

Oh, and by the way. Java’s handling of CRL’s is very memory intensive. General rule of thumb, take the CRL file size and multiply by two and thats how much memory the CRLs will take up alone. Im working on OCSP support which should make this better.

What’s the time frame for you finishing up the OCSP support?

Alex

Hi, I can’t really see the code provided after “looks like this:” Any chance you can provide it in a different way? We are planning on using C2S connection with SASL EXTERNAL. Time will show if will be able to add it the client we are planning on using. You are saying that the CN must match the JID of the user. In our environment we are using unique node names and thus wan’t that to be the matching point and not the JID as such. I hope tha that doesn’t mean that we need to do a lot of changes to the Openfire code.

Kind regards,

Lars

Im not sure what you are asking here- I never posted any code to the forums here. If you need some help with PKI and Openfire, let me know and Ill see what I can do to help. If you need to make JID’s map to something besides some part of the subject (or other certificate feature) it is possible, the SASL code has hooks for doing such things. Its never really been used that way, so I cant say how well it works :slight_smile:

Thanks! The part I was asking about was the sasl.mechs to add in the openfire.xml file. I found out that it was quite obvious how to do this after I looked into the code. EXTERNAL, PLAIN etc… to set sasl.mechs.

Regarding other issues about PKI and Openfire, I will most likely come back to you with some more questions. First of all were trying to get the certificate chain verification to work (making sure that our OpenSSL stuff works appropriately) between servers (TLS + SASL EXTERNAL). Then we will start working on the same between the server and the client we are using. This includes using the hooks you mention in the SASL code. In a way, it seems like we are covering some new ground here which is both fun and a bit hard.

Hopefully, you will find the time to read through future postings on this matter :wink:

Cheers

Yes! I followed you’re guideline and have now verified that SASL EXTERNAL can work with both s2s and c2s :wink:

As you mention, you need to have the CA certs in the client.truststore on the server. Without it you will get the …null cert chain message in the debug log on the server etc. It is true that Spark has some support for SASL EXTERNAL, but it seems that the last step is missing and that is how the passord for the keystore can be retrieved with the PasswordCallback. In the last version also from the repository it seems that it doesn’t create an XMPPConnection with a CallbackHandler. Instead of using Spark I tested this by using Smack. Adding my own PasswordCallbackHandler that returned the password changed everything.

If anybody else is struggling with SASL EXTERNAL and clients then tell me. I hope I have a few more things to tell you. Since we are actually going to use a .NET C# client I won’t bother modifying the Spark client.

Lars

The main reason for using a callback handler is that not all keystores are accessed by entering a simple password. PKCS#11 keystores are the main focus of my modifications.

Im glad you got it working, though, thats good news to hear its been useful for someone other than myself!

Hi- I’ve done all of the above, AFAICT, but the handshake is failing. Enabling ssl debug for handshake, I’m seeing:

[Server side]

trigger seeding of SecureRandom
done seeding SecureRandom
Using SSLEngineImpl.
SocketAcceptorIoProcessor-0.0, READ: SSL v2, contentType = Handshake, translated length = 73
*** ClientHello, TLSv1

[…]

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)
[…]

Caused by: java.lang.NullPointerException
at com.sun.net.ssl.internal.ssl.HandshakeMessage$CertificateRequest.(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

[Client Side]

Spark> tail logs/output.log
Smack Packet Reader (0), setSoTimeout(0) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1219913857 bytes = { 213, 152, 250, 91, 14, 240, 132, 158, 156, 243, 23, 155, 234, 123, 46, 230, 225, 60, 26, 197, 253, 114, 22, 102, 109, 240, 169, 27 }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_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]
Compression Methods: { 0 }


Smack Packet Reader (0), WRITE: TLSv1 Handshake, length = 73
Smack Packet Reader (0), WRITE: SSLv2 client hello message, length = 98

Then both sides are waiting, and eventually timeout.

I’ve tried setting JVM params in Spark via System properties (-D): javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword (tried xmpp. variants), but i can get no farther.

The CA is installed both in ~/.keystore for the user, and in client.truststore on the server (I put it in truststore, too, just to be safe) with -trustcacerts, and so forth. I see no mention of the client cert being provided to the server, but I can’t figure out if that’s because something isn’t set right or it’s just a handshake issue and it doesn’t get that far.

/tmp/spark/Spark/jre/bin/java -client -Djavax.net.debug=ssl
-Dhttps.protocols=TLSv1,SSLv3
-Djavax.net.ssl.keyStore=~/.keystore
-Djavax.net.ssl.keyStorePassword=[***]
-Dxmpp.socket.ssl.keystore=~/.keystore
-Dxmpp.socket.ssl.keypass=[***] -Dinstall4j.jvmDir=/tmp/spark/Spark/jre
-Dexe4j.moduleName=/tmp/spark/Spark/Spark -Dappdir=/tmp/spark/Spark/
-Dsun.java2d.noddraw=true -Djava.library.path=/tmp/spark/Spark/\lib\windows
-classpath

Any ideas?

I would need more info, the debug output you posted is incomplete. It often is too large to easily post here, so maybe attach it or post it somewhere. I also suggest instead of hyjacking this thread (which is essentially resolved) you start your own thread.

Sure, i’ll start a new thread.

slushpupie wrote:

This post might just become the documentation

so i figured it was germane.

Cross-ref to:

http://www.igniterealtime.org/community/message/190988#190988

Please note that paths for the CRL and Client.Truststore apparently must be relative paths to the root of the openfire server, and not full paths. E.g., /opt/openfire/resources/security/client.truststore did not work for me, but resources/security/client.truststore did.