Friday, 15 June 2007

Python GSSAPI bindings

So, after a few blind alleys, I finally got the JWChat code working. Unfortunately, what this revealed is that the state of GSSAPI support for Python isn't that great.

Esentially, there are two different sources of GSSAPI-Python bindings:

  • PyGSSAPI (on Sourceforge). This is old, and unmaintained. It's written in SWIG, but the SWIG source won't compile in recent SWIGs, and the provided C source won't work with current Python
  • PyKerberos (part of Apple's CalDav server). This is a simple solution, but only provides access to an interface designed to do Negotiate-Auth. The interface isn't object oriented, nor will it garbage collect properly.


In order to get PunJab doing what I needed, the quickest route seemed to be to add SASL support to the PyKerberos library, so I did so. This solution isn't particularly clean, nor does it interface well with situations where you're trying to do anything other than perform a SASL handshake using credentials acquired in a previous NegotiateAuth transaction.

Other local projects required a way to do normal GSSAPI SASL from Python, and I really wanted to tidy up the PunJab code,so I ended up breaking and implementing my own Python bindings. Whilst not yet complete, these currently provide enough functionality to implement a GSSAPI SASL layer for the Twisted Jabber library, which solves our immediate local issue.

Once I've finished documenting the library, I'll package it up and announce it more widely.

Tuesday, 22 May 2007

Adding SSO to JWChat

We're in the process of deploying a new Jabber server here, and have already got the server (jabberd2) and assorted clients (Gaim, Psi, AdiumX, Cocinella) supporting Kerberos based single signon. In my idle moments, though, I've been playing with JWChat - which doesn't support any of the WebSSO technologies, instead requiring a username and password. This limitation isn't really JWChat's fault - instead, it's a product of the way that it must be implemented. JWChat is a complete, Javascript based, Jabber client which runs in the browser - which talks XMPP encapsulated in HTTP (using either HTTP-Binding, or HTTP-Polling) via a proxy, back to your Jabber server. The fact that it's implemented in the browser means that it doesn't have access to anything useful, like a password store, let alone a Kerberos credentials cache. The fact that the proxy just passes XMPP packets blindly to the server, means that you can't use authentication to the proxy as a way of securely authenticating to the Jabber server.

So, here's a cunning plan. There's already a Man-In-The-Middle (the proxy). This is already slightly active at moments during the session. My plan is to make this proxy a little more active when connection establishment is being performed. In particular ...
*) Use the EXTERNAL SASL mechanism to indicate that the authentication is happening over an external channel.
*) The proxy runs at a URL which is optionally protected by some form of proxiable authentication (the one I'm interested in here is Kerberos, but other options are possible).
*) If the user has successfully authenticated to the proxy, then it looks out for the stream:features packet at the start of the XMPP handshake. It intercepts this packet, and adds EXTERNAL to the _start_ of the list of supported SASL mechanisms.
*) The client then picks which authentication mechanism to use. If it is a hacked version of JWChat, it will try EXTERNAL
*) The proxy looks out for an attempt at doing EXTERNAL. If there is one, it doesn't forward this packet to the server. Instead, it starts its own GSSAPI based authentication, using the current user's credentials. It talks directly to the XMPP server (without returning any packets to the client) until the GSSAPI handshake is complete. It then fakes success or failure to the client as coming from the EXTERNAL mechanism.

This should all work, with a few caveats. We can't establish security layers (unless the proxy becomes really clever). The proxy needs to know about a Kerberised authentication mechanism (in our case, probably NegotiateAuth), and about how to do the SASL GSSAPI mechanism. The proxy needs to decode, and encode, XMPP packets by itself.

I'm going to have a go at implementing this using Punjab as the proxy (as Python is slightly less unfamiliar than Java at the moment, and there is at least a free SPNEGO / NegotiateAuth plugin for Twisted available in the Apple CalDav source)

Sunday, 13 May 2007

AFS & Kerberos Workshop

Sitting in Atlanta waiting for a delayed flight on my way back from the AFS & Kerberos Best Practices Workshop at SLAC.

The conference was a little lower-key this year, as accounting restrictions presented commercial sponsorship & the provision of food at meal breaks. Whilst this perhaps reduced the amount of mingling that took place, it didn't really reduce the quality of the talks - which were another strong mixture of case-studies and development reports. Another great effort from Derrick, Jeff, Russ,Tracy, Alf (and the sadly missing Moose).

The talks from the workshop are up on their web pages at http://www.pmw.org/afsbpw07/. Of particular interest to us are Kristen's talk on NDMP, Russ's talk on his pam modules (which I hope we'll be able to migrate to using before our next client platform release), Love's description of rxgk, Matt and Marcus's byte range locking, and Derrick's version of hostafsd.

