mirror of
https://github.com/irssi/irssi.git
synced 2026-08-24 11:02:21 +02:00
Add pinned TLS fingerprint support.
This patch adds support for pinning TLS fingerprints. Setting a pinned fingerprint will override all other TLS verification and will thus be the only variable that will be looked at when connecting to a TLS enabled IRC server.
This commit is contained in:
parent
fb78787d4e
commit
78f007d493
31 changed files with 1114 additions and 357 deletions
|
|
@ -24,6 +24,7 @@ libfe_common_core_a_SOURCES = \
|
|||
fe-queries.c \
|
||||
fe-server.c \
|
||||
fe-settings.c \
|
||||
fe-tls.c \
|
||||
formats.c \
|
||||
hilight-text.c \
|
||||
keyboard.c \
|
||||
|
|
@ -48,6 +49,7 @@ pkginc_fe_common_core_HEADERS = \
|
|||
fe-exec.h \
|
||||
fe-messages.h \
|
||||
fe-queries.h \
|
||||
fe-tls.h \
|
||||
formats.h \
|
||||
hilight-text.h \
|
||||
keyboard.h \
|
||||
|
|
|
|||
|
|
@ -88,6 +88,9 @@ void fe_server_deinit(void);
|
|||
void fe_settings_init(void);
|
||||
void fe_settings_deinit(void);
|
||||
|
||||
void fe_tls_init(void);
|
||||
void fe_tls_deinit(void);
|
||||
|
||||
void window_commands_init(void);
|
||||
void window_commands_deinit(void);
|
||||
|
||||
|
|
@ -161,21 +164,24 @@ void fe_common_core_init(void)
|
|||
g_get_charset(&str);
|
||||
settings_add_str("lookandfeel", "term_charset", str);
|
||||
themes_init();
|
||||
theme_register(fecommon_core_formats);
|
||||
theme_register(fecommon_core_formats);
|
||||
|
||||
command_history_init();
|
||||
completion_init();
|
||||
keyboard_init();
|
||||
printtext_init();
|
||||
formats_init();
|
||||
fe_exec_init();
|
||||
fe_expandos_init();
|
||||
#ifndef WIN32
|
||||
fe_exec_init();
|
||||
#endif
|
||||
fe_expandos_init();
|
||||
fe_help_init();
|
||||
fe_ignore_init();
|
||||
fe_log_init();
|
||||
fe_modules_init();
|
||||
fe_server_init();
|
||||
fe_settings_init();
|
||||
fe_tls_init();
|
||||
windows_init();
|
||||
window_activity_init();
|
||||
window_commands_init();
|
||||
|
|
@ -183,8 +189,8 @@ void fe_common_core_init(void)
|
|||
windows_layout_init();
|
||||
fe_core_commands_init();
|
||||
|
||||
fe_channels_init();
|
||||
fe_queries_init();
|
||||
fe_channels_init();
|
||||
fe_queries_init();
|
||||
|
||||
fe_messages_init();
|
||||
hilight_text_init();
|
||||
|
|
@ -193,10 +199,10 @@ void fe_common_core_init(void)
|
|||
|
||||
settings_check();
|
||||
|
||||
signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
|
||||
module_register("core", "fe");
|
||||
}
|
||||
|
|
@ -209,14 +215,17 @@ void fe_common_core_deinit(void)
|
|||
keyboard_deinit();
|
||||
printtext_deinit();
|
||||
formats_deinit();
|
||||
fe_exec_deinit();
|
||||
fe_expandos_deinit();
|
||||
#ifndef WIN32
|
||||
fe_exec_deinit();
|
||||
#endif
|
||||
fe_expandos_deinit();
|
||||
fe_help_deinit();
|
||||
fe_ignore_deinit();
|
||||
fe_log_deinit();
|
||||
fe_modules_deinit();
|
||||
fe_server_deinit();
|
||||
fe_settings_deinit();
|
||||
fe_tls_deinit();
|
||||
windows_deinit();
|
||||
window_activity_deinit();
|
||||
window_commands_deinit();
|
||||
|
|
@ -224,21 +233,21 @@ void fe_common_core_deinit(void)
|
|||
windows_layout_deinit();
|
||||
fe_core_commands_deinit();
|
||||
|
||||
fe_channels_deinit();
|
||||
fe_queries_deinit();
|
||||
fe_channels_deinit();
|
||||
fe_queries_deinit();
|
||||
|
||||
fe_messages_deinit();
|
||||
fe_ignore_messages_deinit();
|
||||
fe_recode_deinit();
|
||||
|
||||
theme_unregister();
|
||||
theme_unregister();
|
||||
themes_deinit();
|
||||
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
|
||||
signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
|
||||
signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
|
||||
signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
|
||||
signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
|
||||
}
|
||||
|
||||
void glog_func(const char *log_domain, GLogLevelFlags log_level,
|
||||
|
|
|
|||
|
|
@ -154,42 +154,66 @@ static void cmd_server_add_modify(const char *data, gboolean add)
|
|||
else if (g_hash_table_lookup(optlist, "4"))
|
||||
rec->family = AF_INET;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "ssl"))
|
||||
rec->use_ssl = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "tls") || g_hash_table_lookup(optlist, "ssl"))
|
||||
rec->use_tls = TRUE;
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_cert");
|
||||
value = g_hash_table_lookup(optlist, "tls_cert");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_cert");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_cert = g_strdup(value);
|
||||
rec->tls_cert = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_pkey");
|
||||
value = g_hash_table_lookup(optlist, "tls_pkey");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_pkey");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_pkey = g_strdup(value);
|
||||
rec->tls_pkey = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_pass");
|
||||
value = g_hash_table_lookup(optlist, "tls_pass");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_pass");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_pass = g_strdup(value);
|
||||
rec->tls_pass = g_strdup(value);
|
||||
|
||||
if (g_hash_table_lookup(optlist, "ssl_verify"))
|
||||
rec->ssl_verify = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "tls_verify") || g_hash_table_lookup(optlist, "ssl_verify"))
|
||||
rec->tls_verify = TRUE;
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_cafile");
|
||||
value = g_hash_table_lookup(optlist, "tls_cafile");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_cafile");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_cafile = g_strdup(value);
|
||||
rec->tls_cafile = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_capath");
|
||||
value = g_hash_table_lookup(optlist, "tls_capath");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_capath");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_capath = g_strdup(value);
|
||||
rec->tls_capath = g_strdup(value);
|
||||
|
||||
value = g_hash_table_lookup(optlist, "ssl_ciphers");
|
||||
value = g_hash_table_lookup(optlist, "tls_ciphers");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_ciphers");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->ssl_ciphers = g_strdup(value);
|
||||
rec->tls_ciphers = g_strdup(value);
|
||||
|
||||
if ((rec->ssl_cafile != NULL && rec->ssl_cafile[0] != '\0')
|
||||
|| (rec->ssl_capath != NULL && rec->ssl_capath[0] != '\0'))
|
||||
rec->ssl_verify = TRUE;
|
||||
value = g_hash_table_lookup(optlist, "tls_pinned_cert");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_pinned_cert");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->tls_pinned_cert = g_strdup(value);
|
||||
|
||||
if ((rec->ssl_cert != NULL && rec->ssl_cert[0] != '\0') || rec->ssl_verify == TRUE)
|
||||
rec->use_ssl = TRUE;
|
||||
value = g_hash_table_lookup(optlist, "tls_pinned_pubkey");
|
||||
if (value == NULL)
|
||||
value = g_hash_table_lookup(optlist, "ssl_pinned_pubkey");
|
||||
if (value != NULL && *value != '\0')
|
||||
rec->tls_pinned_pubkey = g_strdup(value);
|
||||
|
||||
if ((rec->tls_cafile != NULL && rec->tls_cafile[0] != '\0')
|
||||
|| (rec->tls_capath != NULL && rec->tls_capath[0] != '\0'))
|
||||
rec->tls_verify = TRUE;
|
||||
|
||||
if ((rec->tls_cert != NULL && rec->tls_cert[0] != '\0') || rec->tls_verify == TRUE)
|
||||
rec->use_tls = TRUE;
|
||||
|
||||
if (g_hash_table_lookup(optlist, "auto")) rec->autoconnect = TRUE;
|
||||
if (g_hash_table_lookup(optlist, "noauto")) rec->autoconnect = FALSE;
|
||||
|
|
@ -331,8 +355,7 @@ static void sig_server_connected(SERVER_REC *server)
|
|||
{
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||
TXT_CONNECTION_ESTABLISHED, server->connrec->address);
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CONNECTION_ESTABLISHED, server->connrec->address);
|
||||
}
|
||||
|
||||
static void sig_connect_failed(SERVER_REC *server, gchar *msg)
|
||||
|
|
@ -409,8 +432,9 @@ void fe_server_init(void)
|
|||
command_bind("server remove", NULL, (SIGNAL_FUNC) cmd_server_remove);
|
||||
command_bind_first("server", NULL, (SIGNAL_FUNC) server_command);
|
||||
command_bind_first("disconnect", NULL, (SIGNAL_FUNC) server_command);
|
||||
command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers auto noauto proxy noproxy -host -port noautosendcmd");
|
||||
command_set_options("server modify", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers auto noauto proxy noproxy -host -port noautosendcmd");
|
||||
|
||||
command_set_options("server add", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls +tls_cert +tls_pkey +tls_pass tls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd");
|
||||
command_set_options("server modify", "4 6 !! ssl +ssl_cert +ssl_pkey +ssl_pass ssl_verify +ssl_cafile +ssl_capath +ssl_ciphers +ssl_fingerprint tls +tls_cert +tls_pkey +tls_pass tls_verify +tls_cafile +tls_capath +tls_ciphers +tls_pinned_cert +tls_pinned_pubkey auto noauto proxy noproxy -host -port noautosendcmd");
|
||||
|
||||
signal_add("server looking", (SIGNAL_FUNC) sig_server_looking);
|
||||
signal_add("server connecting", (SIGNAL_FUNC) sig_server_connecting);
|
||||
|
|
|
|||
82
src/fe-common/core/fe-tls.c
Normal file
82
src/fe-common/core/fe-tls.c
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Alexander Færøy <ahf@irssi.org>
|
||||
*
|
||||
* 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., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "settings.h"
|
||||
#include "levels.h"
|
||||
#include "tls.h"
|
||||
|
||||
#include "module-formats.h"
|
||||
#include "printtext.h"
|
||||
|
||||
#include "fe-tls.h"
|
||||
|
||||
static void tls_handshake_finished(SERVER_REC *server, TLS_REC *tls)
|
||||
{
|
||||
if (! settings_get_bool("tls_verbose_connect"))
|
||||
return;
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERT_HEADER);
|
||||
|
||||
GSList *certs = NULL;
|
||||
for (certs = tls->certs; certs != NULL; certs = certs->next) {
|
||||
TLS_CERT_REC *tls_cert_rec = certs->data;
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERT_SUBJECT_HEADER);
|
||||
|
||||
GSList *subject = NULL;
|
||||
for (subject = tls_cert_rec->subject; subject != NULL; subject = subject->next) {
|
||||
TLS_CERT_ENTRY_REC *subject_data = subject->data;
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERT_NAMED_ENTRY, subject_data->name, subject_data->value);
|
||||
}
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERT_ISSUER_HEADER);
|
||||
|
||||
GSList *issuer = NULL;
|
||||
for (issuer = tls_cert_rec->issuer; issuer != NULL; issuer = issuer->next) {
|
||||
TLS_CERT_ENTRY_REC *issuer_data = issuer->data;
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERT_NAMED_ENTRY, issuer_data->name, issuer_data->value);
|
||||
}
|
||||
}
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_PROTOCOL_VERSION, tls->protocol_version, tls->cipher_size, tls->cipher);
|
||||
|
||||
#ifdef SSL_get_server_tmp_key
|
||||
if (tls->ephemeral_key_algorithm != NULL)
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_EPHEMERAL_KEY, tls->ephemeral_key_size, tls->ephemeral_key_algorithm);
|
||||
else
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_EPHEMERAL_KEY_UNAVAILBLE);
|
||||
#endif
|
||||
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_PUBLIC_KEY, tls->public_key_size, tls->public_key_algorithm, tls->not_before, tls->not_after);
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_PUBLIC_KEY_FINGERPRINT, tls->public_key_fingerprint, tls->public_key_fingerprint_algorithm);
|
||||
printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, TXT_TLS_CERTIFICATE_FINGERPRINT, tls->certificate_fingerprint, tls->certificate_fingerprint_algorithm);
|
||||
}
|
||||
|
||||
void fe_tls_init(void)
|
||||
{
|
||||
settings_add_bool("lookandfeel", "tls_verbose_connect", TRUE);
|
||||
|
||||
signal_add("tls handshake finished", (SIGNAL_FUNC)tls_handshake_finished);
|
||||
}
|
||||
|
||||
void fe_tls_deinit(void)
|
||||
{
|
||||
signal_remove("tls handshake finished", (SIGNAL_FUNC)tls_handshake_finished);
|
||||
}
|
||||
25
src/fe-common/core/fe-tls.h
Normal file
25
src/fe-common/core/fe-tls.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Alexander Færøy <ahf@irssi.org>
|
||||
*
|
||||
* 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., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301,USA
|
||||
*/
|
||||
|
||||
#ifndef __FE_TLS_H
|
||||
#define __FE_TLS_H
|
||||
|
||||
void fe_tls_init(void);
|
||||
void fe_tls_deinit(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -291,5 +291,19 @@ FORMAT_REC fecommon_core_formats[] = {
|
|||
{ "completion_line", "%#$[10]0 $[!40]1 $2", 3, { 0, 0, 0 } },
|
||||
{ "completion_footer", "", 0 },
|
||||
|
||||
/* ---- */
|
||||
{ NULL, "TLS", 0 },
|
||||
|
||||
{ "tls_ephemeral_key", "EDH Key: {hilight $0} bit {hilight $1}", 2, { 1, 0 } },
|
||||
{ "tls_ephemeral_key_unavailable", "EDH Key: {error N/A}", 0 },
|
||||
{ "tls_public_key", "Public Key: {hilight $0} bit {hilight $1}, valid from {hilight $2} to {hilight $3}", 4, { 1, 0, 0, 0 } },
|
||||
{ "tls_cert_header", "Certificate Chain:", 0 },
|
||||
{ "tls_cert_subject_header", " Subject:", 0 },
|
||||
{ "tls_cert_issuer_header", " Issuer:", 0 },
|
||||
{ "tls_cert_named_entry", " $[-2]0: {hilight $1}", 2, { 0, 0 } },
|
||||
{ "tls_public_key_fingerprint", "Public Key Fingerprint: {hilight $0} ({hilight $1})", 2, { 0, 0 } },
|
||||
{ "tls_certificate_fingerprint", "Certificate Fingerprint: {hilight $0} ({hilight $1})", 2, { 0, 0 } },
|
||||
{ "tls_protocol_version", "Protocol: {hilight $0} ({hilight $1} bit, {hilight $2})", 3, { 0, 1, 0 } },
|
||||
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ enum {
|
|||
|
||||
TXT_LOOKING_UP,
|
||||
TXT_CONNECTING,
|
||||
TXT_RECONNECTING,
|
||||
TXT_CONNECTION_ESTABLISHED,
|
||||
TXT_RECONNECTING,
|
||||
TXT_CONNECTION_ESTABLISHED,
|
||||
TXT_CANT_CONNECT,
|
||||
TXT_CONNECTION_LOST,
|
||||
TXT_LAG_DISCONNECTED,
|
||||
|
|
@ -254,7 +254,20 @@ enum {
|
|||
TXT_COMPLETION_REMOVED,
|
||||
TXT_COMPLETION_HEADER,
|
||||
TXT_COMPLETION_LINE,
|
||||
TXT_COMPLETION_FOOTER
|
||||
TXT_COMPLETION_FOOTER,
|
||||
|
||||
TLS_FILL_15,
|
||||
|
||||
TXT_TLS_EPHEMERAL_KEY,
|
||||
TXT_TLS_EPHEMERAL_KEY_UNAVAILBLE,
|
||||
TXT_TLS_PUBLIC_KEY,
|
||||
TXT_TLS_CERT_HEADER,
|
||||
TXT_TLS_CERT_SUBJECT_HEADER,
|
||||
TXT_TLS_CERT_ISSUER_HEADER,
|
||||
TXT_TLS_CERT_NAMED_ENTRY,
|
||||
TXT_TLS_PUBLIC_KEY_FINGERPRINT,
|
||||
TXT_TLS_CERTIFICATE_FINGERPRINT,
|
||||
TXT_TLS_PROTOCOL_VERSION
|
||||
};
|
||||
|
||||
extern FORMAT_REC fecommon_core_formats[];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue