1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-03 08:13:14 +02:00

irc: evaluate content of server option "ssl_fingerprint" (closes #858)

This commit is contained in:
Sébastien Helleu
2016-12-03 09:44:18 +01:00
parent a864da7b3b
commit 28fde407f4
22 changed files with 189 additions and 94 deletions
+69 -51
View File
@@ -997,7 +997,7 @@ irc_config_server_check_value_cb (const void *pointer, void *data,
const char *pos_error, *proxy_name;
struct t_infolist *infolist;
#ifdef HAVE_GNUTLS
char **fingerprints, *str_sizes;
char *fingerprint_eval, **fingerprints, *str_sizes;
int i, j, rc, algo, length;
#endif /* HAVE_GNUTLS */
@@ -1053,60 +1053,77 @@ irc_config_server_check_value_cb (const void *pointer, void *data,
break;
case IRC_SERVER_OPTION_SSL_FINGERPRINT:
#ifdef HAVE_GNUTLS
if (value && value[0])
if (!value || !value[0])
break;
fingerprint_eval = weechat_string_eval_expression (
value, NULL, NULL, NULL);
if (!fingerprint_eval || !fingerprint_eval[0])
{
fingerprints = weechat_string_split (value, ",", 0, 0,
NULL);
if (fingerprints)
weechat_printf (
NULL,
_("%s%s: the evaluated fingerprint must not be "
"empty"),
weechat_prefix ("error"),
IRC_PLUGIN_NAME);
if (fingerprint_eval)
free (fingerprint_eval);
return 0;
}
fingerprints = weechat_string_split (
(fingerprint_eval) ? fingerprint_eval : value,
",", 0, 0, NULL);
if (!fingerprints)
{
free (fingerprint_eval);
return 1;
}
rc = 0;
for (i = 0; fingerprints[i]; i++)
{
length = strlen (fingerprints[i]);
algo = irc_server_fingerprint_search_algo_with_size (
length * 4);
if (algo < 0)
{
rc = 0;
for (i = 0; fingerprints[i]; i++)
rc = -1;
break;
}
for (j = 0; j < length; j++)
{
if (!isxdigit ((unsigned char)fingerprints[i][j]))
{
length = strlen (fingerprints[i]);
algo = irc_server_fingerprint_search_algo_with_size (
length * 4);
if (algo < 0)
{
rc = -1;
break;
}
for (j = 0; j < length; j++)
{
if (!isxdigit ((unsigned char)fingerprints[i][j]))
{
rc = -2;
break;
}
}
if (rc < 0)
break;
}
weechat_string_free_split (fingerprints);
switch (rc)
{
case -1: /* invalid size */
str_sizes = irc_server_fingerprint_str_sizes ();
weechat_printf (
NULL,
_("%s%s: invalid fingerprint size, the "
"number of hexadecimal digits must be "
"one of: %s"),
weechat_prefix ("error"),
IRC_PLUGIN_NAME,
(str_sizes) ? str_sizes : "?");
if (str_sizes)
free (str_sizes);
return 0;
case -2: /* invalid content */
weechat_printf (
NULL,
_("%s%s: invalid fingerprint, it must "
"contain only hexadecimal digits (0-9, "
"a-f)"),
weechat_prefix ("error"), IRC_PLUGIN_NAME);
return 0;
rc = -2;
break;
}
}
if (rc < 0)
break;
}
weechat_string_free_split (fingerprints);
free (fingerprint_eval);
switch (rc)
{
case -1: /* invalid size */
str_sizes = irc_server_fingerprint_str_sizes ();
weechat_printf (
NULL,
_("%s%s: invalid fingerprint size, the "
"number of hexadecimal digits must be "
"one of: %s"),
weechat_prefix ("error"),
IRC_PLUGIN_NAME,
(str_sizes) ? str_sizes : "?");
if (str_sizes)
free (str_sizes);
return 0;
case -2: /* invalid content */
weechat_printf (
NULL,
_("%s%s: invalid fingerprint, it must "
"contain only hexadecimal digits (0-9, "
"a-f)"),
weechat_prefix ("error"), IRC_PLUGIN_NAME);
return 0;
}
#endif /* HAVE_GNUTLS */
break;
@@ -1642,7 +1659,8 @@ irc_config_server_new_option (struct t_config_file *config_file,
"20 chars for SHA-1 (insecure, not recommended); many "
"fingerprints can be separated by commas; if this option "
"is set, the other checks on certificates are NOT "
"performed (option \"ssl_verify\")"),
"performed (option \"ssl_verify\") "
"(note: content is evaluated, see /help eval)"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
+15 -9
View File
@@ -4056,8 +4056,8 @@ irc_server_gnutls_callback (const void *pointer, void *data,
gnutls_datum_t filedatum;
unsigned int i, cert_list_len, status;
time_t cert_time;
char *cert_path0, *cert_path1, *cert_path2, *cert_str;
const char *weechat_dir, *fingerprint;
char *cert_path0, *cert_path1, *cert_path2, *cert_str, *fingerprint_eval;
const char *weechat_dir, *ptr_fingerprint;
int rc, ret, fingerprint_match, hostname_match, cert_temp_init;
#if LIBGNUTLS_VERSION_NUMBER >= 0x010706 /* 1.7.6 */
gnutls_datum_t cinfo;
@@ -4080,6 +4080,7 @@ irc_server_gnutls_callback (const void *pointer, void *data,
cert_temp_init = 0;
cert_list = NULL;
cert_list_len = 0;
fingerprint_eval = NULL;
if (action == WEECHAT_HOOK_CONNECT_GNUTLS_CB_VERIFY_CERT)
{
@@ -4106,11 +4107,13 @@ irc_server_gnutls_callback (const void *pointer, void *data,
cert_temp_init = 1;
/* get fingerprint option in server */
fingerprint = IRC_SERVER_OPTION_STRING (server,
IRC_SERVER_OPTION_SSL_FINGERPRINT);
ptr_fingerprint = IRC_SERVER_OPTION_STRING(server,
IRC_SERVER_OPTION_SSL_FINGERPRINT);
fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint,
NULL, NULL, NULL);
/* set match options */
fingerprint_match = (fingerprint && fingerprint[0]) ? 0 : 1;
fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1;
hostname_match = 0;
/* get the peer's raw certificate (chain) as sent by the peer */
@@ -4143,10 +4146,10 @@ irc_server_gnutls_callback (const void *pointer, void *data,
if (i == 0)
{
/* check if fingerprint matches the first certificate */
if (fingerprint && fingerprint[0])
if (fingerprint_eval && fingerprint_eval[0])
{
fingerprint_match = irc_server_check_certificate_fingerprint (
server, cert_temp, fingerprint);
server, cert_temp, fingerprint_eval);
}
/* check if hostname matches in the first certificate */
if (gnutls_x509_crt_check_hostname (cert_temp,
@@ -4178,7 +4181,7 @@ irc_server_gnutls_callback (const void *pointer, void *data,
}
#endif /* LIBGNUTLS_VERSION_NUMBER >= 0x010706 */
/* check dates, only if fingerprint is not set */
if (!fingerprint || !fingerprint[0])
if (!ptr_fingerprint || !ptr_fingerprint[0])
{
/* check expiration date */
cert_time = gnutls_x509_crt_get_expiration_time (cert_temp);
@@ -4207,7 +4210,7 @@ irc_server_gnutls_callback (const void *pointer, void *data,
* if fingerprint is set, display if matches, and don't check
* anything else
*/
if (fingerprint && fingerprint[0])
if (ptr_fingerprint && ptr_fingerprint[0])
{
if (fingerprint_match)
{
@@ -4409,6 +4412,9 @@ end:
if (cert_temp_init)
gnutls_x509_crt_deinit (cert_temp);
if (fingerprint_eval)
free (fingerprint_eval);
return rc;
}
#endif /* HAVE_GNUTLS */