diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2018-11-04 14:26:59 +0100 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2018-11-04 14:50:53 +0100 |
commit | 738535e7f628d9b4a26cccc8b598e07e63ac1123 (patch) | |
tree | bbc7de232fb6bf78f72ce82a4ac5a4a6200a88c7 | |
parent | f02fc06dd05310c8d97410bbb00c120b47f885ee (diff) | |
download | weechat-738535e7f628d9b4a26cccc8b598e07e63ac1123.zip |
relay: add support of Time-based One-Time Password (TOTP) as second authentication factor in weechat protocol
-rw-r--r-- | ChangeLog.adoc | 1 | ||||
-rw-r--r-- | doc/de/weechat_user.de.adoc | 29 | ||||
-rw-r--r-- | doc/en/weechat_relay_protocol.en.adoc | 11 | ||||
-rw-r--r-- | doc/en/weechat_user.en.adoc | 28 | ||||
-rw-r--r-- | doc/fr/weechat_relay_protocol.fr.adoc | 11 | ||||
-rw-r--r-- | doc/fr/weechat_user.fr.adoc | 30 | ||||
-rw-r--r-- | doc/it/weechat_user.it.adoc | 29 | ||||
-rw-r--r-- | doc/ja/weechat_relay_protocol.ja.adoc | 13 | ||||
-rw-r--r-- | doc/ja/weechat_user.ja.adoc | 29 | ||||
-rw-r--r-- | doc/pl/weechat_user.pl.adoc | 29 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.c | 88 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.h | 6 | ||||
-rw-r--r-- | src/plugins/relay/relay-server.c | 60 | ||||
-rw-r--r-- | src/plugins/relay/weechat/relay-weechat-protocol.c | 56 | ||||
-rw-r--r-- | src/plugins/relay/weechat/relay-weechat.c | 21 | ||||
-rw-r--r-- | src/plugins/relay/weechat/relay-weechat.h | 1 |
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 */ |