Openfire+Spark - Client X.509/PKI Certificate Support

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?

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(“”, “”);

Callback handler patch has been applied to trunk.

FTR, the fix for the callback processing was applied to trunk today under r11018.