diff --git a/src/command/commands.c b/src/command/commands.c index d48fbe6d..2c3ee1fa 100644 --- a/src/command/commands.c +++ b/src/command/commands.c @@ -207,24 +207,7 @@ cmd_tls(ProfWin *window, const char *const command, gchar **args) } while (curr) { TLSCertificate *cert = curr->data; - if (cert->fingerprint) { - cons_show("Fingerprint : %s", cert->fingerprint); - } - if (cert->domain) { - cons_show("Domain : %s", cert->domain); - } - if (cert->organisation) { - cons_show("Organisation : %s", cert->organisation); - } - if (cert->email) { - cons_show("Email : %s", cert->email); - } - if (cert->notbefore) { - cons_show("Start : %s", cert->notbefore); - } - if (cert->notafter) { - cons_show("End : %s", cert->notafter); - } + cons_show_tlscert(cert); cons_show(""); curr = g_list_next(curr); } @@ -264,9 +247,11 @@ cmd_tls(ProfWin *window, const char *const command, gchar **args) cons_show("No TLS connection established"); return TRUE; } - char *cert = jabber_get_tls_peer_cert(); + TLSCertificate *cert = jabber_get_tls_peer_cert(); if (cert) { - cons_show("TLS certificate fingerprint: %s", cert); + cons_show_tlscert(cert); + cons_show(""); + tlscerts_free(cert); } else { cons_show("Error getting TLS fingerprint."); } diff --git a/src/config/tlscerts.c b/src/config/tlscerts.c index 299b98cf..15433a92 100644 --- a/src/config/tlscerts.c +++ b/src/config/tlscerts.c @@ -119,13 +119,11 @@ tlscerts_list(void) int i = 0; for (i = 0; i < g_strv_length(groups); i++) { char *fingerprint = strdup(groups[i]); - char *domain = g_key_file_get_string(tlscerts, fingerprint, "domain", NULL); - char *organisation = g_key_file_get_string(tlscerts, fingerprint, "organisation", NULL); - char *email = g_key_file_get_string(tlscerts, fingerprint, "email", NULL); + char *subjectname = g_key_file_get_string(tlscerts, fingerprint, "subjectname", NULL); char *notbefore = g_key_file_get_string(tlscerts, fingerprint, "start", NULL); char *notafter = g_key_file_get_string(tlscerts, fingerprint, "end", NULL); - TLSCertificate *cert = tlscerts_new(fingerprint, domain, organisation, email, notbefore, notafter); + TLSCertificate *cert = tlscerts_new(fingerprint, subjectname, notbefore, notafter); res = g_list_append(res, cert); } @@ -138,30 +136,21 @@ tlscerts_list(void) } TLSCertificate* -tlscerts_new(const char *const fingerprint, const char *const domain, const char *const organisation, - const char *const email, const char *const notbefore, const char *const notafter) +tlscerts_new(const char *const fingerprint, const char *const subjectname, const char *const notbefore, + const char *const notafter) { TLSCertificate *cert = malloc(sizeof(TLSCertificate)); + + if (subjectname) { + cert->subjectname = strdup(subjectname); + } else { + cert->subjectname = NULL; + } if (fingerprint) { cert->fingerprint = strdup(fingerprint); } else { cert->fingerprint = NULL; } - if (domain) { - cert->domain = strdup(domain); - } else { - cert->domain = NULL; - } - if (organisation) { - cert->organisation = strdup(organisation); - } else { - cert->organisation = NULL; - } - if (email) { - cert->email = strdup(email); - } else { - cert->email= NULL; - } if (notbefore) { cert->notbefore = strdup(notbefore); } else { @@ -173,6 +162,28 @@ tlscerts_new(const char *const fingerprint, const char *const domain, const char cert->notafter = NULL; } + cert->domain = NULL; + cert->email = NULL; + cert->organisation = NULL; + gchar** fields = g_strsplit(subjectname, "/", 0); + int i = 0; + for (i = 0; i < g_strv_length(fields); i++) { + gchar** keyval = g_strsplit(fields[i], "=", 2); + if (g_strv_length(keyval) == 2) { + if (g_strcmp0(keyval[0], "CN") == 0) { + cert->domain = strdup(keyval[1]); + } + if (g_strcmp0(keyval[0], "O") == 0) { + cert->organisation = strdup(keyval[1]); + } + if (g_strcmp0(keyval[0], "emailAddress") == 0) { + cert->email = strdup(keyval[1]); + } + } + g_strfreev(keyval); + } + g_strfreev(fields); + return cert; } @@ -189,14 +200,8 @@ tlscerts_add(TLSCertificate *cert) autocomplete_add(certs_ac, cert->fingerprint); - if (cert->domain) { - g_key_file_set_string(tlscerts, cert->fingerprint, "domain", cert->domain); - } - if (cert->organisation) { - g_key_file_set_string(tlscerts, cert->fingerprint, "organisation", cert->organisation); - } - if (cert->email) { - g_key_file_set_string(tlscerts, cert->fingerprint, "email", cert->email); + if (cert->subjectname) { + g_key_file_set_string(tlscerts, cert->fingerprint, "subjectname", cert->subjectname); } if (cert->notbefore) { g_key_file_set_string(tlscerts, cert->fingerprint, "start", cert->notbefore); @@ -237,6 +242,7 @@ void tlscerts_free(TLSCertificate *cert) { if (cert) { + free(cert->subjectname); free(cert->fingerprint); free(cert->domain); free(cert->organisation); diff --git a/src/config/tlscerts.h b/src/config/tlscerts.h index c3b273e7..e1ab4748 100644 --- a/src/config/tlscerts.h +++ b/src/config/tlscerts.h @@ -38,6 +38,7 @@ typedef struct tls_cert_t { char *fingerprint; char *domain; + char *subjectname; char *organisation; char *email; char *notbefore; @@ -46,9 +47,8 @@ typedef struct tls_cert_t { void tlscerts_init(void); -TLSCertificate* tlscerts_new(const char *const fingerprint, const char *const domain, - const char *const organisation, const char *const email, - const char *const notbefore, const char *const notafter); +TLSCertificate* tlscerts_new(const char *const fingerprint, const char *const subjectname, const char *const notbefore, + const char *const notafter); void tlscerts_set_current(const char *const fp); diff --git a/src/event/server_events.c b/src/event/server_events.c index 2663eb09..58add417 100644 --- a/src/event/server_events.c +++ b/src/event/server_events.c @@ -716,56 +716,22 @@ sv_ev_muc_occupant_online(const char *const room, const char *const nick, const } int -sv_ev_certfail(const char *const errormsg, const char *const certname, const char *const certfp, - const char *const notbefore, const char *const notafter) +sv_ev_certfail(const char *const errormsg, TLSCertificate *cert) { // check profanity trusted certs - if (tlscerts_exists(certfp)) { + if (tlscerts_exists(cert->fingerprint)) { return 1; } // check current cert char *current_fp = tlscerts_get_current(); - if (current_fp && g_strcmp0(current_fp, certfp) == 0) { + if (current_fp && g_strcmp0(current_fp, cert->fingerprint) == 0) { return 1; } - char *domain = NULL; - char *org = NULL; - char *email = NULL; - gchar** fields = g_strsplit(certname, "/", 0); - int i = 0; - for (i = 0; i < g_strv_length(fields); i++) { - gchar** keyval = g_strsplit(fields[i], "=", 2); - if (g_strv_length(keyval) == 2) { - if (g_strcmp0(keyval[0], "CN") == 0) { - domain = strdup(keyval[1]); - } - if (g_strcmp0(keyval[0], "O") == 0) { - org = strdup(keyval[1]); - } - if (g_strcmp0(keyval[0], "emailAddress") == 0) { - email = strdup(keyval[1]); - } - } - g_strfreev(keyval); - } - g_strfreev(fields); - cons_show(""); cons_show_error("TLS certificate verification failed: %s", errormsg); - if (domain) { - cons_show(" Domain : %s", domain); - } - if (org) { - cons_show(" Organisation : %s", org); - } - if (email) { - cons_show(" Email : %s", email); - } - cons_show(" Fingerprint : %s", certfp); - cons_show(" Start : %s", notbefore); - cons_show(" End : %s", notafter); + cons_show_tlscert(cert); cons_show(""); cons_show("Use '/tls allow' to accept this certificate"); cons_show("Use '/tls always' to accept this certificate permanently"); @@ -788,28 +754,17 @@ sv_ev_certfail(const char *const errormsg, const char *const certname, const cha } if (g_strcmp0(cmd, "/tls allow") == 0) { - tlscerts_set_current(certfp); + tlscerts_set_current(cert->fingerprint); free(cmd); - free(domain); - free(org); - free(email); return 1; } else if (g_strcmp0(cmd, "/tls always") == 0) { - if (!tlscerts_exists(certfp)) { - TLSCertificate *cert = tlscerts_new(certfp, domain, org, email, notbefore, notafter); + if (!tlscerts_exists(cert->fingerprint)) { tlscerts_add(cert); - tlscerts_free(cert); } free(cmd); - free(domain); - free(org); - free(email); return 1; } else { free(cmd); - free(domain); - free(org); - free(email); return 0; } } diff --git a/src/event/server_events.h b/src/event/server_events.h index 73c2ec03..e54e964f 100644 --- a/src/event/server_events.h +++ b/src/event/server_events.h @@ -85,8 +85,7 @@ void sv_ev_muc_occupant_online(const char *const room, const char *const nick, c void sv_ev_roster_update(const char *const barejid, const char *const name, GSList *groups, const char *const subscription, gboolean pending_out); void sv_ev_roster_received(void); -int sv_ev_certfail(const char *const errormsg, const char *const certname, const char *const certfp, - const char *const notbefore, const char *const notafter); +int sv_ev_certfail(const char *const errormsg, TLSCertificate *cert); void sv_ev_lastactivity_response(const char *const from, const int seconds, const char *const msg); #endif diff --git a/src/ui/console.c b/src/ui/console.c index 665da9c5..4d4edec0 100644 --- a/src/ui/console.c +++ b/src/ui/console.c @@ -188,6 +188,28 @@ cons_show_error(const char *const msg, ...) cons_alert(); } +void +cons_show_tlscert(TLSCertificate *cert) +{ + if (!cert) { + return; + } + + cons_show("Certificate:"); + if (cert->domain) { + cons_show(" Domain : %s", cert->domain); + } + if (cert->organisation) { + cons_show(" Organisation : %s", cert->organisation); + } + if (cert->email) { + cons_show(" Email : %s", cert->email); + } + cons_show(" Fingerprint : %s", cert->fingerprint); + cons_show(" Start : %s", cert->notbefore); + cons_show(" End : %s", cert->notafter); +} + void cons_show_typing(const char *const barejid) { diff --git a/src/ui/ui.h b/src/ui/ui.h index b967ea8b..242772a5 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -293,6 +293,7 @@ void cons_inpblock_setting(void); void cons_show_contact_online(PContact contact, Resource *resource, GDateTime *last_activity); void cons_show_contact_offline(PContact contact, char *resource, char *status); void cons_theme_colours(void); +void cons_show_tlscert(TLSCertificate *cert); // title bar void title_bar_set_presence(contact_presence_t presence); diff --git a/src/xmpp/connection.c b/src/xmpp/connection.c index 2986b0bc..dce836bc 100644 --- a/src/xmpp/connection.c +++ b/src/xmpp/connection.c @@ -387,16 +387,34 @@ _connection_free_session_data(void) #ifdef HAVE_LIBMESODE static int -_connection_certfail_cb(const char *const certname, const char *const certfp, - char *const notbefore, const char *const notafter, const char *const errormsg) +_connection_certfail_cb(xmpp_tlscert_t *xmpptlscert, const char *const errormsg) { - return sv_ev_certfail(errormsg, certname, certfp, notbefore, notafter); + char *subjectname = xmpp_conn_tlscert_subjectname(xmpptlscert); + char *fp = xmpp_conn_tlscert_fp(xmpptlscert); + char *notbefore = xmpp_conn_tlscert_notbefore(xmpptlscert); + char *notafter = xmpp_conn_tlscert_notafter(xmpptlscert); + + TLSCertificate *cert = tlscerts_new(fp, subjectname, notbefore, notafter); + int res = sv_ev_certfail(errormsg, cert); + tlscerts_free(cert); + + return res; } -char* +TLSCertificate* jabber_get_tls_peer_cert(void) { - return xmpp_conn_tls_peer_cert(jabber_conn.conn); + xmpp_tlscert_t *xmpptlscert = xmpp_conn_tls_peer_cert(jabber_conn.conn); + char *subjectname = xmpp_conn_tlscert_subjectname(xmpptlscert); + char *fp = xmpp_conn_tlscert_fp(xmpptlscert); + char *notbefore = xmpp_conn_tlscert_notbefore(xmpptlscert); + char *notafter = xmpp_conn_tlscert_notafter(xmpptlscert); + + TLSCertificate *cert = tlscerts_new(fp, subjectname, notbefore, notafter); + + xmpp_conn_free_tlscert(jabber_conn.ctx, xmpptlscert); + + return cert; } #endif diff --git a/src/xmpp/xmpp.h b/src/xmpp/xmpp.h index 00f83d3f..f52603eb 100644 --- a/src/xmpp/xmpp.h +++ b/src/xmpp/xmpp.h @@ -45,6 +45,7 @@ #endif #include "config/accounts.h" +#include "config/tlscerts.h" #include "contact.h" #include "jid.h" #include "tools/autocomplete.h" @@ -153,7 +154,7 @@ GList* jabber_get_available_resources(void); char* jabber_create_uuid(void); void jabber_free_uuid(char *uuid); #ifdef HAVE_LIBMESODE -char* jabber_get_tls_peer_cert(void); +TLSCertificate* jabber_get_tls_peer_cert(void); #endif gboolean jabber_conn_is_secured(void); diff --git a/tests/unittests/ui/stub_ui.c b/tests/unittests/ui/stub_ui.c index 6ebf4803..fe553a8c 100644 --- a/tests/unittests/ui/stub_ui.c +++ b/tests/unittests/ui/stub_ui.c @@ -262,6 +262,17 @@ void ui_redraw_all_room_rosters(void) {} void ui_show_all_room_rosters(void) {} void ui_hide_all_room_rosters(void) {} +gboolean jabber_conn_is_secured(void) +{ + return TRUE; +} +TLSCertificate* jabber_get_tls_peer_cert(void) +{ + return NULL; +} +void cons_show_tlscert(TLSCertificate *cert) {} + + void ui_prune_wins(void) {} void ui_handle_login_account_success(ProfAccount *account, int secured) {}