From f5307d0d0b283569003b15b47350ca571708af7e Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Sun, 8 Dec 2002 03:15:44 +0000 Subject: [PATCH] new certificate presentation (easier ui separation for ssl cert check, only hook missing) --- ChangeLog.claws | 11 ++ configure.in | 2 +- src/gtk/Makefile.am | 3 +- src/gtk/sslcertwindow.c | 246 ++++++++++++++++++++++++++++++++++++++++ src/gtk/sslcertwindow.h | 41 +++++++ src/ssl_certificate.c | 61 +++++----- src/ssl_certificate.h | 2 + src/ssl_manager.c | 11 +- 8 files changed, 332 insertions(+), 45 deletions(-) create mode 100644 src/gtk/sslcertwindow.c create mode 100644 src/gtk/sslcertwindow.h diff --git a/ChangeLog.claws b/ChangeLog.claws index 117e2954c..fd933620c 100644 --- a/ChangeLog.claws +++ b/ChangeLog.claws @@ -1,3 +1,14 @@ +2002-12-08 [colin] 0.8.6claws71 + + * src/gtk/sslcertwindow.[ch] ** NEW ** + new certificate presentation + * src/gtk/Makefile.am + add new files + * src/ssl_certificate.[ch] + gtk cleanup, made utility functions public + * src/ssl_manager.c + use new cert presentation + 2002-12-07 [christoph] 0.8.6claws70 * src/Makefile.am diff --git a/configure.in b/configure.in index b9613917c..2360ac084 100644 --- a/configure.in +++ b/configure.in @@ -11,7 +11,7 @@ MINOR_VERSION=8 MICRO_VERSION=6 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=claws70 +EXTRA_VERSION=claws71 VERSION=$MAJOR_VERSION.$MINOR_VERSION.$MICRO_VERSION$EXTRA_VERSION dnl set $target diff --git a/src/gtk/Makefile.am b/src/gtk/Makefile.am index a683d6e79..0a2c85c5c 100644 --- a/src/gtk/Makefile.am +++ b/src/gtk/Makefile.am @@ -1,7 +1,8 @@ noinst_LTLIBRARIES = libsylpheedgtk.la libsylpheedgtk_la_SOURCES = \ - gtksctree.c gtksctree.h + gtksctree.c gtksctree.h \ + sslcertwindow.c sslcertwindow.h INCLUDES = \ $(GTK_CFLAGS) diff --git a/src/gtk/sslcertwindow.c b/src/gtk/sslcertwindow.c new file mode 100644 index 000000000..cb1829764 --- /dev/null +++ b/src/gtk/sslcertwindow.c @@ -0,0 +1,246 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if USE_SSL + +#include +#include +#include +#include "../common/intl.h" +#include "../ssl_certificate.h" +#include "../common/utils.h" +#include "../alertpanel.h" + +GtkWidget *cert_presenter(SSLCertificate *cert) +{ + GtkWidget *vbox = NULL; + GtkWidget *hbox = NULL; + GtkWidget *frame_owner = NULL; + GtkWidget *frame_signer = NULL; + GtkWidget *frame_status = NULL; + GtkTable *owner_table = NULL; + GtkTable *signer_table = NULL; + GtkTable *status_table = NULL; + GtkWidget *label = NULL; + char *ret, buf[100]; + char *issuer_commonname, *issuer_location, *issuer_organization; + char *subject_commonname, *subject_location, *subject_organization; + char *fingerprint, *sig_status; + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + + /* issuer */ + if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), + NID_commonName, buf, 100) >= 0) + issuer_commonname = g_strdup(buf); + else + issuer_commonname = g_strdup(_("")); + if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), + NID_localityName, buf, 100) >= 0) { + issuer_location = g_strdup(buf); + if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), + NID_countryName, buf, 100) >= 0) + issuer_location = g_strconcat(issuer_location,", ",buf, NULL); + } else if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), + NID_countryName, buf, 100) >= 0) + issuer_location = g_strdup(buf); + else + issuer_location = g_strdup(_("")); + + if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), + NID_organizationName, buf, 100) >= 0) + issuer_organization = g_strdup(buf); + else + issuer_organization = g_strdup(_("")); + + /* subject */ + if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), + NID_commonName, buf, 100) >= 0) + subject_commonname = g_strdup(buf); + else + subject_commonname = g_strdup(_("")); + if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), + NID_localityName, buf, 100) >= 0) { + subject_location = g_strdup(buf); + if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), + NID_countryName, buf, 100) >= 0) + subject_location = g_strconcat(subject_location,", ",buf, NULL); + } else if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), + NID_countryName, buf, 100) >= 0) + subject_location = g_strdup(buf); + else + subject_location = g_strdup(_("")); + + if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), + NID_organizationName, buf, 100) >= 0) + subject_organization = g_strdup(buf); + else + subject_organization = g_strdup(_("")); + + /* fingerprint */ + X509_digest(cert->x509_cert, EVP_md5(), md, &n); + fingerprint = readable_fingerprint(md, (int)n); + + /* signature */ + sig_status = ssl_certificate_check_signer(cert->x509_cert); + + if (sig_status==NULL) + sig_status = g_strdup(_("correct")); + + vbox = gtk_vbox_new(FALSE, 5); + hbox = gtk_hbox_new(FALSE, 5); + + frame_owner = gtk_frame_new(_("Owner")); + frame_signer = gtk_frame_new(_("Signer")); + frame_status = gtk_frame_new(_("Status")); + + owner_table = gtk_table_new(3, 2, FALSE); + signer_table = gtk_table_new(3, 2, FALSE); + status_table = gtk_table_new(2, 2, FALSE); + + label = gtk_label_new(_("Name: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(owner_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(subject_commonname); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(owner_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Organization: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(owner_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(subject_organization); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(owner_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Location: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(owner_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(subject_location); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(owner_table, label, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Name: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(signer_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(issuer_commonname); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(signer_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Organization: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(signer_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(issuer_organization); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(signer_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Location: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(signer_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(issuer_location); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(signer_table, label, 1, 2, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + label = gtk_label_new(_("Fingerprint: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(status_table, label, 0, 1, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(fingerprint); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(status_table, label, 1, 2, 0, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(_("Signature status: ")); + gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); + gtk_table_attach(status_table, label, 0, 1, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + label = gtk_label_new(sig_status); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_table_attach(status_table, label, 1, 2, 1, 2, GTK_EXPAND|GTK_FILL, 0, 0, 0); + + gtk_container_add(GTK_CONTAINER(frame_owner), GTK_WIDGET(owner_table)); + gtk_container_add(GTK_CONTAINER(frame_signer), GTK_WIDGET(signer_table)); + gtk_container_add(GTK_CONTAINER(frame_status), GTK_WIDGET(status_table)); + + gtk_box_pack_end(GTK_BOX(hbox), frame_signer, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(hbox), frame_owner, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), frame_status, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), hbox, TRUE, TRUE, 0); + + gtk_widget_show_all(vbox); + + g_free(issuer_commonname); + g_free(issuer_location); + g_free(issuer_organization); + g_free(subject_commonname); + g_free(subject_location); + g_free(subject_organization); + g_free(fingerprint); + g_free(sig_status); + + return vbox; +} + +void sslcertwindow_show_cert(SSLCertificate *cert) +{ + GtkWidget *cert_widget = cert_presenter(cert); + gchar *buf; + + buf = g_strdup_printf(_("SSL certificate for %s"), cert->host); + alertpanel_with_widget(buf, NULL, _("OK"), NULL, NULL, cert_widget); + g_free(buf); +} + +gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert) +{ + GtkWidget *cert_widget = cert_presenter(cert); + gchar *buf; + AlertValue val; + buf = g_strdup_printf(_("Do you want to accept SSL certificate for %s?"), cert->host); + val = alertpanel_with_widget(_("Unknown SSL Certificate"), buf, _("Accept and save"), _("Cancel connection"), NULL, cert_widget); + g_free(buf); + return (val == G_ALERTDEFAULT); +} + +gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCertificate *new_cert) +{ + GtkWidget *old_cert_widget = cert_presenter(old_cert); + GtkWidget *new_cert_widget = cert_presenter(new_cert); + GtkWidget *vbox; + GtkWidget *label; + gchar *buf; + AlertValue val; + + vbox = gtk_vbox_new(FALSE, 5); + label = gtk_label_new(_("New certificate:")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_box_pack_end(GTK_BOX(vbox), new_cert_widget, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), label, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), gtk_hseparator_new(), TRUE, TRUE, 0); + label = gtk_label_new(_("Known certificate:")); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + gtk_box_pack_end(GTK_BOX(vbox), old_cert_widget, TRUE, TRUE, 0); + gtk_box_pack_end(GTK_BOX(vbox), label, TRUE, TRUE, 0); + gtk_widget_show_all(vbox); + + buf = g_strdup_printf(_("Do you want to accept new SSL certificate for %s?"), new_cert->host); + val = alertpanel_with_widget(_("Changed SSL Certificate"), buf, _("Accept and save"), _("Cancel connection"), NULL, vbox); + g_free(buf); + return (val == G_ALERTDEFAULT); +} +#endif diff --git a/src/gtk/sslcertwindow.h b/src/gtk/sslcertwindow.h new file mode 100644 index 000000000..715876b65 --- /dev/null +++ b/src/gtk/sslcertwindow.h @@ -0,0 +1,41 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2001 Hiroyuki Yamamoto + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __SSL_CERTWINDOW_H__ +#define __SSL_CERTWINDOW_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if USE_SSL + +#include +#include +#include +#include +#include "../ssl_certificate.h" + +GtkWidget *cert_presenter(SSLCertificate *cert); +void sslcertwindow_show_cert(SSLCertificate *cert); +gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert); +gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCertificate *new_cert); + +#endif /* USE_SSL */ +#endif /* __SSL_CERTWINDOW_H__ */ diff --git a/src/ssl_certificate.c b/src/ssl_certificate.c index ab02fa31b..62a2be5da 100644 --- a/src/ssl_certificate.c +++ b/src/ssl_certificate.c @@ -26,14 +26,11 @@ #include #include #include "ssl_certificate.h" -#include "alertpanel.h" +#include "sslcertwindow.h" #include "utils.h" #include "intl.h" #include "prefs_common.h" -#include "socket.h" -#include "log.h" -static char *ssl_certificate_check_signer (X509 *cert); static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host, gushort port, gboolean lookup); static char * get_fqdn(char *host) @@ -50,7 +47,7 @@ static char * get_fqdn(char *host) return g_strdup(hp->h_name); } -static char * readable_fingerprint(unsigned char *src, int len) +char * readable_fingerprint(unsigned char *src, int len) { int i=0; char * ret; @@ -115,7 +112,7 @@ static void ssl_certificate_save (SSLCertificate *cert) fp = fopen(file, "wb"); if (fp == NULL) { g_free(file); - alertpanel_error(_("Can't save certificate !")); + debug_print("Can't save certificate !\n"); return; } i2d_X509_fp(fp, cert->x509_cert); @@ -293,7 +290,7 @@ static gboolean ssl_certificate_compare (SSLCertificate *cert_a, SSLCertificate return FALSE; } -static char *ssl_certificate_check_signer (X509 *cert) +char *ssl_certificate_check_signer (X509 *cert) { X509_STORE_CTX store_ctx; X509_STORE *store; @@ -346,7 +343,7 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *host, gushort port) known_cert = ssl_certificate_find (host, port); if (known_cert == NULL) { - gint val; + gboolean val; gchar *err_msg, *cur_cert_str, *sig_status; sig_status = ssl_certificate_check_signer(x509_cert); @@ -380,24 +377,22 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *host, gushort port) g_free(err_msg); return FALSE; } - - val = alertpanel(_("Warning"), - err_msg, - _("Accept and save"), _("Cancel connection"), NULL); + + /* FIXME: replace this with a hook, then uncomment the check in ssl.c */ + val = sslcertwindow_ask_new_cert(current_cert); g_free(err_msg); - switch (val) { - case G_ALERTALTERNATE: - ssl_certificate_destroy(current_cert); - return FALSE; - default: - ssl_certificate_save(current_cert); - ssl_certificate_destroy(current_cert); - return TRUE; + if (!val) { + ssl_certificate_destroy(current_cert); + return FALSE; + } else { + ssl_certificate_save(current_cert); + ssl_certificate_destroy(current_cert); + return TRUE; } } else if (!ssl_certificate_compare (current_cert, known_cert)) { - gint val; + gboolean val; gchar *err_msg, *known_cert_str, *cur_cert_str; known_cert_str = ssl_certificate_to_string(known_cert); @@ -417,21 +412,19 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *host, gushort port) return FALSE; } - val = alertpanel(_("Warning"), - err_msg, - _("Accept and save"), _("Cancel connection"), NULL); + /* FIXME: replace this with a hook, then uncomment the check in ssl.c */ + val = sslcertwindow_ask_changed_cert(known_cert, current_cert); g_free(err_msg); - switch (val) { - case G_ALERTALTERNATE: - ssl_certificate_destroy(current_cert); - ssl_certificate_destroy(known_cert); - return FALSE; - default: - ssl_certificate_save(current_cert); - ssl_certificate_destroy(current_cert); - ssl_certificate_destroy(known_cert); - return TRUE; + if (!val) { + ssl_certificate_destroy(current_cert); + ssl_certificate_destroy(known_cert); + return FALSE; + } else { + ssl_certificate_save(current_cert); + ssl_certificate_destroy(current_cert); + ssl_certificate_destroy(known_cert); + return TRUE; } } diff --git a/src/ssl_certificate.h b/src/ssl_certificate.h index 371174e07..9c7070474 100644 --- a/src/ssl_certificate.h +++ b/src/ssl_certificate.h @@ -45,6 +45,8 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *host, gushort port); char* ssl_certificate_to_string(SSLCertificate *cert); void ssl_certificate_destroy(SSLCertificate *cert); void ssl_certificate_delete_from_disk(SSLCertificate *cert); +char * readable_fingerprint(unsigned char *src, int len); +char *ssl_certificate_check_signer (X509 *cert); #endif /* USE_SSL */ #endif /* SSL_CERTIFICATE_H */ diff --git a/src/ssl_manager.c b/src/ssl_manager.c index df28513b3..16be64dac 100644 --- a/src/ssl_manager.c +++ b/src/ssl_manager.c @@ -34,6 +34,7 @@ #include "intl.h" #include "gtksctree.h" #include "alertpanel.h" +#include "sslcertwindow.h" static struct SSLManager { @@ -232,8 +233,6 @@ static void ssl_manager_view_cb(GtkWidget *widget, { SSLCertificate *cert; GList *rowlist; - gchar *cert_str; - gchar *str; rowlist = GTK_CLIST(manager.certlist)->selection; if (!rowlist) @@ -246,13 +245,7 @@ static void ssl_manager_view_cb(GtkWidget *widget, if (!cert) return; - cert_str = ssl_certificate_to_string(cert); - str = g_strconcat(_("SSL certificate for "),cert->host, ":\n\n", cert_str, NULL); - alertpanel(_("SSL Certificate"), - str, - _("OK"), NULL, NULL); - g_free(str); - g_free(cert_str); + sslcertwindow_show_cert(cert); } -- 2.25.1