diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2018-02-05 21:41:03 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2018-02-05 21:41:03 +0100 |
commit | f889306c5edf5eeb37a9e37e6468ec0ac549d32c (patch) | |
tree | 8ff4f825d32214d9ebbe811b77d6e4ba42b973d6 /src | |
parent | e2b439d046996662042356ef0571168db165c210 (diff) | |
download | weechat-f889306c5edf5eeb37a9e37e6468ec0ac549d32c.zip |
irc: allow ${irc_server.xxx} and ${server} in server evaluated options (closes #1144)
The server option "ssl_fingerprint" is now evaluated when it is used (during
SSL connection), instead of when it is set with command /set.
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/irc/irc-config.c | 126 | ||||
-rw-r--r-- | src/plugins/irc/irc-ctcp.c | 12 | ||||
-rw-r--r-- | src/plugins/irc/irc-protocol.c | 24 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.c | 202 | ||||
-rw-r--r-- | src/plugins/irc/irc-server.h | 2 |
5 files changed, 230 insertions, 136 deletions
diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index ac0c53440..04bccb25c 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -23,7 +23,6 @@ #include <unistd.h> #include <stdio.h> #include <string.h> -#include <ctype.h> #include <time.h> #include <limits.h> #include <pwd.h> @@ -998,10 +997,6 @@ irc_config_server_check_value_cb (const void *pointer, void *data, char *error; long number; struct t_infolist *infolist; -#ifdef HAVE_GNUTLS - char *fingerprint_eval, **fingerprints, *str_sizes; - int i, j, rc, algo, length; -#endif /* HAVE_GNUTLS */ /* make C compiler happy */ (void) data; @@ -1053,82 +1048,6 @@ irc_config_server_check_value_cb (const void *pointer, void *data, return 0; } break; - case IRC_SERVER_OPTION_SSL_FINGERPRINT: -#ifdef HAVE_GNUTLS - if (!value || !value[0]) - break; - fingerprint_eval = weechat_string_eval_expression ( - value, NULL, NULL, NULL); - if (!fingerprint_eval || !fingerprint_eval[0]) - { - 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 = -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); - 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; case IRC_SERVER_OPTION_SPLIT_MSG_MAX_LENGTH: if (!value || !value[0]) break; @@ -1560,7 +1479,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("list of hostname/port or IP/port for server (separated by " "comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1687,7 +1608,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "fingerprints can be separated by commas; if this option " "is set, the other checks on certificates are NOT " "performed (option \"ssl_verify\") " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1720,7 +1643,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("password for server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1784,7 +1709,9 @@ irc_config_server_new_option (struct t_config_file *config_file, option_name, "string", N_("username for SASL authentication; this option is not used " "for mechanism \"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1803,7 +1730,9 @@ irc_config_server_new_option (struct t_config_file *config_file, N_("password for SASL authentication; this option is not used " "for mechanisms \"ecdsa-nist256p-challenge\" and " "\"external\" " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1925,7 +1854,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("nicknames to use on server (separated by comma) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1962,7 +1893,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("user name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -1979,7 +1912,9 @@ irc_config_server_new_option (struct t_config_file *config_file, config_file, section, option_name, "string", N_("real name to use on server " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2016,7 +1951,10 @@ irc_config_server_new_option (struct t_config_file *config_file, "executing command and the auto-join of channels; examples: " "\"+R\" (to set mode \"R\"), \"+R-i\" (to set mode \"R\" " "and remove \"i\"); see /help mode for the complete mode " - "syntax (note: content is evaluated, see /help eval)"), + "syntax " + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2036,7 +1974,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "auto-join of channels (many commands can be separated by " "\";\", use \"\\;\" for a semicolon, special variables " "$nick, $channel and $server are replaced by their value) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, @@ -2077,7 +2017,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "channels (separated by a space) (example: \"#channel1," "#channel2,#channel3 key1,key2\" where #channel1 and " "#channel2 are protected by key1 and key2) " - "(note: content is evaluated, see /help eval)"), + "(note: content is evaluated, see /help eval; server " + "options are evaluated with ${irc_server.xxx} and " + "${server} is replaced by the server name)"), NULL, 0, 0, default_value, value, null_value_allowed, diff --git a/src/plugins/irc/irc-ctcp.c b/src/plugins/irc/irc-ctcp.c index 14ca3c4aa..112e842cb 100644 --- a/src/plugins/irc/irc-ctcp.c +++ b/src/plugins/irc/irc-ctcp.c @@ -467,9 +467,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $username: user name, example: * name */ - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); if (username) { temp = weechat_string_replace (res, "$username", username); @@ -484,9 +484,9 @@ irc_ctcp_replace_variables (struct t_irc_server *server, const char *format) * $realname: real name, example: * John doe */ - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); if (realname) { temp = weechat_string_replace (res, "$realname", realname); diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 573892788..8aa118f1b 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -248,12 +248,12 @@ IRC_PROTOCOL_CALLBACK(authenticate) { sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); answer = NULL; switch (sasl_mechanism) @@ -2496,9 +2496,9 @@ IRC_PROTOCOL_CALLBACK(001) WEECHAT_HOOK_SIGNAL_STRING, server->name); /* set usermode when connected */ - usermode = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE), - NULL, NULL, NULL); + usermode = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERMODE)); if (usermode && usermode[0]) { irc_server_sendf (server, @@ -2510,9 +2510,9 @@ IRC_PROTOCOL_CALLBACK(001) free (usermode); /* execute command when connected */ - server_command = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND), - NULL, NULL, NULL); + server_command = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_COMMAND)); if (server_command && server_command[0]) { /* split command on ';' which can be escaped with '\;' */ diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index cdeb679a2..ab332c03e 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdarg.h> #include <string.h> +#include <ctype.h> #include <time.h> #ifdef _WIN32 #include <winsock.h> @@ -338,6 +339,152 @@ irc_server_strncasecmp (struct t_irc_server *server, } /* + * Evaluates a string using the server as context: + * ${irc_server.xxx} and ${server} are replaced by a server option and the + * server name. + * + * Returns the evaluated string. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_expression (struct t_irc_server *server, const char *string) +{ + struct t_hashtable *pointers, *extra_vars; + char *value; + + pointers = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_POINTER, + NULL, NULL); + extra_vars = weechat_hashtable_new ( + 32, + WEECHAT_HASHTABLE_STRING, + WEECHAT_HASHTABLE_STRING, + NULL, NULL); + + if (server) + { + if (pointers) + weechat_hashtable_set (pointers, "irc_server", server); + if (extra_vars) + weechat_hashtable_set (extra_vars, "server", server->name); + } + + value = weechat_string_eval_expression (string, + pointers, extra_vars, NULL); + + if (pointers) + weechat_hashtable_free (pointers); + if (extra_vars) + weechat_hashtable_free (extra_vars); + + return value; +} + +/* + * Evaluates and returns the fingerprint. + * + * Returns the evaluated fingerprint, NULL if the fingerprint option is + * invalid. + * + * Note: result must be freed after use. + */ + +char * +irc_server_eval_fingerprint (struct t_irc_server *server) +{ +#ifdef HAVE_GNUTLS + const char *ptr_fingerprint; + char *fingerprint_eval, **fingerprints, *str_sizes; + int i, j, rc, algo, length; + + ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, + IRC_SERVER_OPTION_SSL_FINGERPRINT); + + /* empty fingerprint is just ignored (considered OK) */ + if (!ptr_fingerprint || !ptr_fingerprint[0]) + return strdup (""); + + /* evaluate fingerprint */ + fingerprint_eval = irc_server_eval_expression (server, ptr_fingerprint); + if (!fingerprint_eval || !fingerprint_eval[0]) + { + weechat_printf ( + server->buffer, + _("%s%s: the evaluated fingerprint for server \"%s\" must not be " + "empty"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name); + if (fingerprint_eval) + free (fingerprint_eval); + return NULL; + } + + /* split fingerprint */ + fingerprints = weechat_string_split (fingerprint_eval, ",", 0, 0, NULL); + if (!fingerprints) + return fingerprint_eval; + + 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 = -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 ( + server->buffer, + _("%s%s: invalid fingerprint size for server \"%s\", the " + "number of hexadecimal digits must be " + "one of: %s"), + weechat_prefix ("error"), + IRC_PLUGIN_NAME, + server->name, + (str_sizes) ? str_sizes : "?"); + if (str_sizes) + free (str_sizes); + free (fingerprint_eval); + return NULL; + case -2: /* invalid content */ + weechat_printf ( + server->buffer, + _("%s%s: invalid fingerprint for server \"%s\", it must " + "contain only hexadecimal digits (0-9, " + "a-f)"), + weechat_prefix ("error"), IRC_PLUGIN_NAME, server->name); + free (fingerprint_eval); + return NULL; + } + return fingerprint_eval; +#else + return strdup (""); +#endif /* HAVE_GNUTLS */ +} + +/* * Checks if SASL is enabled on server. * * Returns: @@ -354,12 +501,12 @@ irc_server_sasl_enabled (struct t_irc_server *server) sasl_mechanism = IRC_SERVER_OPTION_INTEGER( server, IRC_SERVER_OPTION_SASL_MECHANISM); - sasl_username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME), - NULL, NULL, NULL); - sasl_password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD), - NULL, NULL, NULL); + sasl_username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_USERNAME)); + sasl_password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_PASSWORD)); sasl_key = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SASL_KEY); /* @@ -423,8 +570,7 @@ irc_server_set_addresses (struct t_irc_server *server, const char *addresses) if (addresses && addresses[0]) { - addresses_eval = weechat_string_eval_expression (addresses, - NULL, NULL, NULL); + addresses_eval = irc_server_eval_expression (server, addresses); if (server->addresses_eval && (strcmp (server->addresses_eval, addresses_eval) == 0)) { @@ -551,7 +697,7 @@ irc_server_set_nicks (struct t_irc_server *server, const char *nicks) } /* evaluate value */ - nicks2 = weechat_string_eval_expression (nicks, NULL, NULL, NULL); + nicks2 = irc_server_eval_expression (server, nicks); /* set new nicks */ server->nicks_array = weechat_string_split ( @@ -3503,15 +3649,15 @@ irc_server_login (struct t_irc_server *server) const char *capabilities; char *password, *username, *realname, *username2; - password = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD), - NULL, NULL, NULL); - username = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME), - NULL, NULL, NULL); - realname = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME), - NULL, NULL, NULL); + password = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_PASSWORD)); + username = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_USERNAME)); + realname = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_REALNAME)); capabilities = IRC_SERVER_OPTION_STRING( server, IRC_SERVER_OPTION_CAPABILITIES); @@ -4230,8 +4376,12 @@ irc_server_gnutls_callback (const void *pointer, void *data, /* get fingerprint option in server */ ptr_fingerprint = IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_SSL_FINGERPRINT); - fingerprint_eval = weechat_string_eval_expression (ptr_fingerprint, - NULL, NULL, NULL); + fingerprint_eval = irc_server_eval_fingerprint (server); + if (!fingerprint_eval) + { + rc = -1; + goto end; + } /* set match options */ fingerprint_match = (ptr_fingerprint && ptr_fingerprint[0]) ? 0 : 1; @@ -4963,9 +5113,9 @@ irc_server_autojoin_create_buffers (struct t_irc_server *server) return; /* evaluate server option "autojoin" */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); /* extract channel names from autojoin option */ if (autojoin && autojoin[0]) @@ -5036,9 +5186,9 @@ irc_server_autojoin_channels (struct t_irc_server *server) else { /* auto-join when connecting to server for first time */ - autojoin = weechat_string_eval_expression ( - IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN), - NULL, NULL, NULL); + autojoin = irc_server_eval_expression ( + server, + IRC_SERVER_OPTION_STRING(server, IRC_SERVER_OPTION_AUTOJOIN)); if (!server->disable_autojoin && autojoin && autojoin[0]) irc_command_join_server (server, autojoin, 0, 0); if (autojoin) diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index 6fc42f7cd..84b64ca6d 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -280,6 +280,8 @@ extern int irc_server_strcasecmp (struct t_irc_server *server, extern int irc_server_strncasecmp (struct t_irc_server *server, const char *string1, const char *string2, int max); +extern char *irc_server_eval_expression (struct t_irc_server *server, + const char *string); extern int irc_server_sasl_enabled (struct t_irc_server *server); extern char *irc_server_get_name_without_port (const char *name); extern int irc_server_set_addresses (struct t_irc_server *server, |