# HG changeset patch # User Paul Aurich # Date 1296409862 0 # Node ID e89df17f5ae79128014a798963c578c54e2e94bc # Parent 78e68751cc4039edb2b15226283dac03e2730c65 certificate: Better validation of chains which have an intermediate signed w/ MD5. We already distribute the CAcert class 3 root as a trusted root. Newer versions of GnuTLS (combined with the changes to deal with MSN's cert breakage) require us to check if the last cert (not just its issuer) is in our trusted store. diff -r 78e68751cc40 -r e89df17f5ae7 ChangeLog --- a/ChangeLog Wed Jan 26 02:58:37 2011 +0000 +++ b/ChangeLog Sun Jan 30 17:51:02 2011 +0000 @@ -10,6 +10,8 @@ * Perl bindings now respect LDFLAGS. (Peter Volkov, Markos Chandras) (#12638) * Added AddTrust External Root CA. (#11554) + * Resolve some issues validating X.509 certificates signed off the CAcert + Class 3 intermediate cert when using the GnuTLS SSL/TLS plugin. Groupwise: * Don't show two windows when using "Get Info" on a buddy. (Gabriel Burt; diff -r 78e68751cc40 -r e89df17f5ae7 libpurple/certificate.c --- a/libpurple/certificate.c Wed Jan 26 02:58:37 2011 +0000 +++ b/libpurple/certificate.c Sun Jan 30 17:51:02 2011 +0000 @@ -1602,7 +1602,7 @@ GSList *ca_crts, *cur; GByteArray *last_fpr, *ca_fpr; gboolean valid = FALSE; - gchar *ca_id; + gchar *ca_id, *ca2_id; peer_crt = (PurpleCertificate *) chain->data; @@ -1668,7 +1668,9 @@ return; } /* if (signature chain not good) */ - /* Next, attempt to verify the last certificate against a CA */ + /* Next, attempt to verify the last certificate is signed by a trusted + * CA, or is a trusted CA (based on fingerprint). + */ /* If, for whatever reason, there is no Certificate Authority pool loaded, we'll verify the subject name and then warn about thsi. */ if ( !ca ) { @@ -1684,27 +1686,31 @@ end_crt = g_list_last(chain)->data; - /* Attempt to look up the last certificate's issuer */ - ca_id = purple_certificate_get_issuer_unique_id(end_crt); + /* Attempt to look up the last certificate, and the last certificate's + * issuer. + */ + ca_id = purple_certificate_get_issuer_unique_id(end_crt); + ca2_id = purple_certificate_get_unique_id(end_crt); purple_debug_info("certificate/x509/tls_cached", "Checking for a CA with DN=%s\n", ca_id); - ca_crts = x509_ca_get_certs(ca_id); + purple_debug_info("certificate/x509/tls_cached", + "Also checking for a CA with DN=%s\n", + ca2_id); + ca_crts = g_slist_concat(x509_ca_get_certs(ca_id), x509_ca_get_certs(ca2_id)); + g_free(ca_id); + g_free(ca2_id); if ( NULL == ca_crts ) { flags |= PURPLE_CERTIFICATE_CA_UNKNOWN; purple_debug_warning("certificate/x509/tls_cached", - "Certificate Authority with DN='%s' not " - "found. I'll prompt the user, I guess.\n", - ca_id); - g_free(ca_id); + "No Certificate Authorities with either DN found " + "found. I'll prompt the user, I guess.\n"); x509_tls_cached_check_subject_name(vrq, flags); return; } - g_free(ca_id); - /* * Check the fingerprints; if they match, then this certificate *is* one * of the designated "trusted roots", and we don't need to verify the @@ -1714,10 +1720,6 @@ * * If the fingerprints don't match, we'll fall back to checking the * signature. - * - * GnuTLS doesn't seem to include the final root in the verification - * list, so this check will never succeed. NSS *does* include it in - * the list, so here we are. */ last_fpr = purple_certificate_get_fingerprint_sha1(end_crt); for (cur = ca_crts; cur; cur = cur->next) {