I’m a dabbler, I like to dabble.
While most people are happily using Google Talk, Facebook chat, Skype and the like I’m busy playing around with my own chat server, writing plugins for it and seeing if I can get things like Single Sign On (SSO), DNS Service Records and Federation working. It’s time consuming, frustrating at times but ultimately rewarding. One particularly frustrating problem I recently tackled was single sign on with Openfire (a Jabber/XMPP messaging server).
My basic setup likely mirrors most enterprise-y networks:
- Windows Active Directory Domain Controller with Windows Support Tools installed
- Openfire 3.8 bound to the Windows DC
- Windows XP/Windows Terminal Server Clients running Pandion/Pidgin
- Mac OS X Clients Running Adium
The first step is to ensure that you have a working Windows AD network alongside a working Openfire installation.
- AD Domain: EXAMPLE.COM
- AD Host: DC.EXAMPLE.COM
- Openfire (XMPP) Domain: EXAMPLE.COM
- Openfire Host: OPENFIRE.EXAMPLE.COM
- Keytab account: xmpp-openfire
Ensure you have an A and reverse DNS record for your Openfire server and then setup your DNS Service Records for Openfire like so:
_xmpp-client._tcp.example.com. 86400 IN SRV 0 0 5222 openfire.example.com. _xmpp-server._tcp.example.com. 86400 IN SRV 0 0 5269 openfire.example.com.
With DNS done create two new Active Directory accounts. Account one is for binding the Openfire server to the domain (skip this account if you’ve already bound Openfire to your domain).
Account two is to associate your Service Principal Name (SPN) so Kerberos clients can find and authenticate using SSO with your Openfire server.
On account two check under Account properties that User cannot change password, Password never expires and Do not require Kerberos preauthentication are checked.
On the Windows Domain Controller you’ll now need to create the SPN and keytab. The SPN (Service Principal Name) is used by clients to lookup the name of the Openfire server for SSO. The keytab contains pairs of Service Principals and encrypted keys which allows a service to automatically authenticate against the Domain Controller without being prompted for a password.
Creating the SPN:
I created two records since it seems some clients lookup xmpp/openfire.example.com@EXAMPLE.COM and some look up xmpp/openfire.example.com.
setspn -A xmpp/openfire.example.com@EXAMPLE.COM xmpp-openfire setspn -A xmpp/openfire.example.com xmpp-openfire
Mapping the SPN to the keytab account xmpp-openfire and when prompted enter the xmpp-openfire password:
ktpass -princ xmpp/openfire.example.com@EXAMPLE.COM -mapuser xmpp-openfire@EXAMPLE.COM -pass * -ptype KRB5_NT_PRINCIPAL
Create the keytab:
I found that the Java keytab didn’t work on my Openfire system in which case I used the Windows ktpass utility to create it. Some users report the converse, so see whichever works for you:
Java keytab generation:
ktab -k xmpp.keytab -a xmpp/openfire.example.com@EXAMPLE.COM
Windows keytab generation:
ktpass -princ xmpp/openfire.example.com@EXAMPLE.COM -mapuser xmpp-openfire@EXAMPLE.COM -pass * -ptype KRB5_NT_PRINCIPAL -out xmpp.keytab
Copy the keytab to your Openfire directory, typically /usr/share/openfire or /opt/openfire. The full path will look like this:
/usr/share/openfire/xmpp.keytab
Configuring Linux for Active Directory
Configure Kerberos
First we need to install ntp, kerberos and samba:
apt-get install ntp krb5-config krb5-user krb5-doc winbind samba
Enter your workgroup name:
eg. EXAMPLE.COM
Configure /etc/krb5.conf
[logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] dns_lookup_realm = true dns_lookup_kdc = true ticket_lifetime = 24h forwardable = yes [appdefaults] pam = { debug = false ticket_lifetime = 36000 renew_lifetime = 36000 forwardable = true krb4_convert = false }
Test connection to Active Directory by entering the following commands:
:~# kinit xmpp-openfire@EXAMPLE.COM
Check if the request for the Active Directory ticket was successful using the kinit command
:~# klist
The result of this command should be something like this:
Ticket cache: FILE:/tmp/krb5cc_0 Default principal: xmpp-openfire@EXAMPLE.COM Valid starting Expires Service principal 07/11/13 21:41:31 07/12/13 07:41:31 krbtgt/EXAMPLE.COM@EXAMPLE.COM renew until 07/12/14 21:41:31
Join the domain
Configure your smb.conf like so:
#GLOBAL PARAMETERS [global] workgroup = EXAMPLE realm = EXAMPLE.COM preferred master = no server string = Linux Test Machine security = ADS encrypt passwords = yes log level = 3 log file = /var/log/samba/%m max log size = 50 printcap name = cups printing = cups winbind enum users = Yes winbind enum groups = Yes winbind use default domain = Yes winbind nested groups = Yes winbind separator = + idmap uid = 600-20000 idmap gid = 600-20000 ;template primary group = "Domain Users" template shell = /bin/bash [homes] comment = Home Direcotries valid users = %S read only = No browseable = No [printers] comment = All Printers path = /var/spool/cups browseable = no printable = yes guest ok = yes
Join the domain:
:~# net ads join -U administrator
You will be asked to enter the AD Administrator password.
Verify you can list the user’s and groups on the domain:
:~# wbinfo -u
:~# wbinfo -g
Testing the keytab works:
From your Openfire system run the below command:
kinit -k -t /usr/share/openfire/resources/xmpp.keytab xmpp/openfire.example.com@EXAMPLE.COM -V
You should see:
Authenticated to Kerberos v5
Then create a GSSAPI configuration file called gss.conf in your Openfire configuration folder normally in /etc/openfire or /opt/openfire/conf. Ensure you set the path to your xmpp.keytab file:
com.sun.security.jgss.accept { com.sun.security.auth.module.Krb5LoginModule required storeKey=true keyTab="/usr/share/openfire/xmpp.keytab" doNotPrompt=true useKeyTab=true realm="EXAMPLE.COM" principal="xmpp/openfire.example.com@EXAMPLE.COM" debug=true isInitiator=false; };
Ensure the file is owned by the openfire user.
Stop Openfire and enable GSSAPI by editing your openfire.xml configuration file which is found in the openfire conf directory:
<!-- sasl configuration --> <sasl> <mechs>GSSAPI</mechs> <!-- Set this to your Keberos realm name which is usually your AD domain name in all caps. --> <realm>EXAMPLE.COM</realm> <gssapi> <!-- You can set this to false once you have everything working. --> <debug>true</debug> <!-- Set this to the location of your gss.conf file created earlier --> <!-- "/" is used in the path here not "\" even though this is on Windows. --> <config>/etc/openfire/gss.conf</config> <useSubjectCredsOnly>false</useSubjectCredsOnly> </gssapi> </sasl>
Or add to System Properties:
sasl.gssapi.config /etc/openfire/gss.conf sasl.gssapi.debug false sasl.gssapi.useSubjectCredsOnly false sasl.mechs GSSAPI sasl.realm EXAMPLE.COM
Restart Openfire