summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2014-04-04 16:00:07 +0200
committerSébastien Helleu <flashcode@flashtux.org>2014-04-04 16:00:07 +0200
commitdf8acd1d7bc1ddb1495e1a36b4e9c14efdd6541d (patch)
treecea8e89018f7280f8d0358f5aad21f84199d7791 /src
parentde4ce8eeb664c3dc6c707d2096bd6431d2067c1d (diff)
downloadweechat-df8acd1d7bc1ddb1495e1a36b4e9c14efdd6541d.zip
irc: allow many fingerprints in server option ssl_fingerprint (closes #49)
Diffstat (limited to 'src')
-rw-r--r--src/plugins/irc/irc-config.c37
-rw-r--r--src/plugins/irc/irc-server.c75
2 files changed, 86 insertions, 26 deletions
diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c
index c7dce6c10..d034e2541 100644
--- a/src/plugins/irc/irc-config.c
+++ b/src/plugins/irc/irc-config.c
@@ -1016,8 +1016,9 @@ irc_config_server_check_value_cb (void *data,
struct t_config_option *option,
const char *value)
{
- int index_option, proxy_found;
+ int i, index_option, proxy_found, rc;
const char *pos_error, *proxy_name;
+ char **fingerprints;
struct t_infolist *infolist;
/* make C compiler happy */
@@ -1072,11 +1073,30 @@ irc_config_server_check_value_cb (void *data,
case IRC_SERVER_OPTION_SSL_FINGERPRINT:
if (value && value[0] && (strlen (value) != 40))
{
- weechat_printf (NULL,
- _("%s%s: fingerprint must have exactly 40 "
- "hexadecimal digits"),
- weechat_prefix ("error"), IRC_PLUGIN_NAME);
- return 0;
+ fingerprints = weechat_string_split (value, ",", 0, 0, NULL);
+ if (fingerprints)
+ {
+ rc = 1;
+ for (i = 0; fingerprints[i]; i++)
+ {
+ if (strlen (fingerprints[i]) != 40)
+ {
+ rc = 0;
+ break;
+ }
+ }
+ weechat_string_free_split (fingerprints);
+ if (!rc)
+ {
+ weechat_printf (NULL,
+ _("%s%s: fingerprint must have "
+ "exactly 40 hexadecimal "
+ "digits"),
+ weechat_prefix ("error"),
+ IRC_PLUGIN_NAME);
+ return 0;
+ }
+ }
}
break;
}
@@ -1595,8 +1615,9 @@ irc_config_server_new_option (struct t_config_file *config_file,
option_name, "string",
N_("SHA1 fingerprint of certificate which is trusted and "
"accepted for the server (it must be exactly 40 hexadecimal "
- "digits without separators); if this option is set, the "
- "other checks on certificates are NOT performed (option "
+ "digits without separators); many fingerprints can be "
+ "separated by commas; if this option is set, the other "
+ "checks on certificates are NOT performed (option "
"\"ssl_verify\")"),
NULL, 0, 0,
default_value, value,
diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c
index 45a3cc341..84620e237 100644
--- a/src/plugins/irc/irc-server.c
+++ b/src/plugins/irc/irc-server.c
@@ -3563,6 +3563,37 @@ irc_server_create_buffer (struct t_irc_server *server)
}
#ifdef HAVE_GNUTLS
+/*
+ * Compares two fingerprints: one hexadecimal (given by user), the second binary
+ * (received from IRC server).
+ *
+ * Returns:
+ * 0: fingerprints are the same
+ * -1: fingerprints are different
+ */
+
+int
+irc_server_compare_fingerprints (const char *fingerprint,
+ const unsigned char *fingerprint_server,
+ ssize_t fingerprint_size)
+{
+ ssize_t i;
+ unsigned int value;
+
+ if ((ssize_t)strlen (fingerprint) != fingerprint_size * 2)
+ return -1;
+
+ for (i = 0; i < fingerprint_size; i++)
+ {
+ if (sscanf (&fingerprint[i * 2], "%02x", &value) != 1)
+ return -1;
+ if (value != fingerprint_server[i])
+ return -1;
+ }
+
+ /* fingerprints are the same */
+ return 0;
+}
/*
* Checks if a GnuTLS session uses the certificate with a given fingerprint.
@@ -3575,21 +3606,18 @@ irc_server_create_buffer (struct t_irc_server *server)
int
irc_server_check_certificate_fingerprint (struct t_irc_server *server,
gnutls_x509_crt_t certificate,
- const char *good_fingerprint)
+ const char *good_fingerprints)
{
- unsigned char fingerprint[20];
- size_t i, fingerprint_size;
- unsigned int value;
-
- fingerprint_size = sizeof (fingerprint);
+ unsigned char fingerprint_server[20];
+ char **fingerprints;
+ int i, rc;
+ size_t fingerprint_size;
- /* invalid length for good_fingerprint? */
- if (strlen (good_fingerprint) != fingerprint_size * 2)
- return 0;
+ fingerprint_size = sizeof (fingerprint_server);
/* calculate the SHA1 fingerprint for the certificate */
if (gnutls_x509_crt_get_fingerprint (certificate, GNUTLS_DIG_SHA1,
- fingerprint,
+ fingerprint_server,
&fingerprint_size) != GNUTLS_E_SUCCESS)
{
weechat_printf (server->buffer,
@@ -3599,17 +3627,28 @@ irc_server_check_certificate_fingerprint (struct t_irc_server *server,
return 0;
}
- /* compare the fingerprints */
- for (i = 0; i < fingerprint_size; i++)
+ /* split good_fingerprints */
+ fingerprints = weechat_string_split (good_fingerprints, ",", 0, 0, NULL);
+ if (!fingerprints)
+ return 0;
+
+ rc = 0;
+
+ for (i = 0; fingerprints[i]; i++)
{
- if (sscanf (&good_fingerprint[i * 2], "%02x", &value) != 1)
- return 0;
- if (value != fingerprint[i])
- return 0;
+ /* check if the fingerprint matches */
+ if (irc_server_compare_fingerprints (fingerprints[i],
+ fingerprint_server,
+ fingerprint_size) == 0)
+ {
+ rc = 1;
+ break;
+ }
}
- /* fingerprint matches */
- return 1;
+ weechat_string_free_split (fingerprints);
+
+ return rc;
}
/*