mirror of
https://github.com/weechat/weechat.git
synced 2026-07-01 02:45:42 +02:00
relay/irc: fix timing attack on PASS command (GHSA-vhv8-g2r9-cwcc)
The IRC relay protocol's PASS handler compared the server password with the client-supplied value using strcmp, leaking the password byte-by-byte via response timing. This is the same class of bug fixed for the api and weechat protocols, on a separate code path that did not go through relay_auth_check_password_plain. Extract the HMAC-then-constant-time-compare logic from relay_auth_check_password_plain into relay_auth_password_equals, then use it in both the plain-auth wrapper and the IRC PASS handler.
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
#include "../../weechat-plugin.h"
|
||||
#include "../relay.h"
|
||||
#include "relay-irc.h"
|
||||
#include "../relay-auth.h"
|
||||
#include "../relay-buffer.h"
|
||||
#include "../relay-client.h"
|
||||
#include "../relay-config.h"
|
||||
@@ -1701,7 +1702,7 @@ relay_irc_recv (struct t_relay_client *client, const char *data)
|
||||
NULL, NULL, NULL);
|
||||
if (password)
|
||||
{
|
||||
if (strcmp (password, pos_password) == 0)
|
||||
if (relay_auth_password_equals (password, pos_password))
|
||||
{
|
||||
RELAY_IRC_DATA(client, password_ok) = 1;
|
||||
weechat_hook_signal_send ("relay_client_auth_ok",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,8 @@ extern char *relay_auth_password_hash_algo_name[];
|
||||
|
||||
extern int relay_auth_password_hash_algo_search (const char *name);
|
||||
extern char *relay_auth_generate_nonce (int size);
|
||||
extern int relay_auth_password_equals (const char *password1,
|
||||
const char *password2);
|
||||
extern int relay_auth_check_password_plain (struct t_relay_client *client,
|
||||
const char *password,
|
||||
const char *relay_password);
|
||||
|
||||
@@ -109,6 +109,31 @@ TEST(RelayAuth, GenerateNonce)
|
||||
free (nonce);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* relay_auth_password_equals
|
||||
*/
|
||||
|
||||
TEST(RelayAuth, PasswordEquals)
|
||||
{
|
||||
/* invalid arguments */
|
||||
LONGS_EQUAL(0, relay_auth_password_equals (NULL, NULL));
|
||||
LONGS_EQUAL(0, relay_auth_password_equals ("abcd", NULL));
|
||||
LONGS_EQUAL(0, relay_auth_password_equals (NULL, "abcd"));
|
||||
|
||||
/* different passwords */
|
||||
LONGS_EQUAL(0, relay_auth_password_equals ("test", "password"));
|
||||
LONGS_EQUAL(0, relay_auth_password_equals ("Password", "password"));
|
||||
LONGS_EQUAL(0, relay_auth_password_equals ("", "password"));
|
||||
LONGS_EQUAL(0, relay_auth_password_equals ("password", ""));
|
||||
|
||||
/* equal passwords */
|
||||
LONGS_EQUAL(1, relay_auth_password_equals ("", ""));
|
||||
LONGS_EQUAL(1, relay_auth_password_equals ("password", "password"));
|
||||
LONGS_EQUAL(1, relay_auth_password_equals ("a really long password with spaces",
|
||||
"a really long password with spaces"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* relay_auth_check_password_plain
|
||||
|
||||
Reference in New Issue
Block a user