From b73f2b5f0e2e34326193fe8c5eff99127a33fa54 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Thu, 9 Aug 2012 11:32:26 +0000 Subject: [PATCH] 2012-08-09 [colin] 3.8.1cvs26 * src/common/ssl.c * src/common/ssl_certificate.c * src/common/ssl_certificate.h * src/gtk/sslcertwindow.c Fix bug 2718, "Failure to check peer hostname when checking certificate" --- ChangeLog | 9 ++++++ PATCHSETS | 1 + configure.ac | 2 +- src/common/ssl.c | 1 + src/common/ssl_certificate.c | 18 +++++++++++ src/common/ssl_certificate.h | 4 +-- src/gtk/sslcertwindow.c | 61 ++++++++++++++++++++++++++++++------ 7 files changed, 84 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5ec622aca..7fd9f439b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-08-09 [colin] 3.8.1cvs26 + + * src/common/ssl.c + * src/common/ssl_certificate.c + * src/common/ssl_certificate.h + * src/gtk/sslcertwindow.c + Fix bug 2718, "Failure to check peer hostname + when checking certificate" + 2012-08-05 [ticho] 3.8.1cvs25 * src/compose.c diff --git a/PATCHSETS b/PATCHSETS index b385b31fb..03c77c352 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -4400,3 +4400,4 @@ ( cvs diff -u -r 1.5.2.63 -r 1.5.2.64 src/gtk/pluginwindow.c; cvs diff -u -r 1.12.2.61 -r 1.12.2.62 src/gtk/prefswindow.c; ) > 3.8.1cvs23.patchset ( cvs diff -u -r 1.382.2.605 -r 1.382.2.606 src/compose.c; ) > 3.8.1cvs24.patchset ( cvs diff -u -r 1.382.2.606 -r 1.382.2.607 src/compose.c; ) > 3.8.1cvs25.patchset +( cvs diff -u -r 1.9.2.53 -r 1.9.2.54 src/common/ssl.c; cvs diff -u -r 1.4.2.43 -r 1.4.2.44 src/common/ssl_certificate.c; cvs diff -u -r 1.1.4.19 -r 1.1.4.20 src/common/ssl_certificate.h; cvs diff -u -r 1.9.2.35 -r 1.9.2.36 src/gtk/sslcertwindow.c; ) > 3.8.1cvs26.patchset diff --git a/configure.ac b/configure.ac index 8b958d788..d1394f2e2 100644 --- a/configure.ac +++ b/configure.ac @@ -12,7 +12,7 @@ MINOR_VERSION=8 MICRO_VERSION=1 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=25 +EXTRA_VERSION=26 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/common/ssl.c b/src/common/ssl.c index e1f3e8065..9e8b242b7 100644 --- a/src/common/ssl.c +++ b/src/common/ssl.c @@ -105,6 +105,7 @@ const gchar *claws_ssl_get_cert_file(void) const char *cert_files[]={ "/etc/pki/tls/certs/ca-bundle.crt", "/etc/certs/ca-bundle.crt", + "/etc/ssl/ca-bundle.pem", "/usr/share/ssl/certs/ca-bundle.crt", "/etc/ssl/certs/ca-certificates.crt", "/usr/local/ssl/certs/ca-bundle.crt", diff --git a/src/common/ssl_certificate.c b/src/common/ssl_certificate.c index a25e891e1..efc5c53e3 100644 --- a/src/common/ssl_certificate.c +++ b/src/common/ssl_certificate.c @@ -834,4 +834,22 @@ void ssl_certificate_get_x509_and_pkey_from_p12_file(const gchar *file, const gc gnutls_pkcs12_deinit(p12); } } + +gboolean ssl_certificate_check_subject_cn(SSLCertificate *cert) +{ + return gnutls_x509_crt_check_hostname(cert->x509_cert, cert->host) != 0; +} + +gchar *ssl_certificate_get_subject_cn(SSLCertificate *cert) +{ + gchar subject_cn[BUFFSIZE]; + size_t n = BUFFSIZE; + + if(gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, + GNUTLS_OID_X520_COMMON_NAME, 0, 0, subject_cn, &n)) + strncpy(subject_cn, _(""), BUFFSIZE); + + return g_strdup(subject_cn); +} + #endif /* USE_GNUTLS */ diff --git a/src/common/ssl_certificate.h b/src/common/ssl_certificate.h index f5380ed46..0b6dce51e 100644 --- a/src/common/ssl_certificate.h +++ b/src/common/ssl_certificate.h @@ -63,13 +63,13 @@ void ssl_certificate_delete_from_disk(SSLCertificate *cert); char * readable_fingerprint(unsigned char *src, int len); char *ssl_certificate_check_signer (gnutls_x509_crt cert, guint status); -#ifdef USE_GNUTLS gnutls_x509_crt ssl_certificate_get_x509_from_pem_file(const gchar *file); gnutls_x509_privkey ssl_certificate_get_pkey_from_pem_file(const gchar *file); void ssl_certificate_get_x509_and_pkey_from_p12_file(const gchar *file, const gchar *password, gnutls_x509_crt *crt, gnutls_x509_privkey *key); size_t gnutls_i2d_X509(gnutls_x509_crt x509_cert, unsigned char **output); size_t gnutls_i2d_PrivateKey(gnutls_x509_privkey pkey, unsigned char **output); -#endif +gboolean ssl_certificate_check_subject_cn(SSLCertificate *cert); +gchar *ssl_certificate_get_subject_cn(SSLCertificate *cert); #endif /* USE_GNUTLS */ #endif /* SSL_CERTIFICATE_H */ diff --git a/src/gtk/sslcertwindow.c b/src/gtk/sslcertwindow.c index 9b7b4c5b3..f954eef6c 100644 --- a/src/gtk/sslcertwindow.c +++ b/src/gtk/sslcertwindow.c @@ -285,6 +285,7 @@ static gboolean sslcert_ask_hook(gpointer source, gpointer data) } else { hookdata->accept = sslcertwindow_ask_changed_cert(hookdata->old_cert, hookdata->cert); } + return TRUE; } @@ -304,6 +305,24 @@ void sslcertwindow_show_cert(SSLCertificate *cert) g_free(buf); } +static gchar *sslcertwindow_get_invalid_str(SSLCertificate *cert) +{ + gchar *subject_cn = NULL; + gchar *str = NULL; + + if (ssl_certificate_check_subject_cn(cert)) + return g_strdup(""); + + subject_cn = ssl_certificate_get_subject_cn(cert); + + str = g_strdup_printf(_("Certificate is for %s, but connection is to %s.\n" + "You may be connecting to a rogue server.\n\n"), + subject_cn, cert->host); + g_free(subject_cn); + + return str; +} + static gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert) { gchar *buf, *sig_status; @@ -312,9 +331,11 @@ static gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert) GtkWidget *label; GtkWidget *button; GtkWidget *cert_widget; - + gchar *invalid_str = sslcertwindow_get_invalid_str(cert); + const gchar *title; + vbox = gtk_vbox_new(FALSE, 5); - buf = g_strdup_printf(_("Certificate for %s is unknown.\nDo you want to accept it?"), cert->host); + buf = g_strdup_printf(_("Certificate for %s is unknown.\n%sDo you want to accept it?"), cert->host, invalid_str); label = gtk_label_new(buf); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); @@ -337,7 +358,12 @@ static gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert) cert_widget = cert_presenter(cert); gtk_container_add(GTK_CONTAINER(button), cert_widget); - val = alertpanel_full(_("Unknown SSL Certificate"), NULL, + if (!ssl_certificate_check_subject_cn(cert)) + title = _("SSL certificate is invalid"); + else + title = _("SSL Certificate is unknown"); + + val = alertpanel_full(title, NULL, _("_Cancel connection"), _("_Accept and save"), NULL, FALSE, vbox, ALERT_QUESTION, G_ALERTDEFAULT); @@ -352,9 +378,13 @@ static gboolean sslcertwindow_ask_expired_cert(SSLCertificate *cert) GtkWidget *label; GtkWidget *button; GtkWidget *cert_widget; - + gchar *invalid_str = sslcertwindow_get_invalid_str(cert); + const gchar *title; + vbox = gtk_vbox_new(FALSE, 5); - buf = g_strdup_printf(_("Certificate for %s is expired.\nDo you want to continue?"), cert->host); + buf = g_strdup_printf(_("Certificate for %s is expired.\n%sDo you want to continue?"), cert->host, invalid_str); + g_free(invalid_str); + label = gtk_label_new(buf); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); @@ -378,7 +408,12 @@ static gboolean sslcertwindow_ask_expired_cert(SSLCertificate *cert) cert_widget = cert_presenter(cert); gtk_container_add(GTK_CONTAINER(button), cert_widget); - val = alertpanel_full(_("Expired SSL Certificate"), NULL, + if (!ssl_certificate_check_subject_cn(cert)) + title = _("SSL certificate is invalid and expired"); + else + title = _("SSL certificate is expired"); + + val = alertpanel_full(title, NULL, _("_Cancel connection"), _("_Accept"), NULL, FALSE, vbox, ALERT_QUESTION, G_ALERTDEFAULT); @@ -395,7 +430,9 @@ static gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCert GtkWidget *label; GtkWidget *button; AlertValue val; - + gchar *invalid_str = sslcertwindow_get_invalid_str(new_cert); + const gchar *title; + vbox = gtk_vbox_new(FALSE, 5); label = gtk_label_new(_("New certificate:")); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); @@ -409,7 +446,9 @@ static gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCert gtk_widget_show_all(vbox); vbox2 = gtk_vbox_new(FALSE, 5); - buf = g_strdup_printf(_("Certificate for %s has changed. Do you want to accept it?"), new_cert->host); + buf = g_strdup_printf(_("Certificate for %s has changed.\n%sDo you want to accept it?"), new_cert->host, invalid_str); + g_free(invalid_str); + label = gtk_label_new(buf); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); @@ -432,7 +471,11 @@ static gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCert gtk_box_pack_start(GTK_BOX(vbox2), button, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(button), vbox); - val = alertpanel_full(_("Changed SSL Certificate"), NULL, + if (!ssl_certificate_check_subject_cn(new_cert)) + title = _("SSL certificate changed and is invalid"); + else + title = _("SSL certificate changed"); + val = alertpanel_full(title, NULL, _("_Cancel connection"), _("_Accept and save"), NULL, FALSE, vbox2, ALERT_WARNING, G_ALERTDEFAULT); -- 2.25.1