comparison libpurple/plugins/ssl/ssl-gnutls.c @ 30959: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 df9de37e0274
children fb0c5aa0fe55
comparison
equal deleted inserted replaced
30958:a467e55ec3c7 30959:43af903bd816
518 } 518 }
519 519
520 /* Forward declarations are fun! */ 520 /* Forward declarations are fun! */
521 static PurpleCertificate * 521 static PurpleCertificate *
522 x509_import_from_datum(const gnutls_datum dt, gnutls_x509_crt_fmt mode); 522 x509_import_from_datum(const gnutls_datum dt, gnutls_x509_crt_fmt mode);
523 /* indeed! */
524 static gboolean
525 x509_certificate_signed_by(PurpleCertificate * crt,
526 PurpleCertificate * issuer);
527 static void
528 x509_destroy_certificate(PurpleCertificate * crt);
523 529
524 static GList * 530 static GList *
525 ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc) 531 ssl_gnutls_get_peer_certificates(PurpleSslConnection * gsc)
526 { 532 {
527 PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc); 533 PurpleSslGnutlsData *gnutls_data = PURPLE_SSL_GNUTLS_DATA(gsc);
534 PurpleCertificate *prvcrt = NULL;
528 535
529 /* List of Certificate instances to return */ 536 /* List of Certificate instances to return */
530 GList * peer_certs = NULL; 537 GList * peer_certs = NULL;
531 538
532 /* List of raw certificates as given by GnuTLS */ 539 /* List of raw certificates as given by GnuTLS */
548 PurpleCertificate * newcrt = x509_import_from_datum(cert_list[i], 555 PurpleCertificate * newcrt = x509_import_from_datum(cert_list[i],
549 GNUTLS_X509_FMT_DER); 556 GNUTLS_X509_FMT_DER);
550 /* Append is somewhat inefficient on linked lists, but is easy 557 /* Append is somewhat inefficient on linked lists, but is easy
551 to read. If someone complains, I'll change it. 558 to read. If someone complains, I'll change it.
552 TODO: Is anyone complaining? (Maybe elb?) */ 559 TODO: Is anyone complaining? (Maybe elb?) */
553 peer_certs = g_list_append(peer_certs, newcrt); 560 /* only append if previous cert was actually signed by this one.
561 * Thanks Microsoft. */
562 if ((prvcrt == NULL) || x509_certificate_signed_by(prvcrt, newcrt)) {
563 peer_certs = g_list_append(peer_certs, newcrt);
564 prvcrt = newcrt;
565 } else {
566 x509_destroy_certificate(newcrt);
567 purple_debug_error("gnutls", "Dropping further peer certificates "
568 "because the chain is broken!\n");
569 break;
570 }
554 } 571 }
555 572
556 /* cert_list doesn't need free()-ing */ 573 /* cert_list doesn't need free()-ing */
557 574
558 return peer_certs; 575 return peer_certs;