# HG changeset patch # User Stu Tomlinson # Date 1290477030 0 # Node ID 43af903bd8166f758cd8c456c8506cfd4a937ddc # Parent a467e55ec3c7bfc98f25e9e1ed2c79487d31a756 NSS will not return invalid or irrelevant intermediate certificates that the server presented as part of the certificate chain. GnuTLS, however, will return them, which breaks our certificate validation when the server is mis-configured. This fixes our GnuTLS SSL plugin to discard any certificate (and subsequent certs) in the chain if it did not sign the previous certificate. This allows GnuTLS users to connect to omega.contacts.msn.com while it is still misconfigured. diff -r a467e55ec3c7 -r 43af903bd816 libpurple/plugins/ssl/ssl-gnutls.c --- a/libpurple/plugins/ssl/ssl-gnutls.c Mon Nov 22 10:50:32 2010 +0000 +++ b/libpurple/plugins/ssl/ssl-gnutls.c Tue Nov 23 01:50:30 2010 +0000 @@ -520,11 +520,18 @@ /* Forward declarations are fun! */ static PurpleCertificate * x509_import_from_datum(const gnutls_datum dt, gnutls_x509_crt_fmt mode); +/* indeed! */ +static gboolean +x509_certificate_signed_by(PurpleCertificate * crt, + PurpleCertificate * issuer); +static void +x509_destroy_certificate(PurpleCertificate * crt); static GList * ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) { PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); + PurpleCertificate *prvcrt = NULL; /* List of Certificate instances to return */ GList * peer_certs = NULL; @@ -550,7 +557,17 @@ /* Append is somewhat inefficient on linked lists, but is easy to read. If someone complains, I'll change it. TODO: Is anyone complaining? (Maybe elb?) */ - peer_certs = g_list_append(peer_certs, newcrt); + /* only append if previous cert was actually signed by this one. + * Thanks Microsoft. */ + if ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt)) { + peer_certs = g_list_append(peer_certs, newcrt); + prvcrt = newcrt; + } else { + x509_destroy_certificate(newcrt); + purple_debug_error("gnutls", "Dropping further peer certificates " + "because the chain is broken!\n"); + break; + } } /* cert_list doesn't need free()-ing */