static void ssl_manager_list_view_insert_cert(GtkWidget *list_view, GtkTreeIter *row_iter, gchar *host, gchar *port, SSLCertificate *cert) { char *sig_status, *exp_date; char buf[100]; time_t exp_time_t; struct tm lt; PangoWeight weight = PANGO_WEIGHT_NORMAL; GtkTreeIter iter, *iterptr; GtkListStore *list_store = GTK_LIST_STORE(gtk_tree_view_get_model (GTK_TREE_VIEW(list_view))); exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert); memset(buf, 0, sizeof(buf)); if (exp_time_t > 0) { fast_strftime(buf, sizeof(buf)-1, prefs_common.date_format, localtime_r(&exp_time_t, <)); exp_date = (*buf) ? g_strdup(buf):g_strdup("?"); } else exp_date = g_strdup(""); if (exp_time_t < time(NULL)) weight = PANGO_WEIGHT_BOLD; sig_status = ssl_certificate_check_signer(cert, cert->status); if (sig_status==NULL) sig_status = g_strdup_printf(_("Correct%s"),exp_time_t < time(NULL)? _(" (expired)"): ""); else { weight = PANGO_WEIGHT_BOLD; if (exp_time_t < time(NULL)) sig_status = g_strconcat(sig_status,_(" (expired)"),NULL); } if (row_iter == NULL) { /* append new */ gtk_list_store_append(list_store, &iter); iterptr = &iter; } else iterptr = row_iter; gtk_list_store_set(list_store, iterptr, SSL_MANAGER_HOST, host, SSL_MANAGER_PORT, port, SSL_MANAGER_CERT, cert, SSL_MANAGER_STATUS, sig_status, SSL_MANAGER_EXPIRY, exp_date, SSL_MANAGER_FONT_WEIGHT, weight, -1); g_free(sig_status); g_free(exp_date); }
static gboolean sslcertwindow_ask_expired_cert(SSLCertificate *cert) { gchar *buf, *sig_status; AlertValue val; GtkWidget *vbox; 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.\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); g_free(buf); sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status); if (sig_status==NULL) sig_status = g_strdup(_("Correct")); buf = g_strdup_printf(_("Signature status: %s"), sig_status); label = gtk_label_new(buf); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0); g_free(buf); g_free(sig_status); button = gtk_expander_new_with_mnemonic(_("_View certificate")); gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0); cert_widget = cert_presenter(cert); gtk_container_add(GTK_CONTAINER(button), cert_widget); 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); return (val == G_ALERTALTERNATE); }
static 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 *issuer_commonname, *issuer_location, *issuer_organization; char *subject_commonname, *subject_location, *subject_organization; char *sig_status, *exp_date; char *md5_fingerprint, *sha1_fingerprint, *fingerprint; size_t n; char buf[100]; unsigned char md[128]; char *tmp; time_t exp_time_t; struct tm lt; /* issuer */ issuer_commonname = g_malloc(BUFFSIZE); issuer_location = g_malloc(BUFFSIZE); issuer_organization = g_malloc(BUFFSIZE); subject_commonname = g_malloc(BUFFSIZE); subject_location = g_malloc(BUFFSIZE); subject_organization = g_malloc(BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, issuer_commonname, &n)) strncpy(issuer_commonname, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, issuer_location, &n)) { if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, issuer_location, &n)) { strncpy(issuer_location, _("<not in certificate>"), BUFFSIZE); } } else { tmp = g_malloc(BUFFSIZE); if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) { strncat(issuer_location, ", ", BUFFSIZE-strlen(issuer_location)-1); strncat(issuer_location, tmp, BUFFSIZE-strlen(issuer_location)-1); } g_free(tmp); } n = BUFFSIZE; if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, issuer_organization, &n)) strncpy(issuer_organization, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0, subject_commonname, &n)) strncpy(subject_commonname, _("<not in certificate>"), BUFFSIZE); n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, subject_location, &n)) { if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, subject_location, &n)) { strncpy(subject_location, _("<not in certificate>"), BUFFSIZE); } } else { tmp = g_malloc(BUFFSIZE); if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) { strncat(subject_location, ", ", BUFFSIZE-strlen(subject_location)-1); strncat(subject_location, tmp, BUFFSIZE-strlen(subject_location)-1); } g_free(tmp); } n = BUFFSIZE; if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, subject_organization, &n)) strncpy(subject_organization, _("<not in certificate>"), BUFFSIZE); exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert); memset(buf, 0, sizeof(buf)); if (exp_time_t > 0) { fast_strftime(buf, sizeof(buf)-1, prefs_common.date_format, localtime_r(&exp_time_t, <)); exp_date = (*buf) ? g_strdup(buf):g_strdup("?"); } else exp_date = g_strdup(""); /* fingerprint */ n = 128; gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_MD5, md, &n); md5_fingerprint = readable_fingerprint(md, (int)n); n = 128; gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_SHA1, md, &n); sha1_fingerprint = readable_fingerprint(md, (int)n); /* signature */ sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status); 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(gtk_table_new(3, 2, FALSE)); signer_table = GTK_TABLE(gtk_table_new(3, 2, FALSE)); status_table = GTK_TABLE(gtk_table_new(3, 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_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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: \n")); 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); fingerprint = g_strdup_printf("MD5: %s\nSHA1: %s", md5_fingerprint, sha1_fingerprint); label = gtk_label_new(fingerprint); g_free(fingerprint); gtk_label_set_selectable(GTK_LABEL(label), TRUE); 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_label_set_selectable(GTK_LABEL(label), TRUE); 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); label = gtk_label_new(_("Expires on: ")); gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5); gtk_table_attach(status_table, label, 0, 1, 2, 3, GTK_EXPAND|GTK_FILL, 0, 0, 0); label = gtk_label_new(exp_date); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_table_attach(status_table, label, 1, 2, 2, 3, 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(md5_fingerprint); g_free(sha1_fingerprint); g_free(sig_status); g_free(exp_date); return vbox; }
static 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; gchar *buf, *sig_status; GtkWidget *vbox2; 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); 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); vbox2 = gtk_vbox_new(FALSE, 5); 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); g_free(buf); sig_status = ssl_certificate_check_signer(new_cert->x509_cert, new_cert->status); if (sig_status==NULL) sig_status = g_strdup(_("Correct")); buf = g_strdup_printf(_("Signature status: %s"), sig_status); label = gtk_label_new(buf); gtk_label_set_selectable(GTK_LABEL(label), TRUE); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0); g_free(buf); g_free(sig_status); button = gtk_expander_new_with_mnemonic(_("_View certificates")); gtk_box_pack_start(GTK_BOX(vbox2), button, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(button), vbox); 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); return (val == G_ALERTALTERNATE); }
int ssl_certificate_check(X509 *x509_cert, const char *host, int port, void *data) { SSLCertificate *current_cert = ssl_certificate_new(x509_cert, host, port); SSLCertificate *known_cert; if (current_cert == NULL) { eb_debug(DBG_CORE, "Buggy certificate !\n"); return FALSE; } eb_debug(DBG_CORE, "%s%d\n", host, port); known_cert = ssl_certificate_find(host, port); if (known_cert == NULL) { char *err_msg, *cur_cert_str, *sig_status; int result = 0; sig_status = ssl_certificate_check_signer(x509_cert); if (sig_status == NULL) { char buf[1024]; if (X509_NAME_get_text_by_NID(X509_get_subject_name (x509_cert), NID_commonName, buf, 100) >= 0) if (!strcmp(buf, current_cert->host)) { ssl_certificate_save(current_cert); ssl_certificate_destroy(current_cert); return TRUE; } } else g_free(sig_status); cur_cert_str = ssl_certificate_to_string(current_cert); err_msg = g_strdup_printf(_ ("The server <b>%s</b> presented an unknown SSL certificate:\n\n%s\n\n" "Do you want to continue connecting?"), current_cert->host, cur_cert_str); result = ay_connection_verify(err_msg, _("Unknown Certificate!"), data); g_free(cur_cert_str); g_free(err_msg); if (result) { ssl_certificate_save(current_cert); } ssl_certificate_destroy(current_cert); return result; } else if (!ssl_certificate_compare(current_cert, known_cert)) { char *err_msg, *known_cert_str, *cur_cert_str; int result = -1; known_cert_str = ssl_certificate_to_string(known_cert); cur_cert_str = ssl_certificate_to_string(current_cert); err_msg = g_strdup_printf(_ ("%s's SSL certificate changed!\nWe have saved this one:\n%s\n\nIt is now:\n%s\n\n" "This could mean the server answering is not the known one.\n" "Do you want to continue connecting ?"), current_cert->host, known_cert_str, cur_cert_str); g_free(cur_cert_str); g_free(known_cert_str); result = ay_connection_verify(err_msg, _("Changed Certificate!"), data); g_free(err_msg); if (result) { ssl_certificate_save(current_cert); } ssl_certificate_destroy(current_cert); return result; } ssl_certificate_destroy(current_cert); ssl_certificate_destroy(known_cert); return TRUE; }
char *ssl_certificate_to_string(SSLCertificate *cert) { 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(_("(Unspecified)")); 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(_("(Unspecified)")); 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(_("(Unspecified)")); /* 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(_("(Unspecified)")); 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(_("(Unspecified)")); 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(_("(Unspecified)")); /* 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); ret = g_strdup_printf(_(" <b>Certificate Owner:</b> %s (%s) in %s\n " "<b>Signed by:</b> %s (%s) in %s\n " "<b>Fingerprint:</b> %s\n " "<b>Signature status:</b> %s"), subject_commonname, subject_organization, subject_location, issuer_commonname, issuer_organization, issuer_location, fingerprint, (sig_status == NULL ? "correct" : sig_status)); if (issuer_commonname) g_free(issuer_commonname); if (issuer_location) g_free(issuer_location); if (issuer_organization) g_free(issuer_organization); if (subject_commonname) g_free(subject_commonname); if (subject_location) g_free(subject_location); if (subject_organization) g_free(subject_organization); if (fingerprint) g_free(fingerprint); if (sig_status) g_free(sig_status); return ret; }