Openfire Client SSL Authentication How-to
Openfire is the only open source XMPP server (that I know of) that supports client-side certificate authentication. This will explain how to setup Openfire and Pidgin to using client-side certificate authentication.
Create Certificates
- You will need to create a test certificate authority. A number of web sites have how-tos on creating a certificate authority for testing.
- Using the OpenSSL CA tools:
Create a certificate/key pair for each user.
The certificate's COMMON NAME must match the XMPP login name
- Create a PKCS12 file containing the certificate/key pair. The files need to be in PEM (text) format for openssl and not DER (binary).
- To convert a certificate to PEM format:
openssl x509 -inform der -in DER_CERT_FILE -outform pem PEM_CERT_FILE
- To convert a key to PEM format:
openssl pkey -inform der -in DER_KEY_FILE -outform pem PEM_KEY_FILE
- To create the PKCS12 file:
openssl pkcs12 -export -inkey KEYFILE -in CERTFILE -out USER.p12 -name USER
Setting Up Openfire
- Download, install, and setup Openfire:
http://www.igniterealtime.org/projects/openfire/index.jsp http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/install-guide.html
- Openfire maintains several key stores in /etc/openfire/security. We are interested in client.truststore which contains the certificates trusted to authenticate users. We can place a certificate authority certificate in the key store and any certificates signed by the authority will be accepted for login to the server.
To add a certificate:
keytool -importcert -keystore /etc/openfire/security/client.truststore -alias NAME -file CERTFILE
The default password is "changeit"
Be sure to say yes to "Trust this certificate?".
- Login to you Openfire server on http://server:9090 and go to Server->Server Manager->System Properties. Ensure the following properties exist and are set:
Property | Value |
---|---|
xmpp.client.cert.policy | "needed" or "wanted" |
xmpp.client.certificate.accept-selfsigned | true |
xmpp.client.certificate.verify | true |
xmpp.client.certificate.verify.chain | true |
xmpp.client.certificate.verify.root | true |
sasl.mechs | EXTERNAL (plus whatever else) |
More properties can be found here:
http://community.igniterealtime.org/thread/45670 http://community.igniterealtime.org/thread/37967
- Add a user with the same username as the common name of the certificate you created above in Users/Groups?->Users->Create New User.
Build Pidgin with Client Certificate Authentication
- Pull the cpw.ljfisher.ssl_client_auth branch from the http://hg.pidgin.im/cpw/ljfisher/ssl_client_auth/ repository.
- Ensure the following prerequisites are installed:
- gnutls 2.10 + Older versions will work but exporting certificates and keys will fail
- Cyrus SASL
- Configure Pidgin with these options:
./configure --enable-cyrus-sasl --enable-gnutls=yes
- Build and install Pidgin:
make install
Configure Pidgin
- Open Tools -> Certificates -> Your Certificates. Select Add. Select the PKCS12 file, USER.p12, created above. Enter a passwords and name.
- Create a XMPP (Jabber) account.
On the Basic tab:
- Enter a username same as the common name in the certificate
On the Advanced tab:
- Select Connection Security: Use old-style SSL
- Select Login certificate: the cert you added above
- Change connection port to 5223.
Openfire doesn't seem to play well with client authentication using starttls so we use regular SSL which uses port 5223.
- Enable the account and it should login.
Troubleshooting
You get SSL Handshake failed messages
- Check that /etc/openfire/security/client.truststore is readable by openfire user.
- Check that the certificate authority's certificate has been added to /etc/openfire/security/client.truststore and has been trusted:
keytool -list -keystore /etc/openfire/security/client.truststore
- Check that the user name matches the common name of the login certificate.
You get a password dialog when trying to login even though you selected a login certificate
- Check that EXTERNAL has been added to the sasl.mechs Openfire server property.
- Check that the user name matches the common name of the login certificate.
- Check that there is an account for the user on the Openfire server
Bug Reports
If you cannot resolve the issue send a capture of the Pidgin debug output by running Pidgin with debug and GNUTLS debug enabled:
PURPLE_GNUTLS_DEBUG=9 pidgin -d > pidgin.dbg
And capture the login using Wireshark and send a pcap.