new certificate presentation
authorColin Leroy <colin@colino.net>
Sun, 8 Dec 2002 03:15:44 +0000 (03:15 +0000)
committerColin Leroy <colin@colino.net>
Sun, 8 Dec 2002 03:15:44 +0000 (03:15 +0000)
(easier ui separation for ssl cert check, only hook missing)

ChangeLog.claws
configure.in
src/gtk/Makefile.am
src/gtk/sslcertwindow.c [new file with mode: 0644]
src/gtk/sslcertwindow.h [new file with mode: 0644]
src/ssl_certificate.c
src/ssl_certificate.h
src/ssl_manager.c

index 117e295..fd93362 100644 (file)
@@ -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
index b961391..2360ac0 100644 (file)
@@ -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
index a683d6e..0a2c85c 100644 (file)
@@ -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 (file)
index 0000000..cb18297
--- /dev/null
@@ -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 <openssl/ssl.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#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(_("<not in certificate>"));
+       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(_("<not in certificate>"));
+
+       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(_("<not in certificate>"));
+        
+       /* 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(_("<not in certificate>"));
+       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(_("<not in certificate>"));
+
+       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(_("<not in certificate>"));
+        
+       /* 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 (file)
index 0000000..715876b
--- /dev/null
@@ -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 <openssl/ssl.h>
+#include <openssl/objects.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#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__ */
index ab02fa3..62a2be5 100644 (file)
 #include <openssl/ssl.h>
 #include <glib.h>
 #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;
                }
        }
 
index 371174e..9c70704 100644 (file)
@@ -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 */
index df28513..16be64d 100644 (file)
@@ -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);
        
        
 }