summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2018-02-05 21:41:03 +0100
committerSébastien Helleu <flashcode@flashtux.org>2018-02-05 21:41:03 +0100
commitf889306c5edf5eeb37a9e37e6468ec0ac549d32c (patch)
tree8ff4f825d32214d9ebbe811b77d6e4ba42b973d6 /src
parente2b439d046996662042356ef0571168db165c210 (diff)
downloadweechat-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.c126
-rw-r--r--src/plugins/irc/irc-ctcp.c12
-rw-r--r--src/plugins/irc/irc-protocol.c24
-rw-r--r--src/plugins/irc/irc-server.c202
-rw-r--r--src/plugins/irc/irc-server.h2
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,