mirror of
https://github.com/weechat/weechat.git
synced 2026-06-26 04:46:37 +02:00
relay: add command "handshake" in weechat relay protocol and nonce to prevent replay attacks (closes #1474)
This introduces a new command called "handshake" in the weechat relay protocol. It should be sent by the client before the "init" command, to negotiate the way to authenticate with a password. 3 new options are added: * relay.network.auth_password * relay.network.hash_iterations * relay.network.nonce_size
This commit is contained in:
@@ -19,13 +19,9 @@
|
||||
|
||||
add_library(relay MODULE
|
||||
relay.c relay.h
|
||||
relay-auth.c relay-auth.h
|
||||
relay-buffer.c relay-buffer.h
|
||||
relay-client.c relay-client.h
|
||||
irc/relay-irc.c irc/relay-irc.h
|
||||
weechat/relay-weechat.c weechat/relay-weechat.h
|
||||
weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h
|
||||
weechat/relay-weechat-nicklist.c weechat/relay-weechat-nicklist.h
|
||||
weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h
|
||||
relay-command.c relay-command.h
|
||||
relay-completion.c relay-completion.h
|
||||
relay-config.c relay-config.h
|
||||
@@ -35,6 +31,13 @@ add_library(relay MODULE
|
||||
relay-server.c relay-server.h
|
||||
relay-upgrade.c relay-upgrade.h
|
||||
relay-websocket.c relay-websocket.h
|
||||
# irc relay
|
||||
irc/relay-irc.c irc/relay-irc.h
|
||||
# weechat relay
|
||||
weechat/relay-weechat.c weechat/relay-weechat.h
|
||||
weechat/relay-weechat-msg.c weechat/relay-weechat-msg.h
|
||||
weechat/relay-weechat-nicklist.c weechat/relay-weechat-nicklist.h
|
||||
weechat/relay-weechat-protocol.c weechat/relay-weechat-protocol.h
|
||||
)
|
||||
set_target_properties(relay PROPERTIES PREFIX "")
|
||||
|
||||
|
||||
@@ -25,20 +25,12 @@ lib_LTLIBRARIES = relay.la
|
||||
|
||||
relay_la_SOURCES = relay.c \
|
||||
relay.h \
|
||||
relay-auth.c \
|
||||
relay-auth.h \
|
||||
relay-buffer.c \
|
||||
relay-buffer.h \
|
||||
relay-client.c \
|
||||
relay-client.h \
|
||||
irc/relay-irc.c \
|
||||
irc/relay-irc.h \
|
||||
weechat/relay-weechat.c \
|
||||
weechat/relay-weechat.h \
|
||||
weechat/relay-weechat-msg.c \
|
||||
weechat/relay-weechat-msg.h \
|
||||
weechat/relay-weechat-nicklist.c \
|
||||
weechat/relay-weechat-nicklist.h \
|
||||
weechat/relay-weechat-protocol.c \
|
||||
weechat/relay-weechat-protocol.h \
|
||||
relay-command.c \
|
||||
relay-command.h \
|
||||
relay-completion.c \
|
||||
@@ -56,7 +48,17 @@ relay_la_SOURCES = relay.c \
|
||||
relay-upgrade.c \
|
||||
relay-upgrade.h \
|
||||
relay-websocket.c \
|
||||
relay-websocket.h
|
||||
relay-websocket.h \
|
||||
irc/relay-irc.c \
|
||||
irc/relay-irc.h \
|
||||
weechat/relay-weechat.c \
|
||||
weechat/relay-weechat.h \
|
||||
weechat/relay-weechat-msg.c \
|
||||
weechat/relay-weechat-msg.h \
|
||||
weechat/relay-weechat-nicklist.c \
|
||||
weechat/relay-weechat-nicklist.h \
|
||||
weechat/relay-weechat-protocol.c \
|
||||
weechat/relay-weechat-protocol.h
|
||||
|
||||
relay_la_LDFLAGS = -module -no-undefined
|
||||
relay_la_LIBADD = $(RELAY_LFLAGS) $(ZLIB_LFLAGS) $(GNUTLS_LFLAGS)
|
||||
|
||||
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* relay-auth.c - relay client authentication
|
||||
*
|
||||
* Copyright (C) 2003-2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "relay.h"
|
||||
#include "relay-auth.h"
|
||||
#include "relay-client.h"
|
||||
#include "relay-config.h"
|
||||
|
||||
|
||||
/*
|
||||
* this list is sorted from the least secure to the safest algorithm:
|
||||
* "plain" is plain text password, the other values are hash algorithms;
|
||||
* during negotiation with the client, the highest value in this list matching
|
||||
* the client supported values is used
|
||||
*/
|
||||
char *relay_auth_password_name[] =
|
||||
{ "plain", "sha256", "sha512", "pbkdf2+sha256", "pbkdf2+sha512" };
|
||||
|
||||
|
||||
/*
|
||||
* Searches for a password authentication.
|
||||
*
|
||||
* Returns index in enum t_relay_auth_password,
|
||||
* -1 if password authentication is not found.
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_password_search (const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RELAY_NUM_PASSWORD_AUTHS; i++)
|
||||
{
|
||||
if (strcmp (relay_auth_password_name[i], name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
/* authentication password type found */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generates a nonce: a buffer of unpredictable bytes
|
||||
*
|
||||
* Note: result must be freed after use.
|
||||
*/
|
||||
|
||||
char *
|
||||
relay_auth_generate_nonce ()
|
||||
{
|
||||
int size;
|
||||
char *nonce, *nonce_hexa;
|
||||
|
||||
size = weechat_config_integer (relay_config_network_nonce_size);
|
||||
|
||||
nonce = malloc (size);
|
||||
if (!nonce)
|
||||
return NULL;
|
||||
|
||||
nonce_hexa = malloc ((size * 2) + 1);
|
||||
if (!nonce_hexa)
|
||||
{
|
||||
free (nonce);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gcry_create_nonce ((unsigned char *)nonce, size);
|
||||
weechat_string_base_encode (16, nonce, size, nonce_hexa);
|
||||
|
||||
free (nonce);
|
||||
|
||||
return nonce_hexa;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if password received as plain text is valid.
|
||||
*
|
||||
* Returns:
|
||||
* 1: password is valid
|
||||
* 0: password is not valid
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_check_password_plain (const char *password,
|
||||
const char *relay_password)
|
||||
{
|
||||
if (!password || !relay_password)
|
||||
return 0;
|
||||
|
||||
return (strcmp (password, relay_password) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticates with password (plain text).
|
||||
*
|
||||
* Returns:
|
||||
* 1: authentication OK
|
||||
* 0: authentication failed
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_password (struct t_relay_client *client,
|
||||
const char *password, const char *relay_password)
|
||||
{
|
||||
if (client->auth_password != RELAY_AUTH_PASSWORD_PLAIN)
|
||||
return 0;
|
||||
|
||||
return relay_auth_check_password_plain (password, relay_password);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses SHA256 or SHA512 parameters from string with format:
|
||||
*
|
||||
* salt:hash
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* salt is the salt in hexadecimal
|
||||
* hash is the hashed password with the parameters above, in hexadecimal
|
||||
*/
|
||||
|
||||
void
|
||||
relay_auth_parse_sha (const char *parameters,
|
||||
char **salt_hexa, char **salt, int *salt_size,
|
||||
char **hash)
|
||||
{
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
*salt_hexa = NULL;
|
||||
*salt = NULL;
|
||||
*salt_size = 0;
|
||||
*hash = NULL;
|
||||
|
||||
if (!parameters)
|
||||
return;
|
||||
|
||||
argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc);
|
||||
|
||||
if (!argv || (argc < 2))
|
||||
{
|
||||
/* not enough parameters */
|
||||
if (argv)
|
||||
weechat_string_free_split (argv);
|
||||
return;
|
||||
}
|
||||
|
||||
/* parameter 1: salt */
|
||||
*salt = malloc (strlen (argv[0]) + 1);
|
||||
if (*salt)
|
||||
{
|
||||
*salt_size = weechat_string_base_decode (16, argv[0], *salt);
|
||||
if (*salt_size > 0)
|
||||
*salt_hexa = strdup (argv[0]);
|
||||
else
|
||||
{
|
||||
free (*salt);
|
||||
*salt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* parameter 2: the SHA256 or SHA512 hash */
|
||||
*hash = strdup (argv[1]);
|
||||
|
||||
weechat_string_free_split (argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses PBKDF2 parameters from string with format:
|
||||
*
|
||||
* salt:iterations:hash
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* salt is the salt in hexadecimal
|
||||
* iterations it the number of iterations (≥ 1)
|
||||
* hash is the hashed password with the parameters above, in hexadecimal
|
||||
*/
|
||||
|
||||
void
|
||||
relay_auth_parse_pbkdf2 (const char *parameters,
|
||||
char **salt_hexa, char **salt, int *salt_size,
|
||||
int *iterations, char **hash)
|
||||
{
|
||||
char **argv, *error;
|
||||
int argc;
|
||||
|
||||
*salt_hexa = NULL;
|
||||
*salt = NULL;
|
||||
*salt_size = 0;
|
||||
*iterations = 0;
|
||||
*hash = NULL;
|
||||
|
||||
if (!parameters)
|
||||
return;
|
||||
|
||||
argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc);
|
||||
|
||||
if (!argv || (argc < 3))
|
||||
{
|
||||
/* not enough parameters */
|
||||
if (argv)
|
||||
weechat_string_free_split (argv);
|
||||
return;
|
||||
}
|
||||
|
||||
/* parameter 1: salt */
|
||||
*salt = malloc (strlen (argv[0]) + 1);
|
||||
if (*salt)
|
||||
{
|
||||
*salt_size = weechat_string_base_decode (16, argv[0], *salt);
|
||||
if (*salt_size > 0)
|
||||
*salt_hexa = strdup (argv[0]);
|
||||
else
|
||||
{
|
||||
free (*salt);
|
||||
*salt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* parameter 2: iterations */
|
||||
*iterations = (int)strtol (argv[1], &error, 10);
|
||||
if (!error || error[0])
|
||||
*iterations = 0;
|
||||
|
||||
/* parameter 3: the PBKDF2 hash */
|
||||
*hash = strdup (argv[2]);
|
||||
|
||||
weechat_string_free_split (argv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the salt received from the client is valid.
|
||||
*
|
||||
* It is valid if both conditions are true:
|
||||
* 1. the salt is longer than the server nonce, so it means it includes a
|
||||
* client nonce
|
||||
* 2. the salt begins with the server nonce (client->nonce)
|
||||
*
|
||||
* Returns:
|
||||
* 1: salt is valid
|
||||
* 0: salt is not valid
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_check_salt (struct t_relay_client *client, const char *salt_hexa)
|
||||
{
|
||||
return (salt_hexa
|
||||
&& client->nonce
|
||||
&& (strlen (salt_hexa) > strlen (client->nonce))
|
||||
&& (weechat_strncasecmp (salt_hexa, client->nonce,
|
||||
strlen (client->nonce)) == 0)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if password received as SHA256/SHA512 hash is valid.
|
||||
*
|
||||
* Returns:
|
||||
* 1: password is valid
|
||||
* 0: password is not valid
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_check_hash_sha (const char *hash_algo,
|
||||
const char *salt,
|
||||
int salt_size,
|
||||
const char *hash_sha,
|
||||
const char *relay_password)
|
||||
{
|
||||
char *salt_password, hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1];
|
||||
int rc, length, hash_size;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (salt && (salt_size > 0) && hash_sha)
|
||||
{
|
||||
length = salt_size + strlen (relay_password);
|
||||
salt_password = malloc (length);
|
||||
if (salt_password)
|
||||
{
|
||||
memcpy (salt_password, salt, salt_size);
|
||||
memcpy (salt_password + salt_size, relay_password,
|
||||
strlen (relay_password));
|
||||
if (weechat_crypto_hash (salt_password, length,
|
||||
hash_algo,
|
||||
hash, &hash_size))
|
||||
{
|
||||
weechat_string_base_encode (16, hash, hash_size,
|
||||
hash_hexa);
|
||||
if (weechat_strcasecmp (hash_hexa, hash_sha) == 0)
|
||||
rc = 1;
|
||||
}
|
||||
free (salt_password);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if password received as PBKDF2 hash is valid.
|
||||
*
|
||||
* Returns:
|
||||
* 1: password is valid
|
||||
* 0: password is not valid
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo,
|
||||
const char *salt,
|
||||
int salt_size,
|
||||
int iterations,
|
||||
const char *hash_pbkdf2,
|
||||
const char *relay_password)
|
||||
{
|
||||
char hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1];
|
||||
int rc, hash_size;
|
||||
|
||||
rc = 0;
|
||||
|
||||
if (hash_pbkdf2_algo && salt && (salt_size > 0) && hash_pbkdf2)
|
||||
{
|
||||
if (weechat_crypto_hash_pbkdf2 (relay_password,
|
||||
strlen (relay_password),
|
||||
hash_pbkdf2_algo,
|
||||
salt, salt_size,
|
||||
iterations,
|
||||
hash, &hash_size))
|
||||
{
|
||||
weechat_string_base_encode (16, hash, hash_size, hash_hexa);
|
||||
if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0)
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticates with password hash.
|
||||
*
|
||||
* Returns:
|
||||
* 1: authentication OK
|
||||
* 0: authentication failed
|
||||
*/
|
||||
|
||||
int
|
||||
relay_auth_password_hash (struct t_relay_client *client,
|
||||
const char *hashed_password, const char *relay_password)
|
||||
{
|
||||
const char *pos_hash;
|
||||
char *str_hash_algo;
|
||||
char *hash_pbkdf2_algo, *salt_hexa, *salt, *hash_sha, *hash_pbkdf2;
|
||||
int rc, auth_password, salt_size, iterations;
|
||||
|
||||
rc = 0;
|
||||
|
||||
str_hash_algo = NULL;
|
||||
|
||||
/* no authentication supported at all? */
|
||||
if (client->auth_password < 0)
|
||||
goto end;
|
||||
|
||||
if (!hashed_password || !relay_password)
|
||||
goto end;
|
||||
|
||||
pos_hash = strchr (hashed_password, ':');
|
||||
if (!pos_hash)
|
||||
goto end;
|
||||
|
||||
str_hash_algo = weechat_strndup (hashed_password,
|
||||
pos_hash - hashed_password);
|
||||
if (!str_hash_algo)
|
||||
goto end;
|
||||
|
||||
pos_hash++;
|
||||
|
||||
auth_password = relay_auth_password_search (str_hash_algo);
|
||||
|
||||
if (auth_password != client->auth_password)
|
||||
goto end;
|
||||
|
||||
switch (auth_password)
|
||||
{
|
||||
case RELAY_AUTH_PASSWORD_SHA256:
|
||||
case RELAY_AUTH_PASSWORD_SHA512:
|
||||
relay_auth_parse_sha (pos_hash, &salt_hexa, &salt, &salt_size,
|
||||
&hash_sha);
|
||||
if (relay_auth_check_salt (client, salt_hexa)
|
||||
&& relay_auth_check_hash_sha (str_hash_algo, salt, salt_size,
|
||||
hash_sha, relay_password))
|
||||
{
|
||||
rc = 1;
|
||||
}
|
||||
if (salt_hexa)
|
||||
free (salt_hexa);
|
||||
if (salt)
|
||||
free (salt);
|
||||
if (hash_sha)
|
||||
free (hash_sha);
|
||||
break;
|
||||
case RELAY_AUTH_PASSWORD_PBKDF2_SHA256:
|
||||
case RELAY_AUTH_PASSWORD_PBKDF2_SHA512:
|
||||
hash_pbkdf2_algo = strdup (str_hash_algo + 7);
|
||||
relay_auth_parse_pbkdf2 (pos_hash, &salt_hexa, &salt, &salt_size,
|
||||
&iterations, &hash_pbkdf2);
|
||||
if ((iterations == client->hash_iterations)
|
||||
&& relay_auth_check_salt (client, salt_hexa)
|
||||
&& relay_auth_check_hash_pbkdf2 (hash_pbkdf2_algo, salt,
|
||||
salt_size, iterations,
|
||||
hash_pbkdf2, relay_password))
|
||||
{
|
||||
rc = 1;
|
||||
}
|
||||
if (hash_pbkdf2_algo)
|
||||
free (hash_pbkdf2_algo);
|
||||
if (salt_hexa)
|
||||
free (salt_hexa);
|
||||
if (salt)
|
||||
free (salt);
|
||||
if (hash_pbkdf2)
|
||||
free (hash_pbkdf2);
|
||||
break;
|
||||
case RELAY_NUM_PASSWORD_AUTHS:
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
if (str_hash_algo)
|
||||
free (str_hash_algo);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2003-2020 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* WeeChat is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with WeeChat. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WEECHAT_PLUGIN_RELAY_AUTH_H
|
||||
#define WEECHAT_PLUGIN_RELAY_AUTH_H
|
||||
|
||||
struct t_relay_client;
|
||||
|
||||
enum t_relay_auth_password
|
||||
{
|
||||
RELAY_AUTH_PASSWORD_PLAIN = 0,
|
||||
RELAY_AUTH_PASSWORD_SHA256,
|
||||
RELAY_AUTH_PASSWORD_SHA512,
|
||||
RELAY_AUTH_PASSWORD_PBKDF2_SHA256,
|
||||
RELAY_AUTH_PASSWORD_PBKDF2_SHA512,
|
||||
/* number of password auths */
|
||||
RELAY_NUM_PASSWORD_AUTHS,
|
||||
};
|
||||
|
||||
extern char *relay_auth_password_name[];
|
||||
|
||||
extern int relay_auth_password_search (const char *name);
|
||||
extern char *relay_auth_generate_nonce ();
|
||||
extern int relay_auth_check_password_plain (const char *password,
|
||||
const char *relay_password);
|
||||
extern int relay_auth_password (struct t_relay_client *client,
|
||||
const char *password,
|
||||
const char *relay_password);
|
||||
extern void relay_auth_parse_sha (const char *parameters,
|
||||
char **salt_hexa,
|
||||
char **salt,
|
||||
int *salt_size,
|
||||
char **hash);
|
||||
extern void relay_auth_parse_pbkdf2 (const char *parameters,
|
||||
char **salt_hexa,
|
||||
char **salt,
|
||||
int *salt_size,
|
||||
int *iterations,
|
||||
char **hash);
|
||||
extern int relay_auth_check_salt (struct t_relay_client *client,
|
||||
const char *salt_hexa);
|
||||
extern int relay_auth_check_hash_sha (const char *hash_algo,
|
||||
const char *salt,
|
||||
int salt_size,
|
||||
const char *hash_sha,
|
||||
const char *relay_password);
|
||||
extern int relay_auth_check_hash_pbkdf2 (const char *hash_pbkdf2_algo,
|
||||
const char *salt,
|
||||
int salt_size,
|
||||
int iterations,
|
||||
const char *hash_pbkdf2,
|
||||
const char *relay_password);
|
||||
extern int relay_auth_password_hash (struct t_relay_client *client,
|
||||
const char *hashed_password,
|
||||
const char *relay_password);
|
||||
|
||||
#endif /* WEECHAT_PLUGIN_RELAY_AUTH_H */
|
||||
@@ -36,14 +36,15 @@
|
||||
#include "../weechat-plugin.h"
|
||||
#include "relay.h"
|
||||
#include "relay-client.h"
|
||||
#include "irc/relay-irc.h"
|
||||
#include "weechat/relay-weechat.h"
|
||||
#include "relay-auth.h"
|
||||
#include "relay-config.h"
|
||||
#include "relay-buffer.h"
|
||||
#include "relay-network.h"
|
||||
#include "relay-raw.h"
|
||||
#include "relay-server.h"
|
||||
#include "relay-websocket.h"
|
||||
#include "irc/relay-irc.h"
|
||||
#include "weechat/relay-weechat.h"
|
||||
|
||||
|
||||
char *relay_client_status_string[] = /* status strings for display */
|
||||
@@ -1269,6 +1270,7 @@ struct t_relay_client *
|
||||
relay_client_new (int sock, const char *address, struct t_relay_server *server)
|
||||
{
|
||||
struct t_relay_client *new_client;
|
||||
int plain_text_password;
|
||||
#ifdef HAVE_GNUTLS
|
||||
int bits;
|
||||
struct t_config_option *ptr_option;
|
||||
@@ -1295,6 +1297,14 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server)
|
||||
new_client->protocol = server->protocol;
|
||||
new_client->protocol_string = (server->protocol_string) ? strdup (server->protocol_string) : NULL;
|
||||
new_client->protocol_args = (server->protocol_args) ? strdup (server->protocol_args) : NULL;
|
||||
plain_text_password = weechat_string_match_list (
|
||||
relay_auth_password_name[0],
|
||||
(const char **)relay_config_network_auth_password_list,
|
||||
1);
|
||||
new_client->auth_password = (plain_text_password) ? 0 : -1;
|
||||
new_client->hash_iterations = weechat_config_integer (
|
||||
relay_config_network_hash_iterations);
|
||||
new_client->nonce = relay_auth_generate_nonce ();
|
||||
new_client->listen_start_time = server->start_time;
|
||||
new_client->start_time = time (NULL);
|
||||
new_client->end_time = 0;
|
||||
@@ -1496,6 +1506,22 @@ relay_client_new_with_infolist (struct t_infolist *infolist)
|
||||
new_client->protocol_string = (str) ? strdup (str) : NULL;
|
||||
str = weechat_infolist_string (infolist, "protocol_args");
|
||||
new_client->protocol_args = (str) ? strdup (str) : NULL;
|
||||
/* "auth_password" is new in WeeChat 2.9 */
|
||||
if (weechat_infolist_search_var (infolist, "auth_password"))
|
||||
new_client->auth_password = weechat_infolist_integer (infolist, "auth_password");
|
||||
else
|
||||
new_client->auth_password = RELAY_AUTH_PASSWORD_PLAIN;
|
||||
/* "hash_iterations" is new in WeeChat 2.9 */
|
||||
if (weechat_infolist_search_var (infolist, "hash_iterations"))
|
||||
new_client->hash_iterations = weechat_infolist_integer (infolist, "hash_iterations");
|
||||
else
|
||||
new_client->hash_iterations = weechat_config_integer (
|
||||
relay_config_network_hash_iterations);
|
||||
/* "nonce" is new in WeeChat 2.9 */
|
||||
if (weechat_infolist_search_var (infolist, "nonce"))
|
||||
new_client->nonce = strdup (weechat_infolist_string (infolist, "nonce"));
|
||||
else
|
||||
new_client->nonce = relay_auth_generate_nonce ();
|
||||
new_client->listen_start_time = weechat_infolist_time (infolist, "listen_start_time");
|
||||
new_client->start_time = weechat_infolist_time (infolist, "start_time");
|
||||
new_client->end_time = weechat_infolist_time (infolist, "end_time");
|
||||
@@ -1693,6 +1719,8 @@ relay_client_free (struct t_relay_client *client)
|
||||
free (client->protocol_string);
|
||||
if (client->protocol_args)
|
||||
free (client->protocol_args);
|
||||
if (client->nonce)
|
||||
free (client->nonce);
|
||||
#ifdef HAVE_GNUTLS
|
||||
if (client->hook_timer_handshake)
|
||||
weechat_unhook (client->hook_timer_handshake);
|
||||
@@ -1829,6 +1857,12 @@ relay_client_add_to_infolist (struct t_infolist *infolist,
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_string (ptr_item, "protocol_args", client->protocol_args))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "auth_password", client->auth_password))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_integer (ptr_item, "hash_iterations", client->hash_iterations))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_string (ptr_item, "nonce", client->nonce))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_time (ptr_item, "listen_start_time", client->listen_start_time))
|
||||
return 0;
|
||||
if (!weechat_infolist_new_var_time (ptr_item, "start_time", client->start_time))
|
||||
@@ -1905,6 +1939,12 @@ relay_client_print_log ()
|
||||
relay_protocol_string[ptr_client->protocol]);
|
||||
weechat_log_printf (" protocol_string . . . : '%s'", ptr_client->protocol_string);
|
||||
weechat_log_printf (" protocol_args . . . . : '%s'", ptr_client->protocol_args);
|
||||
weechat_log_printf (" auth_password . . . . : %d (%s)",
|
||||
ptr_client->auth_password,
|
||||
(ptr_client->auth_password >= 0) ?
|
||||
relay_auth_password_name[ptr_client->auth_password] : "");
|
||||
weechat_log_printf (" hash_iterations . . . : %d", ptr_client->hash_iterations);
|
||||
weechat_log_printf (" nonce . . . . . . . . : '%s'", ptr_client->nonce);
|
||||
weechat_log_printf (" listen_start_time . . : %lld", (long long)ptr_client->listen_start_time);
|
||||
weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_client->start_time);
|
||||
weechat_log_printf (" end_time. . . . . . . : %lld", (long long)ptr_client->end_time);
|
||||
|
||||
@@ -106,6 +106,9 @@ struct t_relay_client
|
||||
char *protocol_string; /* example: "ipv6.ssl.irc.freenode" */
|
||||
char *protocol_args; /* arguments used for protocol */
|
||||
/* example: server for irc protocol */
|
||||
int auth_password; /* password auth (negotiated/client) */
|
||||
int hash_iterations; /* hash iterations */
|
||||
char *nonce; /* nonce used in salt of hashed pwd */
|
||||
time_t listen_start_time; /* when listening started */
|
||||
time_t start_time; /* time of client connection */
|
||||
time_t end_time; /* time of client disconnection */
|
||||
@@ -124,6 +127,7 @@ struct t_relay_client
|
||||
};
|
||||
|
||||
extern char *relay_client_status_string[];
|
||||
extern char *relay_client_status_name[];
|
||||
extern char *relay_client_msg_type_string[];
|
||||
extern struct t_relay_client *relay_clients;
|
||||
extern struct t_relay_client *last_relay_client;
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
#include "../weechat-plugin.h"
|
||||
#include "relay.h"
|
||||
#include "relay-config.h"
|
||||
#include "irc/relay-irc.h"
|
||||
#include "relay-client.h"
|
||||
#include "relay-buffer.h"
|
||||
#include "relay-network.h"
|
||||
#include "relay-server.h"
|
||||
#include "irc/relay-irc.h"
|
||||
|
||||
|
||||
struct t_config_file *relay_config_file = NULL;
|
||||
@@ -60,12 +60,15 @@ struct t_config_option *relay_config_color_text_selected;
|
||||
|
||||
struct t_config_option *relay_config_network_allow_empty_password;
|
||||
struct t_config_option *relay_config_network_allowed_ips;
|
||||
struct t_config_option *relay_config_network_auth_password;
|
||||
struct t_config_option *relay_config_network_auth_timeout;
|
||||
struct t_config_option *relay_config_network_bind_address;
|
||||
struct t_config_option *relay_config_network_clients_purge_delay;
|
||||
struct t_config_option *relay_config_network_compression_level;
|
||||
struct t_config_option *relay_config_network_hash_iterations;
|
||||
struct t_config_option *relay_config_network_ipv6;
|
||||
struct t_config_option *relay_config_network_max_clients;
|
||||
struct t_config_option *relay_config_network_nonce_size;
|
||||
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;
|
||||
@@ -91,6 +94,7 @@ struct t_config_option *relay_config_weechat_commands;
|
||||
regex_t *relay_config_regex_allowed_ips = NULL;
|
||||
regex_t *relay_config_regex_websocket_allowed_origins = NULL;
|
||||
struct t_hashtable *relay_config_hashtable_irc_backlog_tags = NULL;
|
||||
char **relay_config_network_auth_password_list = NULL;
|
||||
|
||||
|
||||
/*
|
||||
@@ -149,6 +153,36 @@ relay_config_change_network_allowed_ips (const void *pointer, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for changes on option "relay.network.auth_password".
|
||||
*/
|
||||
|
||||
void
|
||||
relay_config_change_network_auth_password (const void *pointer, void *data,
|
||||
struct t_config_option *option)
|
||||
{
|
||||
/* make C compiler happy */
|
||||
(void) pointer;
|
||||
(void) data;
|
||||
(void) option;
|
||||
|
||||
if (relay_config_network_auth_password_list)
|
||||
{
|
||||
weechat_string_free_split (relay_config_network_auth_password_list);
|
||||
relay_config_network_auth_password_list = NULL;
|
||||
}
|
||||
|
||||
relay_config_network_auth_password_list = weechat_string_split (
|
||||
weechat_config_string (relay_config_network_auth_password),
|
||||
",",
|
||||
NULL,
|
||||
WEECHAT_STRING_SPLIT_STRIP_LEFT
|
||||
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
|
||||
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
|
||||
0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for changes on option "relay.network.bind_address".
|
||||
*/
|
||||
@@ -1032,6 +1066,20 @@ relay_config_init ()
|
||||
NULL, NULL, NULL,
|
||||
&relay_config_change_network_allowed_ips, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
relay_config_network_auth_password = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"auth_password", "string",
|
||||
N_("comma separated list of hash algorithms used for password "
|
||||
"authentication in weechat protocol, among these values: \"plain\" "
|
||||
"(password in plain text, not hashed), \"sha256\", \"sha512\", "
|
||||
"\"pbkdf2+sha256\", \"pbkdf2+sha512\"), \"*\" means all algorithms, "
|
||||
"a name beginning with \"!\" is a negative value to prevent an "
|
||||
"algorithm from being used, wildcard \"*\" is allowed in names "
|
||||
"(examples: \"*\", \"pbkdf2*\", \"*,!plain\")"),
|
||||
NULL, 0, 0, "*", NULL, 0,
|
||||
NULL, NULL, NULL,
|
||||
&relay_config_change_network_auth_password, NULL, NULL,
|
||||
NULL, NULL, NULL);
|
||||
relay_config_network_auth_timeout = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"auth_timeout", "integer",
|
||||
@@ -1066,6 +1114,16 @@ relay_config_init ()
|
||||
"compression)"),
|
||||
NULL, 0, 9, "6", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
relay_config_network_hash_iterations = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"hash_iterations", "integer",
|
||||
N_("number of iterations asked to the client in weechat protocol "
|
||||
"when a hashed password with algorithm PBKDF2 is used for "
|
||||
"authentication; more iterations is better in term of security but "
|
||||
"is slower to compute; this number should not be too high if your "
|
||||
"CPU is slow"),
|
||||
NULL, 1, 1000000, "100000", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
relay_config_network_ipv6 = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"ipv6", "boolean",
|
||||
@@ -1082,6 +1140,15 @@ relay_config_init ()
|
||||
N_("maximum number of clients connecting to a port (0 = no limit)"),
|
||||
NULL, 0, INT_MAX, "5", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
relay_config_network_nonce_size = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"nonce_size", "integer",
|
||||
N_("size of nonce (in bytes), generated when a client connects; "
|
||||
"the client must use this nonce, concatenated to the client nonce "
|
||||
"and the password when hashing the password in the \"init\" "
|
||||
"command of the weechat protocol"),
|
||||
NULL, 8, 128, "16", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
relay_config_network_password = weechat_config_new_option (
|
||||
relay_config_file, ptr_section,
|
||||
"password", "string",
|
||||
@@ -1294,6 +1361,7 @@ relay_config_read ()
|
||||
if (rc == WEECHAT_CONFIG_READ_OK)
|
||||
{
|
||||
relay_config_change_network_allowed_ips (NULL, NULL, NULL);
|
||||
relay_config_change_network_auth_password (NULL, NULL, NULL);
|
||||
relay_config_change_irc_backlog_tags (NULL, NULL, NULL);
|
||||
}
|
||||
return rc;
|
||||
@@ -1337,4 +1405,10 @@ relay_config_free ()
|
||||
weechat_hashtable_free (relay_config_hashtable_irc_backlog_tags);
|
||||
relay_config_hashtable_irc_backlog_tags = NULL;
|
||||
}
|
||||
|
||||
if (relay_config_network_auth_password_list)
|
||||
{
|
||||
weechat_string_free_split (relay_config_network_auth_password_list);
|
||||
relay_config_network_auth_password_list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,15 @@ extern struct t_config_option *relay_config_color_text_selected;
|
||||
|
||||
extern struct t_config_option *relay_config_network_allow_empty_password;
|
||||
extern struct t_config_option *relay_config_network_allowed_ips;
|
||||
extern struct t_config_option *relay_config_network_auth_password;
|
||||
extern struct t_config_option *relay_config_network_auth_timeout;
|
||||
extern struct t_config_option *relay_config_network_bind_address;
|
||||
extern struct t_config_option *relay_config_network_clients_purge_delay;
|
||||
extern struct t_config_option *relay_config_network_compression_level;
|
||||
extern struct t_config_option *relay_config_network_hash_iterations;
|
||||
extern struct t_config_option *relay_config_network_ipv6;
|
||||
extern struct t_config_option *relay_config_network_max_clients;
|
||||
extern struct t_config_option *relay_config_network_nonce_size;
|
||||
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;
|
||||
@@ -64,6 +67,7 @@ extern struct t_config_option *relay_config_weechat_commands;
|
||||
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 char **relay_config_network_auth_password_list;
|
||||
|
||||
extern int relay_config_check_network_totp_secret (const void *pointer,
|
||||
void *data,
|
||||
|
||||
@@ -70,6 +70,8 @@ extern void relay_weechat_msg_add_pointer (struct t_relay_weechat_msg *msg,
|
||||
void *pointer);
|
||||
extern void relay_weechat_msg_add_time (struct t_relay_weechat_msg *msg,
|
||||
time_t time);
|
||||
extern void relay_weechat_msg_add_hashtable (struct t_relay_weechat_msg *msg,
|
||||
struct t_hashtable *hashtable);
|
||||
extern int relay_weechat_msg_add_hdata (struct t_relay_weechat_msg *msg,
|
||||
const char *path, const char *keys);
|
||||
extern void relay_weechat_msg_add_infolist (struct t_relay_weechat_msg *msg,
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "relay-weechat-nicklist.h"
|
||||
#include "../relay-buffer.h"
|
||||
#include "../relay-client.h"
|
||||
#include "../relay-auth.h"
|
||||
#include "../relay-config.h"
|
||||
#include "../relay-raw.h"
|
||||
|
||||
@@ -159,148 +160,151 @@ relay_weechat_protocol_is_sync (struct t_relay_client *ptr_client,
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses PBKDF2 parameters from string with format:
|
||||
*
|
||||
* algorithm:salt:iterations:hash
|
||||
*
|
||||
* where:
|
||||
*
|
||||
* algorithm is "sha256" or "sha512"
|
||||
* salt is the salt in hexadecimal
|
||||
* iterations it the number of iterations (≥ 1)
|
||||
* hash is the hashed password with the parameters above, in hexadecimal
|
||||
* Replies to a client handshake command.
|
||||
*/
|
||||
|
||||
void
|
||||
relay_weechat_protocol_parse_pbkdf2 (const char *parameters,
|
||||
char **algorithm,
|
||||
char **salt,
|
||||
int *salt_size,
|
||||
int *iterations,
|
||||
char **hash_pbkdf2)
|
||||
relay_weechat_protocol_handshake_reply (struct t_relay_client *client,
|
||||
const char *command)
|
||||
{
|
||||
char **argv, *error;
|
||||
int argc;
|
||||
struct t_relay_weechat_msg *msg;
|
||||
struct t_hashtable *hashtable;
|
||||
char *totp_secret, string[64];
|
||||
|
||||
*algorithm = NULL;
|
||||
*salt = NULL;
|
||||
*salt_size = 0;
|
||||
*iterations = 0;
|
||||
*hash_pbkdf2 = NULL;
|
||||
totp_secret = weechat_string_eval_expression (
|
||||
weechat_config_string (relay_config_network_totp_secret),
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!parameters)
|
||||
return;
|
||||
|
||||
argv = weechat_string_split (parameters, ":", NULL, 0, 0, &argc);
|
||||
|
||||
if (!argv || (argc < 4))
|
||||
hashtable = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
NULL, NULL);
|
||||
if (hashtable)
|
||||
{
|
||||
/* not enough parameters */
|
||||
if (argv)
|
||||
weechat_string_free_split (argv);
|
||||
return;
|
||||
weechat_hashtable_set (
|
||||
hashtable,
|
||||
"auth_password",
|
||||
(client->auth_password >= 0) ?
|
||||
relay_auth_password_name[client->auth_password] : "");
|
||||
snprintf (string, sizeof (string), "%d", client->hash_iterations);
|
||||
weechat_hashtable_set (
|
||||
hashtable,
|
||||
"hash_iterations",
|
||||
string);
|
||||
weechat_hashtable_set (
|
||||
hashtable,
|
||||
"nonce",
|
||||
client->nonce);
|
||||
weechat_hashtable_set (
|
||||
hashtable,
|
||||
"totp",
|
||||
(totp_secret && totp_secret[0]) ? "on" : "off");
|
||||
|
||||
msg = relay_weechat_msg_new (command);
|
||||
if (msg)
|
||||
{
|
||||
relay_weechat_msg_add_type (msg, RELAY_WEECHAT_MSG_OBJ_HASHTABLE);
|
||||
relay_weechat_msg_add_hashtable (msg, hashtable);
|
||||
|
||||
/* send message */
|
||||
relay_weechat_msg_send (client, msg);
|
||||
relay_weechat_msg_free (msg);
|
||||
}
|
||||
|
||||
weechat_hashtable_free (hashtable);
|
||||
}
|
||||
|
||||
/* parameter 1: algorithm */
|
||||
if ((strcmp (argv[0], "sha256") == 0)
|
||||
|| (strcmp (argv[0], "sha512") == 0))
|
||||
{
|
||||
*algorithm = strdup (argv[0]);
|
||||
}
|
||||
|
||||
/* parameter 2: salt */
|
||||
*salt = malloc (strlen (argv[1]) + 1);
|
||||
if (*salt)
|
||||
*salt_size = weechat_string_base_decode (16, argv[1], *salt);
|
||||
|
||||
/* parameter 3: iterations */
|
||||
*iterations = (int)strtol (argv[2], &error, 10);
|
||||
if (!error || error[0])
|
||||
*iterations = 0;
|
||||
|
||||
/* parameter 4: the PBKDF2 hash */
|
||||
*hash_pbkdf2 = strdup (argv[3]);
|
||||
|
||||
weechat_string_free_split (argv);
|
||||
if (totp_secret)
|
||||
free (totp_secret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checks if hashed password received is valid.
|
||||
*
|
||||
* Format of hash_password is: algorithm:hash
|
||||
*
|
||||
* Returns 1 if the hashed password is valid, otherwise 0.
|
||||
* Callback for command "handshake" (from client).
|
||||
*/
|
||||
|
||||
int
|
||||
relay_weechat_protocol_check_hash (const char *hashed_password,
|
||||
const char *password)
|
||||
RELAY_WEECHAT_PROTOCOL_CALLBACK(handshake)
|
||||
{
|
||||
const char *pos_hash;
|
||||
char *hash_algo, hash[512 / 8], hash_hexa[((512 / 8) * 2) + 1];
|
||||
char *hash_pbkdf2_algo, *salt, *hash_pbkdf2;
|
||||
int rc, hash_size, salt_size, iterations;
|
||||
char **options, **auths, *pos;
|
||||
int i, j, index_auth, auth_found, auth_allowed, compression;
|
||||
int password_received, plain_text_password;
|
||||
|
||||
rc = 0;
|
||||
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
|
||||
|
||||
if (!hashed_password || !password)
|
||||
goto end;
|
||||
if (client->status != RELAY_STATUS_WAITING_AUTH)
|
||||
return WEECHAT_RC_OK;
|
||||
|
||||
pos_hash = strchr (hashed_password, ':');
|
||||
if (!pos_hash)
|
||||
goto end;
|
||||
auth_found = -1;
|
||||
password_received = 0;
|
||||
|
||||
hash_algo = weechat_strndup (hashed_password, pos_hash - hashed_password);
|
||||
if (!hash_algo)
|
||||
goto end;
|
||||
|
||||
pos_hash++;
|
||||
|
||||
if ((strcmp (hash_algo, "sha256") == 0)
|
||||
|| (strcmp (hash_algo, "sha512") == 0))
|
||||
options = (argc > 0) ?
|
||||
weechat_string_split_command (argv_eol[0], ',') : NULL;
|
||||
if (options)
|
||||
{
|
||||
if (weechat_crypto_hash (password, strlen (password), hash_algo,
|
||||
hash, &hash_size))
|
||||
for (i = 0; options[i]; i++)
|
||||
{
|
||||
weechat_string_base_encode (16, hash, hash_size, hash_hexa);
|
||||
if (weechat_strcasecmp (hash_hexa, pos_hash) == 0)
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
else if (strcmp (hash_algo, "pbkdf2") == 0)
|
||||
{
|
||||
relay_weechat_protocol_parse_pbkdf2 (pos_hash,
|
||||
&hash_pbkdf2_algo,
|
||||
&salt,
|
||||
&salt_size,
|
||||
&iterations,
|
||||
&hash_pbkdf2);
|
||||
if (hash_pbkdf2_algo && salt && (salt_size > 0) && (iterations > 0)
|
||||
&& hash_pbkdf2)
|
||||
{
|
||||
if (weechat_crypto_hash_pbkdf2 (password, strlen (password),
|
||||
hash_pbkdf2_algo,
|
||||
salt, salt_size,
|
||||
iterations,
|
||||
hash, &hash_size))
|
||||
pos = strchr (options[i], '=');
|
||||
if (pos)
|
||||
{
|
||||
weechat_string_base_encode (16, hash, hash_size, hash_hexa);
|
||||
if (weechat_strcasecmp (hash_hexa, hash_pbkdf2) == 0)
|
||||
rc = 1;
|
||||
pos[0] = '\0';
|
||||
pos++;
|
||||
if (strcmp (options[i], "password") == 0)
|
||||
{
|
||||
password_received = 1;
|
||||
auths = weechat_string_split (
|
||||
pos,
|
||||
":",
|
||||
NULL,
|
||||
WEECHAT_STRING_SPLIT_STRIP_LEFT
|
||||
| WEECHAT_STRING_SPLIT_STRIP_RIGHT
|
||||
| WEECHAT_STRING_SPLIT_COLLAPSE_SEPS,
|
||||
0,
|
||||
NULL);
|
||||
if (auths)
|
||||
{
|
||||
for (j = 0; auths[j]; j++)
|
||||
{
|
||||
index_auth = relay_auth_password_search (
|
||||
auths[j]);
|
||||
if ((index_auth >= 0) && (index_auth > auth_found))
|
||||
{
|
||||
auth_allowed = weechat_string_match_list (
|
||||
relay_auth_password_name[index_auth],
|
||||
(const char **)relay_config_network_auth_password_list,
|
||||
1);
|
||||
if (auth_allowed)
|
||||
auth_found = index_auth;
|
||||
}
|
||||
}
|
||||
weechat_string_free_split (auths);
|
||||
}
|
||||
}
|
||||
else if (strcmp (options[i], "compression") == 0)
|
||||
{
|
||||
compression = relay_weechat_compression_search (pos);
|
||||
if (compression >= 0)
|
||||
RELAY_WEECHAT_DATA(client, compression) = compression;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hash_pbkdf2_algo)
|
||||
free (hash_pbkdf2_algo);
|
||||
if (salt)
|
||||
free (salt);
|
||||
if (hash_pbkdf2)
|
||||
free (hash_pbkdf2);
|
||||
weechat_string_free_split_command (options);
|
||||
}
|
||||
|
||||
free (hash_algo);
|
||||
if (!password_received)
|
||||
{
|
||||
plain_text_password = weechat_string_match_list (
|
||||
relay_auth_password_name[0],
|
||||
(const char **)relay_config_network_auth_password_list,
|
||||
1);
|
||||
if (plain_text_password)
|
||||
auth_found = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
client->auth_password = auth_found;
|
||||
|
||||
relay_weechat_protocol_handshake_reply (client, command);
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -328,12 +332,12 @@ end:
|
||||
|
||||
RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
|
||||
{
|
||||
char **options, *pos, *password, *totp_secret, *info_totp_args, *info_totp;
|
||||
char **options, *pos, *relay_password, *totp_secret, *info_totp_args, *info_totp;
|
||||
int i, compression, length, password_received, totp_received;
|
||||
|
||||
RELAY_WEECHAT_PROTOCOL_MIN_ARGS(0);
|
||||
|
||||
password = weechat_string_eval_expression (
|
||||
relay_password = weechat_string_eval_expression (
|
||||
weechat_config_string (relay_config_network_password),
|
||||
NULL, NULL, NULL);
|
||||
totp_secret = weechat_string_eval_expression (
|
||||
@@ -357,17 +361,14 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
|
||||
if (strcmp (options[i], "password") == 0)
|
||||
{
|
||||
password_received = 1;
|
||||
if (password && (strcmp (password, pos) == 0))
|
||||
if (relay_auth_password (client, pos, relay_password))
|
||||
RELAY_WEECHAT_DATA(client, password_ok) = 1;
|
||||
}
|
||||
else if (strcmp (options[i], "password_hash") == 0)
|
||||
{
|
||||
password_received = 1;
|
||||
if (password
|
||||
&& relay_weechat_protocol_check_hash (pos, password))
|
||||
{
|
||||
if (relay_auth_password_hash (client, pos, relay_password))
|
||||
RELAY_WEECHAT_DATA(client, password_ok) = 1;
|
||||
}
|
||||
}
|
||||
else if (strcmp (options[i], "totp") == 0)
|
||||
{
|
||||
@@ -405,7 +406,7 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
|
||||
}
|
||||
|
||||
/* if no password received and password is empty, it's OK */
|
||||
if (!password_received && (!password || !password[0]))
|
||||
if (!password_received && (!relay_password || !relay_password[0]))
|
||||
RELAY_WEECHAT_DATA(client, password_ok) = 1;
|
||||
|
||||
/* if no TOTP received and totp_secret is empty, it's OK */
|
||||
@@ -425,8 +426,8 @@ RELAY_WEECHAT_PROTOCOL_CALLBACK(init)
|
||||
relay_client_set_status (client, RELAY_STATUS_AUTH_FAILED);
|
||||
}
|
||||
|
||||
if (password)
|
||||
free (password);
|
||||
if (relay_password)
|
||||
free (relay_password);
|
||||
if (totp_secret)
|
||||
free (totp_secret);
|
||||
|
||||
@@ -1547,7 +1548,8 @@ relay_weechat_protocol_recv (struct t_relay_client *client, const char *data)
|
||||
char *pos, *id, *command, **argv, **argv_eol;
|
||||
int i, argc, return_code;
|
||||
struct t_relay_weechat_protocol_cb protocol_cb[] =
|
||||
{ { "init", &relay_weechat_protocol_cb_init },
|
||||
{ { "handshake", &relay_weechat_protocol_cb_handshake },
|
||||
{ "init", &relay_weechat_protocol_cb_init },
|
||||
{ "hdata", &relay_weechat_protocol_cb_hdata },
|
||||
{ "info", &relay_weechat_protocol_cb_info },
|
||||
{ "infolist", &relay_weechat_protocol_cb_infolist },
|
||||
@@ -1631,13 +1633,14 @@ 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)
|
||||
if ((strcmp (protocol_cb[i].name, "handshake") != 0)
|
||||
&& (strcmp (protocol_cb[i].name, "init") != 0)
|
||||
&& (!RELAY_WEECHAT_DATA(client, password_ok)
|
||||
|| !RELAY_WEECHAT_DATA(client, totp_ok)))
|
||||
{
|
||||
/*
|
||||
* command is not "init" and password or totp are not set?
|
||||
* then close connection!
|
||||
* command is not handshake/init and password or totp are not
|
||||
* set? then close connection!
|
||||
*/
|
||||
relay_client_set_status (client,
|
||||
RELAY_STATUS_AUTH_FAILED);
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "../relay-raw.h"
|
||||
|
||||
|
||||
char *relay_weechat_compression_string[] = /* strings for compressions */
|
||||
char *relay_weechat_compression_string[] = /* strings for compression */
|
||||
{ "off", "zlib" };
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user