XMPP SSL client certificates

Paul Aurich darkrain42 at pidgin.im
Thu Jul 30 16:43:01 EDT 2009


And Michal Witkowski spoke on 07/29/2009 07:57 AM, saying:
> Hi,
> 
> I've been working on implementing XEP-0178 compatible client2server SASL External 
> authentication for jabberd2 (https://bugs.launchpad.net/jabberd2/+bug/405233). I've 
> already tested this implementation with a pyXmpp Python XMPP library and I would like to 
> implement SASL External authentication (based on TLS certificates) in Pidgin. While 
> implementing SASL External negotiation is trivial, assigning client certificates to TLS 
> connections isn't as simple in Purple code.

Cool!

> I took a short glimpse at the current structure of Pidgin and I see two approaches.
> 
> 1. Make a client cert/client key field in PurpleAccount/PurpleConnection, which would be 
> operated from the Account settings dialog box. Then somehow propagate the information (by 
> possibly modifying other data structures) right up to ssl-gnutls and explicitly set the 
> connection credentials using SSL_CTX_use_certificate_file and SSL_CTX_use_PrivateKey_file. 
> 
> This approach is a bit hackish, yet simple. The user could set the certificates per 
> account explicitly, encouraging the feel that the certificate is not only used for SSL but 
> also for auth. However, this approach would require some modifications to key data 
> structures. Would this be a really bad thing or is it acceptable?

I think this solution is pretty close to how I'd imagine it.  Protocols can
add account options to the "Modify Account" dialog, so one way to do this
would be to have the XMPP protocol add a "SSL Private Key" option which
opens a file selection dialog*.

Then, I think we'd need to have a purple_ssl_connect_with_private_key
function (or similar, we'd probably also need a
purple_ssl_connect_with_fd_and_private_key, since I assume this also needs
to work with STARTTLS), which, as you said, propagates that private key up
to the SSL plugin.

Does that make sense and seem reasonable?

* This isn't currently supported. Pidgin only implements support for
account options of type bool, int, string, and list, so as a first step,
you could just use a string and treat it as a file path.

> 
> 2. Another approach is to rely on PurpleCertificatePool for storing client certificates. 
> This would require adding another statically (for example 'client_certs) created pool of 
> certificates (next to 'tls_peers'). ssl-gnutls would then rely on 
> (http://www.gnu.org/software/gnutls/manual/html_node/Using-a-callback-to-select-the-
> certificate-to-use.html) a callback function to match the server-acceptable CA's against 
> certificates in this pool. 
> 
> While elegant, this approach is complicated. PurpleCertificatePool, as far as I can see, 
> doesn't support looking up certificates by issuer DN, only by subject DN. Support for 
> issuer DN lookup would have to be added. Additonally, RSA key support is missing. I've 
> tested the certificate manager by importing a PEM file containg a x509 cert with a RSA 
> key. Only the x509 was read. That comes as no suprise, since ssl-gnutls only imports x509 
> parts of datums. After scoping around I found that the certificate manager code is hard to 
> modify in order to accomodate private key handling, although I can be missing some obvious 
> ways of doing it.

Right, it currently only supports the public parts. I think it would
require a fair amount of work to get it to support private keys.

That said, this approach does have the benefit of "automagically" working
for any account where the server advertises support for accepting private keys.

My one concern (and I have no idea how valid of a use-case this is) is what
about when people *don't* want to be using the private key to identify
themselves. Say someone has multiple identities on a server and only wants
to use a certificate for one of them. Although it might be possible to use
the request API so that libpurple could present the user with a dialog (the
first time through? every time? have an option to forget the binding?):

	The server <example.com> allows you to identify yourself with
	an SSL Certificate. Please select one:
	   * No public certificate  (default)
	   * <paul at example.com>
	   * <alice at example.com>
	<GO!> <Give up>

(it's just an idea).

> 
> If anyone has any suggestions as to how to proceed, please let me know.
> 
> Cheers,
> Michal

Does that help? I'm not sure which of these is better (though I know of a
few people who are going to yell at me for suggesting *more* account
options for XMPP ;) ), but perhaps there's a way to integrate a generic
directory full of public keys with an account option? :)

~Paul




More information about the Devel mailing list