From 0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Mon, 26 Feb 2018 11:23:00 +0100 Subject: Initial commit for sylpheed 3.7.0 --- src/sslmanager.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 src/sslmanager.c (limited to 'src/sslmanager.c') diff --git a/src/sslmanager.c b/src/sslmanager.c new file mode 100644 index 0000000..a633710 --- /dev/null +++ b/src/sslmanager.c @@ -0,0 +1,225 @@ +/* + * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client + * Copyright (C) 1999-2014 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 "defs.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ssl.h" +#include "sslmanager.h" +#include "manage_window.h" +#include "prefs_common.h" + +gint ssl_manager_verify_cert(SockInfo *sockinfo, const gchar *hostname, + X509 *server_cert, glong verify_result) +{ + static PangoFontDescription *font_desc; + GtkWidget *dialog; + GtkWidget *hbox; + GtkWidget *image; + GtkWidget *vbox; + GtkWidget *label; + const gchar *title; + GString *message; + gchar *subject, *issuer; + guchar keyid[EVP_MAX_MD_SIZE]; + gchar keyidstr[EVP_MAX_MD_SIZE * 3 + 1] = ""; + guint keyidlen = 0; + gchar *sha1_keyidstr, *md5_keyidstr; + BIO *bio; + gchar not_before[64] = "", not_after[64] = ""; + gint i; + gint result; + gboolean disable_always = FALSE; + + if (verify_result == X509_V_OK) + return 0; + + gdk_threads_enter(); + + title = _("SSL certificate verify failed"); + + subject = X509_NAME_oneline(X509_get_subject_name(server_cert), + NULL, 0); + issuer = X509_NAME_oneline(X509_get_issuer_name(server_cert), NULL, 0); + + bio = BIO_new(BIO_s_mem()); + ASN1_TIME_print(bio, X509_get_notBefore(server_cert)); + BIO_gets(bio, not_before, sizeof(not_before)); + BIO_reset(bio); + ASN1_TIME_print(bio, X509_get_notAfter(server_cert)); + BIO_gets(bio, not_after, sizeof(not_after)); + BIO_free(bio); + + if (X509_digest(server_cert, EVP_sha1(), keyid, &keyidlen)) { + for (i = 0; i < keyidlen; i++) + g_snprintf(keyidstr + i * 3, 4, "%02x:", keyid[i]); + keyidstr[keyidlen * 3 - 1] = '\0'; + sha1_keyidstr = g_ascii_strup(keyidstr, -1); + } else { + sha1_keyidstr = g_strdup("(cannot calculate digest)"); + } + if (X509_digest(server_cert, EVP_md5(), keyid, &keyidlen)) { + for (i = 0; i < keyidlen; i++) + g_snprintf(keyidstr + i * 3, 4, "%02x:", keyid[i]); + keyidstr[keyidlen * 3 - 1] = '\0'; + md5_keyidstr = g_ascii_strup(keyidstr, -1); + } else { + md5_keyidstr = g_strdup("(cannot calculate digest)"); + } + + message = g_string_new(""); + g_string_append_printf(message, _("The SSL certificate of %s cannot be verified by the following reason:"), hostname); + if (verify_result == X509_V_ERR_APPLICATION_VERIFICATION) { + g_string_append_printf(message, "\n certificate hostname does not match\n\n"); + } else { + g_string_append_printf(message, "\n %s\n\n", X509_verify_cert_error_string(verify_result)); + } + g_string_append_printf(message, _("Subject: %s\n"), subject ? subject : "(unknown)"); + g_string_append_printf(message, _("Issuer: %s\n"), issuer ? issuer : "(unknown)"); + g_string_append_printf(message, _("Issued date: %s\n"), not_before); + g_string_append_printf(message, _("Expire date: %s\n"), not_after); + g_string_append(message, "\n"); + g_string_append_printf(message, _("SHA1 fingerprint: %s\n"), sha1_keyidstr); + g_string_append_printf(message, _("MD5 fingerprint: %s\n"), md5_keyidstr); + g_string_append(message, "\n"); + g_string_append(message, _("Do you accept this certificate?")); + g_free(md5_keyidstr); + g_free(sha1_keyidstr); + if (issuer) + OPENSSL_free(issuer); + if (subject) + OPENSSL_free(subject); + + dialog = gtk_dialog_new(); + gtk_window_set_title(GTK_WINDOW(dialog), title); + gtk_window_set_policy(GTK_WINDOW(dialog), FALSE, FALSE, FALSE); + gtk_window_set_position(GTK_WINDOW(dialog), + GTK_WIN_POS_CENTER_ON_PARENT); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + manage_window_set_transient(GTK_WINDOW(dialog)); + gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); + gtk_widget_realize(dialog); + + hbox = gtk_hbox_new(FALSE, 12); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 12); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), + hbox, FALSE, FALSE, 0); + + image = gtk_image_new_from_stock + (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_DIALOG); + + gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.0); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); + + vbox = gtk_vbox_new(FALSE, 12); + gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); + + label = gtk_label_new(title); + gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + + if (!font_desc) { + gint size; + + size = pango_font_description_get_size + (label->style->font_desc); + font_desc = pango_font_description_new(); + pango_font_description_set_weight + (font_desc, PANGO_WEIGHT_BOLD); + pango_font_description_set_size + (font_desc, size * PANGO_SCALE_LARGE); + } + if (font_desc) + gtk_widget_modify_font(label, font_desc); + + label = gtk_label_new(message->str); + g_string_free(message, TRUE); + gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); + gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); + gtk_label_set_selectable(GTK_LABEL(label), TRUE); + GTK_WIDGET_UNSET_FLAGS(label, GTK_CAN_FOCUS); +#ifdef G_OS_WIN32 + { + GtkStyle *style; + style = gtk_widget_get_style(dialog); + gtk_widget_modify_base(label, GTK_STATE_ACTIVE, + &style->base[GTK_STATE_SELECTED]); + gtk_widget_modify_text(label, GTK_STATE_ACTIVE, + &style->text[GTK_STATE_SELECTED]); + } +#endif + + /* prohibit acception of expired certificates */ + if (verify_result == X509_V_ERR_CERT_HAS_EXPIRED) + disable_always = TRUE; + + if (prefs_common.comply_gnome_hig) + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + _("_Reject"), GTK_RESPONSE_REJECT, + _("_Temporarily accept"), GTK_RESPONSE_OK, + _("Always _accept"), GTK_RESPONSE_ACCEPT, + NULL); + else + gtk_dialog_add_buttons(GTK_DIALOG(dialog), + _("Always _accept"), GTK_RESPONSE_ACCEPT, + _("_Temporarily accept"), GTK_RESPONSE_OK, + _("_Reject"), GTK_RESPONSE_REJECT, + NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); + if (disable_always) + gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), + GTK_RESPONSE_ACCEPT, FALSE); + + gtk_widget_show_all(dialog); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + + gdk_threads_leave(); + + switch (result) { + case GTK_RESPONSE_ACCEPT: + return 0; + case GTK_RESPONSE_OK: + return 1; + case GTK_RESPONSE_REJECT: + default: + break; + } + + return -1; +} + +#endif /* USE_SSL */ -- cgit v1.3