mirror of
https://github.com/transmission/transmission
synced 2025-02-19 20:57:19 +00:00
configure anti brute force (#1447)
* add brute force configuration options
This commit is contained in:
parent
9d313a8816
commit
cfce6e2e3a
8 changed files with 142 additions and 3 deletions
|
@ -46,6 +46,8 @@ static struct tr_key_struct const my_static[] =
|
|||
Q("announce"),
|
||||
Q("announce-list"),
|
||||
Q("announceState"),
|
||||
Q("anti-brute-force-enabled"),
|
||||
Q("anti-brute-force-threshold"),
|
||||
Q("arguments"),
|
||||
Q("bandwidth-priority"),
|
||||
Q("bandwidthPriority"),
|
||||
|
|
|
@ -45,6 +45,8 @@ enum
|
|||
TR_KEY_announce, /* metainfo */
|
||||
TR_KEY_announce_list, /* metainfo */
|
||||
TR_KEY_announceState, /* rpc */
|
||||
TR_KEY_anti_brute_force_enabled, /* rpc */
|
||||
TR_KEY_anti_brute_force_threshold, /* rpc */
|
||||
TR_KEY_arguments, /* rpc */
|
||||
TR_KEY_bandwidth_priority,
|
||||
TR_KEY_bandwidthPriority,
|
||||
|
|
|
@ -65,6 +65,8 @@ struct tr_rpc_server
|
|||
tr_list* whitelist;
|
||||
tr_list* hostWhitelist;
|
||||
int loginattempts;
|
||||
bool isAntiBruteForceEnabled;
|
||||
int antiBruteForceThreshold;
|
||||
|
||||
bool isStreamInitialized;
|
||||
z_stream stream;
|
||||
|
@ -641,7 +643,7 @@ static void handle_request(struct evhttp_request* req, void* arg)
|
|||
|
||||
evhttp_add_header(req->output_headers, "Server", MY_REALM);
|
||||
|
||||
if (server->loginattempts == 100)
|
||||
if (server->isAntiBruteForceEnabled && server->loginattempts >= server->antiBruteForceThreshold)
|
||||
{
|
||||
send_simple_response(req, 403, "<p>Too many unsuccessful login attempts. Please restart transmission-daemon.</p>");
|
||||
return;
|
||||
|
@ -681,7 +683,11 @@ static void handle_request(struct evhttp_request* req, void* arg)
|
|||
!tr_ssha1_matches(server->password, pass)))
|
||||
{
|
||||
evhttp_add_header(req->output_headers, "WWW-Authenticate", "Basic realm=\"" MY_REALM "\"");
|
||||
server->loginattempts++;
|
||||
if (server->isAntiBruteForceEnabled)
|
||||
{
|
||||
server->loginattempts++;
|
||||
}
|
||||
|
||||
char* unauthuser = tr_strdup_printf("<p>Unauthorized User. %d unsuccessful login attempts.</p>",
|
||||
server->loginattempts);
|
||||
send_simple_response(req, 401, unauthuser);
|
||||
|
@ -1066,6 +1072,30 @@ char const* tr_rpcGetBindAddress(tr_rpc_server const* server)
|
|||
return tr_address_to_string(&server->bindAddress);
|
||||
}
|
||||
|
||||
bool tr_rpcGetAntiBruteForceEnabled(tr_rpc_server const* server)
|
||||
{
|
||||
return server->isAntiBruteForceEnabled;
|
||||
}
|
||||
|
||||
void tr_rpcSetAntiBruteForceEnabled(tr_rpc_server* server, bool isEnabled)
|
||||
{
|
||||
server->isAntiBruteForceEnabled = isEnabled;
|
||||
if (!isEnabled)
|
||||
{
|
||||
server->loginattempts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int tr_rpcGetAntiBruteForceThreshold(tr_rpc_server const* server)
|
||||
{
|
||||
return server->antiBruteForceThreshold;
|
||||
}
|
||||
|
||||
void tr_rpcSetAntiBruteForceThreshold(tr_rpc_server* server, int badRequests)
|
||||
{
|
||||
server->antiBruteForceThreshold = badRequests;
|
||||
}
|
||||
|
||||
/****
|
||||
***** LIFE CYCLE
|
||||
****/
|
||||
|
@ -1228,6 +1258,28 @@ tr_rpc_server* tr_rpcInit(tr_session* session, tr_variant* settings)
|
|||
tr_rpcSetPassword(s, str);
|
||||
}
|
||||
|
||||
key = TR_KEY_anti_brute_force_enabled;
|
||||
|
||||
if (!tr_variantDictFindBool(settings, key, &boolVal))
|
||||
{
|
||||
missing_settings_key(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_rpcSetAntiBruteForceEnabled(s, boolVal);
|
||||
}
|
||||
|
||||
key = TR_KEY_anti_brute_force_threshold;
|
||||
|
||||
if (!tr_variantDictFindInt(settings, key, &i))
|
||||
{
|
||||
missing_settings_key(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_rpcSetAntiBruteForceThreshold(s, i);
|
||||
}
|
||||
|
||||
key = TR_KEY_rpc_bind_address;
|
||||
|
||||
if (!tr_variantDictFindStr(settings, key, &str, NULL))
|
||||
|
|
|
@ -58,4 +58,12 @@ void tr_rpcSetPasswordEnabled(tr_rpc_server* server, bool isEnabled);
|
|||
|
||||
bool tr_rpcIsPasswordEnabled(tr_rpc_server const* session);
|
||||
|
||||
bool tr_rpcGetAntiBruteForceEnabled(tr_rpc_server const* server);
|
||||
|
||||
void tr_rpcSetAntiBruteForceEnabled(tr_rpc_server* server, bool is_enabled);
|
||||
|
||||
int tr_rpcGetAntiBruteForceThreshold(tr_rpc_server const* server);
|
||||
|
||||
void tr_rpcSetAntiBruteForceThreshold(tr_rpc_server* server, int badRequests);
|
||||
|
||||
char const* tr_rpcGetBindAddress(tr_rpc_server const* server);
|
||||
|
|
|
@ -2277,6 +2277,16 @@ static char const* sessionSet(tr_session* session, tr_variant* args_in, tr_varia
|
|||
}
|
||||
}
|
||||
|
||||
if (tr_variantDictFindInt(args_in, TR_KEY_anti_brute_force_threshold, &i))
|
||||
{
|
||||
tr_sessionSetAntiBruteForceThreshold(session, i);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindBool(args_in, TR_KEY_anti_brute_force_enabled, &boolVal))
|
||||
{
|
||||
tr_sessionSetAntiBruteForceEnabled(session, boolVal);
|
||||
}
|
||||
|
||||
notify(session, TR_RPC_SESSION_CHANGED, NULL);
|
||||
|
||||
return NULL;
|
||||
|
@ -2521,6 +2531,14 @@ static void addSessionField(tr_session* s, tr_variant* d, tr_quark key)
|
|||
tr_variantDictAddInt(d, key, tr_sessionGetQueueStalledMinutes(s));
|
||||
break;
|
||||
|
||||
case TR_KEY_anti_brute_force_enabled:
|
||||
tr_variantDictAddBool(d, key, tr_sessionGetAntiBruteForceEnabled(s));
|
||||
break;
|
||||
|
||||
case TR_KEY_anti_brute_force_threshold:
|
||||
tr_variantDictAddInt(d, key, tr_sessionGetAntiBruteForceThreshold(s));
|
||||
break;
|
||||
|
||||
case TR_KEY_units:
|
||||
tr_formatter_get_units(tr_variantDictAddDict(d, key, 0));
|
||||
break;
|
||||
|
|
|
@ -404,6 +404,8 @@ void tr_sessionGetDefaultSettings(tr_variant* d)
|
|||
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, TR_DEFAULT_BIND_ADDRESS_IPV6);
|
||||
tr_variantDictAddBool(d, TR_KEY_start_added_torrents, true);
|
||||
tr_variantDictAddBool(d, TR_KEY_trash_original_torrent_files, false);
|
||||
tr_variantDictAddInt(d, TR_KEY_anti_brute_force_threshold, 100);
|
||||
tr_variantDictAddBool(d, TR_KEY_anti_brute_force_enabled, true);
|
||||
}
|
||||
|
||||
void tr_sessionGetSettings(tr_session* s, tr_variant* d)
|
||||
|
@ -475,6 +477,8 @@ void tr_sessionGetSettings(tr_session* s, tr_variant* d)
|
|||
tr_variantDictAddStr(d, TR_KEY_bind_address_ipv6, tr_address_to_string(&s->public_ipv6->addr));
|
||||
tr_variantDictAddBool(d, TR_KEY_start_added_torrents, !tr_sessionGetPaused(s));
|
||||
tr_variantDictAddBool(d, TR_KEY_trash_original_torrent_files, tr_sessionGetDeleteSource(s));
|
||||
tr_variantDictAddInt(d, TR_KEY_anti_brute_force_threshold, tr_sessionGetAntiBruteForceThreshold(s));
|
||||
tr_variantDictAddBool(d, TR_KEY_anti_brute_force_enabled, tr_sessionGetAntiBruteForceEnabled(s));
|
||||
}
|
||||
|
||||
bool tr_sessionLoadSettings(tr_variant* dict, char const* configDir, char const* appName)
|
||||
|
@ -1144,6 +1148,20 @@ static void sessionSetImpl(void* vdata)
|
|||
session->scrapePausedTorrents = boolVal;
|
||||
}
|
||||
|
||||
/**
|
||||
*** BruteForce
|
||||
**/
|
||||
|
||||
if (tr_variantDictFindInt(settings, TR_KEY_anti_brute_force_threshold, &i))
|
||||
{
|
||||
tr_sessionSetAntiBruteForceThreshold(session, i);
|
||||
}
|
||||
|
||||
if (tr_variantDictFindBool(settings, TR_KEY_anti_brute_force_enabled, &boolVal))
|
||||
{
|
||||
tr_sessionSetAntiBruteForceEnabled(session, boolVal);
|
||||
}
|
||||
|
||||
data->done = true;
|
||||
}
|
||||
|
||||
|
@ -2947,6 +2965,34 @@ int tr_sessionGetQueueStalledMinutes(tr_session const* session)
|
|||
return session->queueStalledMinutes;
|
||||
}
|
||||
|
||||
void tr_sessionSetAntiBruteForceThreshold(tr_session* session, int bad_requests)
|
||||
{
|
||||
TR_ASSERT(tr_isSession(session));
|
||||
TR_ASSERT(bad_requests > 0);
|
||||
tr_rpcSetAntiBruteForceThreshold(session->rpcServer, bad_requests);
|
||||
}
|
||||
|
||||
void tr_sessionSetAntiBruteForceEnabled(tr_session* session, bool is_enabled)
|
||||
{
|
||||
TR_ASSERT(tr_isSession(session));
|
||||
|
||||
tr_rpcSetAntiBruteForceEnabled(session->rpcServer, is_enabled);
|
||||
}
|
||||
|
||||
bool tr_sessionGetAntiBruteForceEnabled(tr_session const* session)
|
||||
{
|
||||
TR_ASSERT(tr_isSession(session));
|
||||
|
||||
return tr_rpcGetAntiBruteForceEnabled(session->rpcServer);
|
||||
}
|
||||
|
||||
int tr_sessionGetAntiBruteForceThreshold(tr_session const* session)
|
||||
{
|
||||
TR_ASSERT(tr_isSession(session));
|
||||
|
||||
return tr_rpcGetAntiBruteForceThreshold(session->rpcServer);
|
||||
}
|
||||
|
||||
struct TorrentAndPosition
|
||||
{
|
||||
tr_torrent* tor;
|
||||
|
|
|
@ -601,6 +601,15 @@ bool tr_sessionGetDeleteSource(tr_session const*);
|
|||
tr_priority_t tr_torrentGetPriority(tr_torrent const*);
|
||||
void tr_torrentSetPriority(tr_torrent*, tr_priority_t);
|
||||
|
||||
void tr_sessionSetAntiBruteForceThreshold(tr_session*, int bad_requests);
|
||||
int tr_sessionGetAntiBruteForceThreshold(tr_session const*);
|
||||
|
||||
void tr_sessionSetAntiBruteForceEnabled(tr_session*, bool enabled);
|
||||
bool tr_sessionGetAntiBruteForceEnabled(tr_session const*);
|
||||
|
||||
/**
|
||||
**/
|
||||
|
||||
/***
|
||||
****
|
||||
**** Torrent Queueing
|
||||
|
|
|
@ -102,7 +102,7 @@ TEST_F(RpcTest, sessionGet)
|
|||
EXPECT_TRUE(tr_variantDictFindDict(&response, TR_KEY_arguments, &args));
|
||||
|
||||
// what we expected
|
||||
auto const expected_keys = std::array<tr_quark, 50>{
|
||||
auto const expected_keys = std::array<tr_quark, 52>{
|
||||
TR_KEY_alt_speed_down,
|
||||
TR_KEY_alt_speed_enabled,
|
||||
TR_KEY_alt_speed_time_begin,
|
||||
|
@ -110,6 +110,8 @@ TEST_F(RpcTest, sessionGet)
|
|||
TR_KEY_alt_speed_time_enabled,
|
||||
TR_KEY_alt_speed_time_end,
|
||||
TR_KEY_alt_speed_up,
|
||||
TR_KEY_anti_brute_force_enabled,
|
||||
TR_KEY_anti_brute_force_threshold,
|
||||
TR_KEY_blocklist_enabled,
|
||||
TR_KEY_blocklist_size,
|
||||
TR_KEY_blocklist_url,
|
||||
|
|
Loading…
Reference in a new issue