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:
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user