summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2018-11-04 14:26:59 +0100
committerSébastien Helleu <flashcode@flashtux.org>2018-11-04 14:50:53 +0100
commit738535e7f628d9b4a26cccc8b598e07e63ac1123 (patch)
treebbc7de232fb6bf78f72ce82a4ac5a4a6200a88c7
parentf02fc06dd05310c8d97410bbb00c120b47f885ee (diff)
downloadweechat-738535e7f628d9b4a26cccc8b598e07e63ac1123.zip
relay: add support of Time-based One-Time Password (TOTP) as second authentication factor in weechat protocol
-rw-r--r--ChangeLog.adoc1
-rw-r--r--doc/de/weechat_user.de.adoc29
-rw-r--r--doc/en/weechat_relay_protocol.en.adoc11
-rw-r--r--doc/en/weechat_user.en.adoc28
-rw-r--r--doc/fr/weechat_relay_protocol.fr.adoc11
-rw-r--r--doc/fr/weechat_user.fr.adoc30
-rw-r--r--doc/it/weechat_user.it.adoc29
-rw-r--r--doc/ja/weechat_relay_protocol.ja.adoc13
-rw-r--r--doc/ja/weechat_user.ja.adoc29
-rw-r--r--doc/pl/weechat_user.pl.adoc29
-rw-r--r--src/plugins/relay/relay-config.c88
-rw-r--r--src/plugins/relay/relay-config.h6
-rw-r--r--src/plugins/relay/relay-server.c60
-rw-r--r--src/plugins/relay/weechat/relay-weechat-protocol.c56
-rw-r--r--src/plugins/relay/weechat/relay-weechat.c21
-rw-r--r--src/plugins/relay/weechat/relay-weechat.h1
16 files changed, 409 insertions, 33 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc
index 3d3fea9fb..e59a08acc 100644
--- a/ChangeLog.adoc
+++ b/ChangeLog.adoc
@@ -22,6 +22,7 @@ New features::
* api: add functions string_base_encode and string_base_decode, remove functions string_encode_base64 and string_decode_base64
* api: add support of Time-based One-Time Password (TOTP), add infos "totp_generate" and "totp_validate"
+ * relay: add support of Time-based One-Time Password (TOTP) as second authentication factor in weechat protocol
Bug fixes::
diff --git a/doc/de/weechat_user.de.adoc b/doc/de/weechat_user.de.adoc
index 109780656..b5636e093 100644
--- a/doc/de/weechat_user.de.adoc
+++ b/doc/de/weechat_user.de.adoc
@@ -3233,6 +3233,35 @@ Es wird nachdrücklich Empfohlen ein Passwort für die Relay-Verbindung zu nutze
Dieses Passwort wird sowohl für das _irc_ als auch für das _weechat_ Protokoll
verwendet.
+// TRANSLATION MISSING
+[[relay_totp]]
+==== TOTP
+
+TOTP (Time-based One-Time Password) can be used as secondary authentication
+factor for _weechat_ protocol, in addition to the password.
+
+This is optional and increases the security level.
+
+One-time passwords can be generated with applications, for example:
+
+* FreeOTP:
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[web site])
+* Google Authenticator:
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+The TOTP secret must be set in WeeChat and the application used to generate
+one-time passwords.
+
+It must be a string encoded in base32, with only letters and digits from 2 to 7,
+for example:
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/doc/en/weechat_relay_protocol.en.adoc b/doc/en/weechat_relay_protocol.en.adoc
index afe0a0c1a..ac6999471 100644
--- a/doc/en/weechat_relay_protocol.en.adoc
+++ b/doc/en/weechat_relay_protocol.en.adoc
@@ -114,8 +114,12 @@ init [<option>=<value>,[<option>=<value>,...]]
Arguments:
* _option_: one of following options:
-** _password_: password used to authenticate on _relay_ (option
- _relay.network.password_ in WeeChat)
+** _password_: password used to authenticate on _relay_
+ (option _relay.network.password_ in WeeChat)
+** _totp_: Time-based One-Time Password (TOTP) used as secondary authentication
+ factor, in addition to the password
+ (option _relay.network.totp_secret_ in WeeChat)
+ _(WeeChat ≥ 2.4)_
** _compression_: compression type:
*** _zlib_: enable _zlib_ compression for messages sent by _relay_
(enabled by default if _relay_ supports _zlib_ compression)
@@ -134,6 +138,9 @@ init password=mypass
# initialize with commas in the password (WeeChat ≥ 1.6)
init password=mypass\,with\,commas
+# initialize with password and TOTP (WeeChat ≥ 2.4)
+init password=mypass,totp=123456
+
# initialize and disable compression
init password=mypass,compression=off
----
diff --git a/doc/en/weechat_user.en.adoc b/doc/en/weechat_user.en.adoc
index efbcff4fe..361c452b7 100644
--- a/doc/en/weechat_user.en.adoc
+++ b/doc/en/weechat_user.en.adoc
@@ -3161,6 +3161,34 @@ It is highly recommended to set a password for relay, with command:
This password is used for _irc_ and _weechat_ protocols.
+[[relay_totp]]
+==== TOTP
+
+TOTP (Time-based One-Time Password) can be used as secondary authentication
+factor for _weechat_ protocol, in addition to the password.
+
+This is optional and increases the security level.
+
+One-time passwords can be generated with applications, for example:
+
+* FreeOTP:
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[web site])
+* Google Authenticator:
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+The TOTP secret must be set in WeeChat and the application used to generate
+one-time passwords.
+
+It must be a string encoded in base32, with only letters and digits from 2 to 7,
+for example:
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/doc/fr/weechat_relay_protocol.fr.adoc b/doc/fr/weechat_relay_protocol.fr.adoc
index 353345496..cb1800d45 100644
--- a/doc/fr/weechat_relay_protocol.fr.adoc
+++ b/doc/fr/weechat_relay_protocol.fr.adoc
@@ -119,8 +119,12 @@ init [<option>=<valeur>,[<option>=<valeur>,...]]
Paramètres :
* _option_ : une des options suivantes :
-** _password_ : mot de passe utilisé pour s'authentifier avec _relay_ (option
- _relay.network.password_ dans WeeChat)
+** _password_ : mot de passe utilisé pour s'authentifier avec _relay_
+ (option _relay.network.password_ dans WeeChat)
+** _totp_ : mot de passe à usage unique basé sur le temps (TOTP : Time-based
+ One-Time Password) utilisé comme second facteur d'authentification, en plus
+ du mot de passe (option _relay.network.totp_secret_ dans WeeChat)
+ _(WeeChat ≥ 2.4)_
** _compression_ : type de compression :
*** _zlib_ : activer la compression _zlib_ pour les messages envoyés par _relay_
(activée par défaut si _relay_ supporte la compression _zlib_)
@@ -139,6 +143,9 @@ init password=mypass
# initialiser avec des virgules dans le mot de passe (WeeChat ≥ 1.6)
init password=mypass\,avec\,virgules
+# initialiser avec le mot de passe et TOTP (WeeChat ≥ 2.4)
+init password=mypass,totp=123456
+
# initialiser et désactiver la compression
init password=mypass,compression=off
----
diff --git a/doc/fr/weechat_user.fr.adoc b/doc/fr/weechat_user.fr.adoc
index 9a627fbb2..45c1d1e23 100644
--- a/doc/fr/weechat_user.fr.adoc
+++ b/doc/fr/weechat_user.fr.adoc
@@ -3261,6 +3261,36 @@ commande :
Ce mot de passe sera utilisé pour les protocoles _irc_ et _weechat_.
+[[relay_totp]]
+==== TOTP
+
+TOTP (« Time-based One-Time Password » : mot de passe à usage unique basé sur le
+temps) peut être utilisé comme second facteur d'authentification pour le protocole
+_weechat_, en plus du mot de passe.
+
+Il est optionnel et augmente le niveau de sécurité.
+
+Les mots de passe à usage unique peuvent être générés avec des applications,
+par exemple :
+
+* FreeOTP :
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[site web])
+* Google Authenticator :
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+Le « secret » TOTP doit être défini dans WeeChat et dans l'application utilisée
+pour générer les mots de passe à usage unique.
+
+Il doit être une chaîne encodée en base32, avec seulement des lettres et des
+chiffres de 2 à 7, par exemple :
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/doc/it/weechat_user.it.adoc b/doc/it/weechat_user.it.adoc
index 4137555ab..ed973e96d 100644
--- a/doc/it/weechat_user.it.adoc
+++ b/doc/it/weechat_user.it.adoc
@@ -3373,6 +3373,35 @@ It is highly recommended to set a password for relay, with command:
This password is used for _irc_ and _weechat_ protocols.
+// TRANSLATION MISSING
+[[relay_totp]]
+==== TOTP
+
+TOTP (Time-based One-Time Password) can be used as secondary authentication
+factor for _weechat_ protocol, in addition to the password.
+
+This is optional and increases the security level.
+
+One-time passwords can be generated with applications, for example:
+
+* FreeOTP:
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[web site])
+* Google Authenticator:
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+The TOTP secret must be set in WeeChat and the application used to generate
+one-time passwords.
+
+It must be a string encoded in base32, with only letters and digits from 2 to 7,
+for example:
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/doc/ja/weechat_relay_protocol.ja.adoc b/doc/ja/weechat_relay_protocol.ja.adoc
index 2fa3181e4..172eedfc9 100644
--- a/doc/ja/weechat_relay_protocol.ja.adoc
+++ b/doc/ja/weechat_relay_protocol.ja.adoc
@@ -121,8 +121,13 @@ init [<option>=<value>,[<option>=<value>,...]]
引数:
* _option_: 以下のうちの 1 つ:
-** _password_: _リレー_ の認証用パスワード (WeeChat の
- _relay.network.password_ オプション)
+** _password_: _リレー_ の認証用パスワード
+ (WeeChat の _relay.network.password_ オプション)
+// TRANSLATION MISSING
+** _totp_: Time-based One-Time Password (TOTP) used as secondary authentication
+ factor, in addition to the password
+ (WeeChat の _relay.network.totp_secret_ オプション)
+ _(WeeChat ≥ 2.4)_
** _compression_: 圧縮タイプ:
*** _zlib_: _リレー_ から受信するメッセージに対して _zlib_ 圧縮を使う
(_リレー_ が _zlib_ 圧縮をサポートしている場合、デフォルトで有効化されます)
@@ -132,6 +137,7 @@ init [<option>=<value>,[<option>=<value>,...]]
WeeChat バージョン 1.6 以上の場合、コンマをエスケープすることで value にコンマを設定可能です。例えば
"foo,bar" というパスワードを送信するには `init password=foo\,bar` のように設定してください。
+// TRANSLATION MISSING
例:
----
@@ -141,6 +147,9 @@ init password=mypass
# パスワードにコンマを含む値を設定する例 (WeeChat バージョン 1.6 以上の場合)
init password=mypass\,with\,commas
+# initialize with password and TOTP (WeeChat ≥ 2.4)
+init password=mypass,totp=123456
+
# 圧縮を使わない例
init password=mypass,compression=off
----
diff --git a/doc/ja/weechat_user.ja.adoc b/doc/ja/weechat_user.ja.adoc
index b8161f9a4..5b3c92bd9 100644
--- a/doc/ja/weechat_user.ja.adoc
+++ b/doc/ja/weechat_user.ja.adoc
@@ -3155,6 +3155,35 @@ Relay プラグインはネットワークを介して異なるプロトコル
このパスワードは _irc_ と _weechat_ プロトコルで利用されます。
+// TRANSLATION MISSING
+[[relay_totp]]
+==== TOTP
+
+TOTP (Time-based One-Time Password) can be used as secondary authentication
+factor for _weechat_ protocol, in addition to the password.
+
+This is optional and increases the security level.
+
+One-time passwords can be generated with applications, for example:
+
+* FreeOTP:
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[web site])
+* Google Authenticator:
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+The TOTP secret must be set in WeeChat and the application used to generate
+one-time passwords.
+
+It must be a string encoded in base32, with only letters and digits from 2 to 7,
+for example:
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/doc/pl/weechat_user.pl.adoc b/doc/pl/weechat_user.pl.adoc
index 295a287c5..e17a050a6 100644
--- a/doc/pl/weechat_user.pl.adoc
+++ b/doc/pl/weechat_user.pl.adoc
@@ -3186,6 +3186,35 @@ Zalecane jest ustawienie hasła dla pośrednika, za pomocą komendy:
Hasło to używane jest przez protokoły _irc_ i _weechat_.
+// TRANSLATION MISSING
+[[relay_totp]]
+==== TOTP
+
+TOTP (Time-based One-Time Password) can be used as secondary authentication
+factor for _weechat_ protocol, in addition to the password.
+
+This is optional and increases the security level.
+
+One-time passwords can be generated with applications, for example:
+
+* FreeOTP:
+ https://play.google.com/store/apps/details?id=org.fedorahosted.freeotp[Android],
+ https://itunes.apple.com/fr/app/freeotp-authenticator/id872559395[iOS]
+ (https://freeotp.github.io/[web site])
+* Google Authenticator:
+ https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2[Android],
+ https://itunes.apple.com/fr/app/google-authenticator/id388497605[iOS]
+
+The TOTP secret must be set in WeeChat and the application used to generate
+one-time passwords.
+
+It must be a string encoded in base32, with only letters and digits from 2 to 7,
+for example:
+
+----
+/set relay.network.totp_secret "secretpasswordbase32"
+----
+
[[relay_ssl]]
==== SSL
diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c
index 27fa0974c..a07d868ef 100644
--- a/src/plugins/relay/relay-config.c
+++ b/src/plugins/relay/relay-config.c
@@ -62,6 +62,8 @@ struct t_config_option *relay_config_network_max_clients;
struct t_config_option *relay_config_network_password;
struct t_config_option *relay_config_network_ssl_cert_key;
struct t_config_option *relay_config_network_ssl_priorities;
+struct t_config_option *relay_config_network_totp_secret;
+struct t_config_option *relay_config_network_totp_window;
struct t_config_option *relay_config_network_websocket_allowed_origins;
/* relay config, irc section */
@@ -203,7 +205,66 @@ relay_config_change_network_ssl_cert_key (const void *pointer, void *data,
}
/*
- * Callback for changes on option "relay.network.ssl_priorities".
+ * Checks if option "relay.network.totp_secret" is valid.
+ *
+ * Returns:
+ * 1: value is valid
+ * 0: value is not valid
+ */
+
+int
+relay_config_check_network_totp_secret (const void *pointer, void *data,
+ struct t_config_option *option,
+ const char *value)
+{
+ char *totp_secret, *secret;
+ int rc, length;
+
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) option;
+
+ totp_secret = NULL;
+ secret = NULL;
+
+ totp_secret = weechat_string_eval_expression (value, NULL, NULL, NULL);
+ if (totp_secret && totp_secret[0])
+ {
+ secret = malloc (strlen (totp_secret) + 1);
+ if (!secret)
+ goto error;
+ length = weechat_string_base_decode (32, totp_secret, secret);
+ if (length < 0)
+ goto error;
+ }
+
+ rc = 1;
+ goto end;
+
+error:
+ rc = 0;
+ weechat_printf (NULL,
+ _("%s%s: invalid value for option "
+ "\"relay.network.totp_secret\"; it must be a valid "
+ "string encoded in base32 "
+ "(only letters and digits from 2 to 7)"),
+ weechat_prefix ("error"), RELAY_PLUGIN_NAME);
+
+end:
+ if (totp_secret)
+ free (totp_secret);
+ if (secret)
+ free (secret);
+ return rc;
+}
+
+/*
+ * Checks if option "relay.network.ssl_priorities" is valid.
+ *
+ * Returns:
+ * 1: value is valid
+ * 0: value is not valid
*/
int
@@ -842,6 +903,31 @@ relay_config_init ()
&relay_config_check_network_ssl_priorities, NULL, NULL,
&relay_config_change_network_ssl_priorities, NULL, NULL,
NULL, NULL, NULL);
+ relay_config_network_totp_secret = weechat_config_new_option (
+ relay_config_file, ptr_section,
+ "totp_secret", "string",
+ N_("secret for the generation of the Time-based One-Time Password "
+ "(TOTP), encoded in base32 (only letters and digits from 2 to 7); "
+ "it is used as second factor in weechat protocol, in addition to "
+ "the password, which must not be empty "
+ "(empty value means no TOTP is required) "
+ "(note: content is evaluated, see /help eval)"),
+ NULL, 0, 0, "", NULL, 0,
+ &relay_config_check_network_totp_secret, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
+ relay_config_network_totp_window = weechat_config_new_option (
+ relay_config_file, ptr_section,
+ "totp_window", "integer",
+ N_("number of Time-based One-Time Passwords to accept before and "
+ "after the current one: "
+ "0 = accept only the current password, "
+ "1 = accept one password before, the current, and one after, "
+ "2 = accept two passwords before, the current, and two after, "
+ "...; a high number reduces the security level "
+ "(0 or 1 are recommended values)"),
+ NULL, 0, 256, "0", NULL, 0,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
relay_config_network_websocket_allowed_origins = weechat_config_new_option (
relay_config_file, ptr_section,
"websocket_allowed_origins", "string",
diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h
index 0555bb88c..b5ceb5247 100644
--- a/src/plugins/relay/relay-config.h
+++ b/src/plugins/relay/relay-config.h
@@ -46,6 +46,8 @@ extern struct t_config_option *relay_config_network_max_clients;
extern struct t_config_option *relay_config_network_password;
extern struct t_config_option *relay_config_network_ssl_cert_key;
extern struct t_config_option *relay_config_network_ssl_priorities;
+extern struct t_config_option *relay_config_network_totp_secret;
+extern struct t_config_option *relay_config_network_totp_window;
extern struct t_config_option *relay_config_network_websocket_allowed_origins;
extern struct t_config_option *relay_config_irc_backlog_max_minutes;
@@ -59,6 +61,10 @@ extern regex_t *relay_config_regex_allowed_ips;
extern regex_t *relay_config_regex_websocket_allowed_origins;
extern struct t_hashtable *relay_config_hashtable_irc_backlog_tags;
+extern int relay_config_check_network_totp_secret (const void *pointer,
+ void *data,
+ struct t_config_option *option,
+ const char *value);
extern int relay_config_create_option_port (const void *pointer, void *data,
struct t_config_file *config_file,
struct t_config_section *section,
diff --git a/src/plugins/relay/relay-server.c b/src/plugins/relay/relay-server.c
index b10a758be..3805f623f 100644
--- a/src/plugins/relay/relay-server.c
+++ b/src/plugins/relay/relay-server.c
@@ -228,13 +228,16 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
void *ptr_addr;
int client_fd, flags, set, max_clients, num_clients_on_port;
char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1];
- char *ptr_ip_address;
- const char *relay_password;
+ char *ptr_ip_address, *relay_password, *relay_totp_secret;
/* make C compiler happy */
(void) data;
(void) fd;
+ client_fd = -1;
+ relay_password = NULL;
+ relay_totp_secret = NULL;
+
server = (struct t_relay_server *)pointer;
if (server->ipv6)
@@ -259,7 +262,7 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
server->port, server->protocol_string,
errno, strerror (errno));
- return WEECHAT_RC_OK;
+ goto error;
}
/* check if relay password is empty and if it is not allowed */
@@ -274,8 +277,34 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
"is empty, and option "
"relay.network.allow_empty_password is off"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME);
- close (client_fd);
- return WEECHAT_RC_OK;
+ goto error;
+ }
+
+ if (server->protocol == RELAY_PROTOCOL_WEECHAT)
+ {
+ /*
+ * TOTP can be enabled only as second factor, in addition to the
+ * password (only for weechat protocol)
+ */
+ relay_totp_secret = weechat_string_eval_expression (
+ weechat_config_string (relay_config_network_totp_secret),
+ NULL, NULL, NULL);
+ if ((!relay_password || !relay_password[0])
+ && relay_totp_secret && relay_totp_secret[0])
+ {
+ weechat_printf (NULL,
+ _("%s%s: Time-based One-Time Password (TOTP) "
+ "can be enabled only as second factor, if the "
+ "password is not empty"),
+ weechat_prefix ("error"), RELAY_PLUGIN_NAME);
+ goto error;
+ }
+ if (!relay_config_check_network_totp_secret (
+ NULL, NULL, NULL,
+ weechat_config_string (relay_config_network_totp_secret)))
+ {
+ goto error;
+ }
}
/* check if we have reached the max number of clients on this port */
@@ -294,8 +323,7 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
max_clients),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
max_clients);
- close (client_fd);
- return WEECHAT_RC_OK;
+ goto error;
}
}
@@ -340,8 +368,7 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
RELAY_PLUGIN_NAME,
ptr_ip_address);
}
- close (client_fd);
- return WEECHAT_RC_OK;
+ goto error;
}
/* set non-blocking mode for socket */
@@ -360,13 +387,24 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
"error %d %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
"SO_REUSEADDR", set, errno, strerror (errno));
- close (client_fd);
- return WEECHAT_RC_OK;
+ goto error;
}
/* add the client */
relay_client_new (client_fd, ptr_ip_address, server);
+ goto end;
+
+error:
+ if (client_fd >= 0)
+ close (client_fd);
+
+end:
+ if (relay_password)
+ free (relay_password);
+ if (relay_totp_secret)
+ free (relay_totp_secret);
+
return WEECHAT_RC_OK;
}
diff --git a/src/plugins/relay/weechat/relay-weechat-protocol.c b/src/plugins/relay/weechat/relay-weechat-protocol.c
index 62b93e09e..f8f557113 100644
--- a/src/plugins/relay/weechat/relay-weechat-protocol.c
+++ b/src/plugins/relay/weechat/relay-weechat-protocol.c
@@ -169,8 +169,9 @@ relay_weechat_protocol_is_sync (struct t_relay_client *ptr_client,
RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
{
- char **options, *pos, *password;
- int i, compression;
+ char **options, *pos, *password, *totp_secret, *info_totp_args;
+ const char *info_totp;
+ int i, compression, length;
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(1);
@@ -186,20 +187,41 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
pos++;
if (strcmp (options[i], "password") == 0)
{
- password = weechat_string_eval_expression (weechat_config_string (relay_config_network_password),
- NULL, NULL, NULL);
+ password = weechat_string_eval_expression (
+ weechat_config_string (relay_config_network_password),
+ NULL, NULL, NULL);
if (password)
{
if (strcmp (password, pos) == 0)
- {
RELAY_WEECHAT_DATA(client, password_ok) = 1;
- weechat_hook_signal_send ("relay_client_auth_ok",
- WEECHAT_HOOK_SIGNAL_POINTER,
- client);
- }
free (password);
}
}
+ else if (strcmp (options[i], "totp") == 0)
+ {
+ totp_secret = weechat_string_eval_expression (
+ weechat_config_string (relay_config_network_totp_secret),
+ NULL, NULL, NULL);
+ if (totp_secret)
+ {
+ length = strlen (totp_secret) + strlen (pos) + 16 + 1;
+ info_totp_args = malloc (length);
+ if (info_totp_args)
+ {
+ /* validate the OTP received from the client */
+ snprintf (info_totp_args, length,
+ "%s,%s,0,%d",
+ totp_secret, /* the shared secret */
+ pos, /* the OTP from client */
+ weechat_config_integer (relay_config_network_totp_window));
+ info_totp = weechat_info_get ("totp_validate", info_totp_args);
+ if (info_totp && (strcmp (info_totp, "1") == 0))
+ RELAY_WEECHAT_DATA(client, totp_ok) = 1;
+ free (info_totp_args);
+ }
+ free (totp_secret);
+ }
+ }
else if (strcmp (options[i], "compression") == 0)
{
compression = relay_weechat_compression_search (pos);
@@ -211,8 +233,17 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
weechat_string_free_split_command (options);
}
- if (!RELAY_WEECHAT_DATA(client, password_ok))
+ if (RELAY_WEECHAT_DATA(client, password_ok)
+ && RELAY_WEECHAT_DATA(client, totp_ok))
+ {
+ weechat_hook_signal_send ("relay_client_auth_ok",
+ WEECHAT_HOOK_SIGNAL_POINTER,
+ client);
+ }
+ else
+ {
relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED);
+ }
return WEECHAT_RC_OK;
}
@@ -1383,10 +1414,11 @@ relay_weechat_protocol_recv (struct t_relay_client *client, const char *data)
if (strcmp (protocol_cb[i].name, command) == 0)
{
if ((strcmp (protocol_cb[i].name, "init") != 0)
- && (!RELAY_WEECHAT_DATA(client, password_ok)))
+ && (!RELAY_WEECHAT_DATA(client, password_ok)
+ || !RELAY_WEECHAT_DATA(client, totp_ok)))
{
/*
- * command is not "init" and password is not set?
+ * command is not "init" and password or totp are not set?
* then close connection!
*/
relay_client_set_status (client,
diff --git a/src/plugins/relay/weechat/relay-weechat.c b/src/plugins/relay/weechat/relay-weechat.c
index 8a7bd8d0f..f30d640ed 100644
--- a/src/plugins/relay/weechat/relay-weechat.c
+++ b/src/plugins/relay/weechat/relay-weechat.c
@@ -166,15 +166,20 @@ relay_weechat_free_buffers_nicklist (struct t_hashtable *hashtable,
void
relay_weechat_alloc (struct t_relay_client *client)
{
- char *password;
+ char *password, *totp_secret;
- password = weechat_string_eval_expression (weechat_config_string (relay_config_network_password),
- NULL, NULL, NULL);
+ password = weechat_string_eval_expression (
+ weechat_config_string (relay_config_network_password),
+ NULL, NULL, NULL);
+ totp_secret = weechat_string_eval_expression (
+ weechat_config_string (relay_config_network_totp_secret),
+ NULL, NULL, NULL);
client->protocol_data = malloc (sizeof (struct t_relay_weechat_data));
if (client->protocol_data)
{
RELAY_WEECHAT_DATA(client, password_ok) = (password && password[0]) ? 0 : 1;
+ RELAY_WEECHAT_DATA(client, totp_ok) = (totp_secret && totp_secret[0]) ? 0 : 1;
RELAY_WEECHAT_DATA(client, compression) = RELAY_WEECHAT_COMPRESSION_ZLIB;
RELAY_WEECHAT_DATA(client, buffers_sync) =
weechat_hashtable_new (32,
@@ -199,6 +204,8 @@ relay_weechat_alloc (struct t_relay_client *client)
if (password)
free (password);
+ if (totp_secret)
+ free (totp_secret);
}
/*
@@ -221,6 +228,11 @@ relay_weechat_alloc_with_infolist (struct t_relay_client *client,
/* general stuff */
RELAY_WEECHAT_DATA(client, password_ok) = weechat_infolist_integer (
infolist, "password_ok");
+ /* "totp_ok" is new in WeeChat 2.4 */
+ if (weechat_infolist_search_var (infolist, "totp_ok"))
+ RELAY_WEECHAT_DATA(client, totp_ok) = weechat_infolist_integer (infolist, "totp_ok");
+ else
+ RELAY_WEECHAT_DATA(client, totp_ok) = 1;
RELAY_WEECHAT_DATA(client, compression) = weechat_infolist_integer (
infolist, "compression");
@@ -314,6 +326,8 @@ relay_weechat_add_to_infolist (struct t_infolist_item *item,
if (!weechat_infolist_new_var_integer (item, "password_ok", RELAY_WEECHAT_DATA(client, password_ok)))
return 0;
+ if (!weechat_infolist_new_var_integer (item, "totp_ok", RELAY_WEECHAT_DATA(client, totp_ok)))
+ return 0;
if (!weechat_infolist_new_var_integer (item, "compression", RELAY_WEECHAT_DATA(client, compression)))
return 0;
if (!weechat_hashtable_add_to_infolist (RELAY_WEECHAT_DATA(client, buffers_sync), item, "buffers_sync"))
@@ -332,6 +346,7 @@ relay_weechat_print_log (struct t_relay_client *client)
if (client->protocol_data)
{
weechat_log_printf (" password_ok. . . . . . : %d", RELAY_WEECHAT_DATA(client, password_ok));
+ weechat_log_printf (" totp_ok. . . . . . . . : %d", RELAY_WEECHAT_DATA(client, totp_ok));
weechat_log_printf (" compression. . . . . . : %d", RELAY_WEECHAT_DATA(client, compression));
weechat_log_printf (" buffers_sync . . . . . : 0x%lx (hashtable: '%s')",
RELAY_WEECHAT_DATA(client, buffers_sync),
diff --git a/src/plugins/relay/weechat/relay-weechat.h b/src/plugins/relay/weechat/relay-weechat.h
index 75e8efe85..a93ad2e15 100644
--- a/src/plugins/relay/weechat/relay-weechat.h
+++ b/src/plugins/relay/weechat/relay-weechat.h
@@ -36,6 +36,7 @@ enum t_relay_weechat_compression
struct t_relay_weechat_data
{
int password_ok; /* password received and OK? */
+ int totp_ok; /* TOTP received and OK? */
enum t_relay_weechat_compression compression; /* compression type */
/* sync of buffers */