Mercurial > pidgin.yaz
changeset 31400:43af903bd816
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.
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Tue, 23 Nov 2010 01:50:30 +0000 |
parents | a467e55ec3c7 |
children | 27c56e6b5fa6 |
files | libpurple/plugins/ssl/ssl-gnutls.c |
diffstat | 1 files changed, 18 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- 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 */