There was also some talk of testing and build farms, which I hope I'll be able to find a way to help with.

Tuesday, 13 March 2007

GSSAPI Key Exchange for OpenSSH 4.6

Just a quick note that I finally managed to get it together enough to produce a GSSAPI Key exchange patch for the new OpenSSH 4.6p1 release. Patch is available, as always, from http://www.sxw.org.uk/computing/patches/openssh.html

I'm also working on a patch to allow propagation of rekeys over the key exchange handshake. In theory, this means that if you are sitting at a workstation and renew your credentials on that machine all of the machines that you've forwarded tickets to over ssh will also get renewed credentials.

This promises to be really quite funky for people who work like me - with a single, desktop login at home, and many many ssh connections to machines at work. Being able to have all those connections 'magically' end up with valid Kerberos tokens just because I renew my ticket at home will greatly save on typing.

Monday, 26 February 2007

Shifting to Jabberd2.1.1

I'm in the process of migrating our development Jabber service from an FC3 platform, where it's running a heavily patched version of jabberd2.0, to the newly revitalised jabberd2.1. 2.1 already has our local Cyrus SASL patches included, so we can drop those from the patch set, along with a large number of other improvements. In addition, I'm taking the opportunity to improve our support for non-local clients.

In the earlier incarnation, our service would only accept GSSAPI connections - it didn't support any form of password based authentication. It was repeatedly pointed out to me that this was a pain! Clients such as iChat just wouldn't work, Adium, Gaim and Psi all had to be used in a locally patched form, and it was not particularly usable. So, I've suspended my concerns about people caching their Kerberos passwords in their chat clients, and added support for doing password based authentication. This has required some reconfiguration (we now use pam for auth checking, rather than LDAP), and some code changes to jabberd2.1

The PAM authreg module that ships with jabberd2.1 has some strange ideas about what a username looks like - it uses the full JID of the user when calling into the PAM stack (so you get usernames of the form user@example.com). This doesn't work well with a conventional PAM stack, so I've patched the code to disable this behaviour.

I also wanted to be able to restrict password authentication to SSL connections, whilst still providing GSSAPI on insecure connections. Previously, jabberd2.1 didn't support having two different sets of supported SASL mechanisms, so I coded up a quick patch to implement this. It's worth noting that clients such as iChat, which use pre-standardisation authentication mechanisms submit their password despite the server telling them not to. This means that the password will be exposed, regardless of the server setting. Ho hum.

Next step is creating a migration script for the user rosters (as we're moving from machine.example.org => example.org for JIDs)

Sunday, 25 February 2007

Gaim, Kerberos and Cyrus SASL

Some time ago, I added Cyrus SASL support to Gaim, so that it could do Kerberos authentication to Jabber servers. As we've developed our Jabber service locally some issues with this support has emerged.

Firstly, there's been a bug introduced which causes connections to hang if a security layer is negotiated. The fix for this is in the Gaim patch tracker.

Secondly, the code uses the user's domain name as the server name when establishing a SASL connection. This doesn't affect the 'normal' DIGEST-MD5 and PLAIN mechanisms, and also has no effect in situations where the hostname matches the domain of the user. It does, however, cause GSSAPI connections to fail when contact a server whose hostname is different from the user's domain (for example, servers that are located through SRV, rather than A records). Again, there's a fix for this in the Gaim patch tracker.

The final change is a functionality change. When I originally wrote my patch, I changed the Jabber protocol definition to indicate that passwords were optional. Whilst this stopped Gaim from prompting for a password whilst doing GSSAPI authentication, it broke any other mechanism that actually required passwords. That bit of the change was quickly reverted! However, it is useful to not have to enter a password when authenticating using a mechanism that doesn't require it.

It turns out that if you don't register a password calllback with Cyrus SASL, it will not attempt any mechanisms that require passwords. Using this, it's possible to prompt for passwords as required, rather than mandate them for a connection. This allows both GSSAPI usage without a password, with fallback to password prompting for other mechanisms. I've just uploaded the patch for this to the Gaim tracker.

GSSAPI support in Thunderbird

The GSSAPI support in Thunderbird has never returned particularly great error messages. In particular, if the server offers GSSAPI, and nothing else, you'll get told that the server doesn't support secure authentication when login fails.

For some reason, this error message seems to annoy people ...

We can't give 'real' error messages whenever GSSAPI fails, because we try GSSAPI whenever the server offers it, and there are lots of broken Linux installations out there which offer GSSAPI whenever the appropriate libraries are installed, regardless of whether the server has suitable key material or not.

So, it looks like Thunderbird needs to have some UI to say whether GSSAPI is supported or not. Of course, Jeff Altman said as much back in 2005...