diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2014-04-04 16:00:07 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2014-04-04 16:00:07 +0200 |
commit | df8acd1d7bc1ddb1495e1a36b4e9c14efdd6541d (patch) | |
tree | cea8e89018f7280f8d0358f5aad21f84199d7791 /src | |
parent | de4ce8eeb664c3dc6c707d2096bd6431d2067c1d (diff) | |
download | weechat-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.c | 37 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 75 |
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; } /* |