diff --git a/CMakeLists.txt b/CMakeLists.txt index ee7ef6270..5158a815e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -534,7 +534,6 @@ set(NEEDED_FUNCTIONS fallocate64 flock getmntent - getpagesize gmtime_r gmtime_s htonll @@ -545,7 +544,6 @@ set(NEEDED_FUNCTIONS ntohll posix_fadvise posix_fallocate - posix_memalign pread pwrite statvfs @@ -553,8 +551,7 @@ set(NEEDED_FUNCTIONS strlcpy strsep syslog - uselocale - valloc) + uselocale) foreach(F ${NEEDED_FUNCTIONS}) tr_make_id("${F}" F_ID) diff --git a/libtransmission/inout.c b/libtransmission/inout.c index af4421439..58be75bad 100644 --- a/libtransmission/inout.c +++ b/libtransmission/inout.c @@ -251,7 +251,7 @@ static bool recalculateHash(tr_torrent* tor, tr_piece_index_t pieceIndex, uint8_ uint32_t offset = 0; bool success = true; size_t const buflen = tor->blockSize; - void* buffer = tr_valloc(buflen); + void* const buffer = tr_malloc(buflen); tr_sha1_ctx_t sha; TR_ASSERT(buffer != NULL); diff --git a/libtransmission/makemeta.c b/libtransmission/makemeta.c index da92e188f..21095c1ed 100644 --- a/libtransmission/makemeta.c +++ b/libtransmission/makemeta.c @@ -265,7 +265,7 @@ static uint8_t* getHashInfo(tr_metainfo_builder* b) return ret; } - buf = tr_valloc(b->pieceSize); + buf = tr_malloc(b->pieceSize); b->pieceIndex = 0; totalRemain = b->totalSize; fd = tr_sys_file_open(b->files[fileIndex].filename, TR_SYS_FILE_READ | TR_SYS_FILE_SEQUENTIAL, 0, &error); diff --git a/libtransmission/quark.c b/libtransmission/quark.c index b0b1bd8c2..a1cfd9b5c 100644 --- a/libtransmission/quark.c +++ b/libtransmission/quark.c @@ -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"), diff --git a/libtransmission/quark.h b/libtransmission/quark.h index 45466532c..823543f90 100644 --- a/libtransmission/quark.h +++ b/libtransmission/quark.h @@ -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, diff --git a/libtransmission/rpc-server.c b/libtransmission/rpc-server.c index d4f6db301..b8b3a6a41 100644 --- a/libtransmission/rpc-server.c +++ b/libtransmission/rpc-server.c @@ -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, "
Too many unsuccessful login attempts. Please restart transmission-daemon.
"); 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("Unauthorized User. %d unsuccessful login attempts.
", 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)) diff --git a/libtransmission/rpc-server.h b/libtransmission/rpc-server.h index ad1eb5204..496359b63 100644 --- a/libtransmission/rpc-server.h +++ b/libtransmission/rpc-server.h @@ -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); diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c index 1d3a126f3..2772d32b7 100644 --- a/libtransmission/rpcimpl.c +++ b/libtransmission/rpcimpl.c @@ -1676,13 +1676,11 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time } else /* successfully fetched the blocklist... */ { - tr_sys_file_t fd; int err; - char* filename; z_stream stream; char const* configDir = tr_sessionGetConfigDir(session); size_t const buflen = 1024 * 128; /* 128 KiB buffer */ - uint8_t* buf = tr_valloc(buflen); + uint8_t* const buf = tr_malloc(buflen); tr_error* error = NULL; /* this is an odd Magic Number required by zlib to enable gz support. @@ -1696,8 +1694,8 @@ static void gotNewBlocklist(tr_session* session, bool did_connect, bool did_time stream.avail_in = response_byte_count; inflateInit2(&stream, windowBits); - filename = tr_buildPath(configDir, "blocklist.tmp.XXXXXX", NULL); - fd = tr_sys_file_open_temp(filename, &error); + char* const filename = tr_buildPath(configDir, "blocklist.tmp.XXXXXX", NULL); + tr_sys_file_t const fd = tr_sys_file_open_temp(filename, &error); if (fd == TR_BAD_SYS_FILE) { @@ -2277,6 +2275,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 +2529,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; diff --git a/libtransmission/session.c b/libtransmission/session.c index 5ee1001c5..7c2d42041 100644 --- a/libtransmission/session.c +++ b/libtransmission/session.c @@ -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; diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h index 2dd7a8a7a..35a39a602 100644 --- a/libtransmission/transmission.h +++ b/libtransmission/transmission.h @@ -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 diff --git a/libtransmission/utils.c b/libtransmission/utils.c index 5506a6165..8105c3ea9 100644 --- a/libtransmission/utils.c +++ b/libtransmission/utils.c @@ -10,11 +10,6 @@ #define _GNU_SOURCE /* glibc's string.h needs this to pick up memmem */ #endif -#if defined(XCODE_BUILD) -#define HAVE_GETPAGESIZE -#define HAVE_VALLOC -#endif - #include