mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-19 23:56:16 +00:00
Add handshake/stream encryption RPC commands
Replace protocol.encryption.set bitmask flags with protocol.encryption.handshake.set and protocol.encryption.stream.set. Add encryption_config to map commands to libtorrent EncryptionPolicy. Startup default matches the old preset (allow_incoming, enable_retry, prefer_plaintext → handshake=allow, stream=allow). Update docs and examples. Peer list distinguishes RC4 (R/L), handshake-only (H/h), and plain (r/l). Fix ui encrypted column conditional. Add encryption config tests; remove OPTION_ENCRYPTION parse tests. Drop the encryption command redirect.
This commit is contained in:
+9
-15
@@ -214,21 +214,15 @@ Add a preferred filename encoding to the list. The encodings are
|
|||||||
attempted in the order they are inserted, if none match the torrent
|
attempted in the order they are inserted, if none match the torrent
|
||||||
default is used.
|
default is used.
|
||||||
.TP
|
.TP
|
||||||
\fBencryption = \fIoption\fB,\fI\&...\fB\fR
|
\fBprotocol.encryption.handshake.set\fR (deny, allow, prefer, require)
|
||||||
Set how rtorrent should deal with encrypted Bittorrent connections. By
|
and \fBprotocol.encryption.stream.set\fR (deny, allow, prefer,
|
||||||
default, encryption is disabled, equivalent to specifying the option
|
require) control how rtorrent deals with encrypted Bittorrent
|
||||||
\fBnone\fR\&. Alternatively, any number of the following
|
connections. Handshake \fBallow\fR accepts plain or PE inbound and
|
||||||
options may be specified:
|
tries plain first outbound with one PE retry on failure.
|
||||||
|
\fBprefer\fR tries PE first with one plain retry. Stream \fBallow\fR
|
||||||
\fBallow_incoming\fR (allow incoming encrypted connections),
|
and \fBprefer\fR offer both handshake-only and RC4 on outgoing PE
|
||||||
\fBtry_outgoing\fR (use encryption for outgoing connections),
|
connections. The default is handshake=allow, stream=allow. Use
|
||||||
\fBrequire\fR (disable unencrypted handshakes),
|
\fBprotocol.encryption\fR to inspect the effective policy.
|
||||||
\fBrequire_RC4\fR (also disable plaintext transmission after the
|
|
||||||
initial encrypted handshake),
|
|
||||||
\fBenable_retry\fR (if the initial outgoing connection fails, retry
|
|
||||||
with encryption turned on if it was off or off if it was on),
|
|
||||||
\fBprefer_plaintext\fR (choose plaintext when peer offers a choice
|
|
||||||
between plaintext transmission and RC4 encryption, otherwise RC4 will be used).
|
|
||||||
.TP
|
.TP
|
||||||
\fBpeer_exchange = \fIyes | no\fB\fR
|
\fBpeer_exchange = \fIyes | no\fB\fR
|
||||||
Enable/disable peer exchange for torrents that aren't marked private. Disabled by default.
|
Enable/disable peer exchange for torrents that aren't marked private. Disabled by default.
|
||||||
|
|||||||
+11
-17
@@ -484,25 +484,19 @@ default is used.
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>encryption = <replaceable>option</replaceable>,<replaceable>...</replaceable></term>
|
<term>protocol.encryption.handshake.set = <replaceable>policy</replaceable></term>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
|
|
||||||
Set how rtorrent should deal with encrypted Bittorrent connections. By
|
Control how rtorrent deals with encrypted Bittorrent connections.
|
||||||
default, encryption is disabled, equivalent to specifying the option
|
<emphasis>protocol.encryption.handshake.set</emphasis> (deny, allow, prefer,
|
||||||
<emphasis>none</emphasis>. Alternatively, any number of the following
|
require) and <emphasis>protocol.encryption.stream.set</emphasis> (deny, allow,
|
||||||
options may be specified:
|
prefer, require). Handshake <emphasis>allow</emphasis> accepts plain or PE
|
||||||
|
inbound and tries plain first outbound with one PE retry on failure.
|
||||||
</para><para>
|
<emphasis>prefer</emphasis> tries PE first with one plain retry. Stream
|
||||||
|
<emphasis>allow</emphasis> and <emphasis>prefer</emphasis> offer both
|
||||||
<emphasis>allow_incoming</emphasis> (allow incoming encrypted connections),
|
handshake-only and RC4 on outgoing PE connections. The default is
|
||||||
<emphasis>try_outgoing</emphasis> (use encryption for outgoing connections),
|
handshake=allow, stream=allow. Use <emphasis>protocol.encryption</emphasis> to
|
||||||
<emphasis>require</emphasis> (disable unencrypted handshakes),
|
inspect the effective policy.
|
||||||
<emphasis>require_RC4</emphasis> (also disable plaintext transmission after the
|
|
||||||
initial encrypted handshake),
|
|
||||||
<emphasis>enable_retry</emphasis> (if the initial outgoing connection fails, retry
|
|
||||||
with encryption turned on if it was off or off if it was on),
|
|
||||||
<emphasis>prefer_plaintext</emphasis> (choose plaintext when peer offers a choice
|
|
||||||
between plaintext transmission and RC4 encryption, otherwise RC4 will be used).
|
|
||||||
|
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
+32
-6
@@ -95,14 +95,40 @@
|
|||||||
#schedule2 = ip_tick,0,1800,ip=rakshasa
|
#schedule2 = ip_tick,0,1800,ip=rakshasa
|
||||||
#schedule2 = bind_tick,0,1800,bind=rakshasa
|
#schedule2 = bind_tick,0,1800,bind=rakshasa
|
||||||
|
|
||||||
# Encryption options, set to none (default) or any combination of the following:
|
# --- Protocol encryption (PE handshake / optional RC4 stream) ---
|
||||||
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
|
# Default at startup: handshake=allow stream=allow
|
||||||
#
|
#
|
||||||
# The example value allows incoming encrypted connections, starts unencrypted
|
# Handshake (PE handshake; incoming accepts plain or PE for allow/prefer):
|
||||||
# outgoing connections but retries with encryption if they fail, preferring
|
# deny - plain BT handshake only both ways; no retry
|
||||||
# plain-text to RC4 encryption after the encrypted handshake.
|
# allow - accept plain or PE inbound; plain first outbound with one PE retry
|
||||||
|
# prefer - accept plain or PE inbound; PE first outbound with one plain retry
|
||||||
|
# require - PE handshake required both ways; no retry
|
||||||
#
|
#
|
||||||
# protocol.encryption.set = allow_incoming,enable_retry,prefer_plaintext
|
# protocol.encryption.handshake.set = allow
|
||||||
|
#
|
||||||
|
# Stream (cipher negotiation after PE handshake succeeds):
|
||||||
|
# deny - offer handshake-only; require handshake-only (no RC4)
|
||||||
|
# allow - incoming: prefer handshake-only if offered, else RC4
|
||||||
|
# outgoing: offer both handshake-only and RC4
|
||||||
|
# prefer - incoming: pick RC4 if offered, else handshake-only
|
||||||
|
# outgoing: offer both handshake-only and RC4
|
||||||
|
# require - offer RC4 only; require RC4
|
||||||
|
#
|
||||||
|
# Outgoing retry summary with handshake=allow (plain first):
|
||||||
|
# stream=allow/prefer -> plain BT -> PE (both)
|
||||||
|
# stream=deny -> plain BT -> PE (handshake-only)
|
||||||
|
# stream=require -> plain BT -> PE (RC4-only)
|
||||||
|
#
|
||||||
|
# Outgoing retry summary with handshake=prefer (PE first):
|
||||||
|
# stream=allow/prefer -> PE (both) -> plain BT
|
||||||
|
# stream=deny -> PE (handshake-only) -> plain BT
|
||||||
|
# stream=require -> PE (RC4-only) -> plain BT
|
||||||
|
#
|
||||||
|
# Negotiated stream cipher is logged at connection_handshake level.
|
||||||
|
#
|
||||||
|
# protocol.encryption.stream.set = allow
|
||||||
|
#
|
||||||
|
# Use protocol.encryption to inspect the effective policy.
|
||||||
|
|
||||||
# Enable DHT support for trackerless torrents or when all trackers are down.
|
# Enable DHT support for trackerless torrents or when all trackers are down.
|
||||||
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
|
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ throttle.min_peers.seed.set = 30
|
|||||||
throttle.max_peers.seed.set = 80
|
throttle.max_peers.seed.set = 80
|
||||||
trackers.numwant.set = 80
|
trackers.numwant.set = 80
|
||||||
|
|
||||||
protocol.encryption.set = allow_incoming,try_outgoing,enable_retry
|
protocol.encryption.handshake.set = allow
|
||||||
|
protocol.encryption.stream.set = prefer
|
||||||
|
|
||||||
# Limits for file handle resources, this is optimized for
|
# Limits for file handle resources, this is optimized for
|
||||||
# an `ulimit` of 1024 (a common default). You MUST leave
|
# an `ulimit` of 1024 (a common default). You MUST leave
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ rc.throttle.min_peers.seed = 30
|
|||||||
rc.throttle.max_peers.seed = 80
|
rc.throttle.max_peers.seed = 80
|
||||||
rc.trackers.numwant = 80
|
rc.trackers.numwant = 80
|
||||||
|
|
||||||
rc.protocol.encryption.set('allow_incoming', 'try_outgoing', 'enable_retry')
|
rc.protocol.encryption.handshake.set('allow')
|
||||||
|
rc.protocol.encryption.stream.set('prefer')
|
||||||
|
|
||||||
-- Limits for file handle resources, this is optimized for
|
-- Limits for file handle resources, this is optimized for
|
||||||
-- an `ulimit` of 1024 (a common default). You MUST leave
|
-- an `ulimit` of 1024 (a common default). You MUST leave
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ echo "Client version: " `xmlrpc2scgi.py -p scgi://127.0.0.1:${PORT_NUMBER} syste
|
|||||||
echo
|
echo
|
||||||
echo "Generated by 'rtorrent/doc/scripts/print_option_string.sh' on `date -u`."
|
echo "Generated by 'rtorrent/doc/scripts/print_option_string.sh' on `date -u`."
|
||||||
|
|
||||||
for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do
|
for i in strings.choke_heuristics strings.choke_heuristics.upload strings.choke_heuristics.download strings.connection_type strings.encryption.handshake strings.encryption.stream strings.ip_filter strings.ip_tos strings.log_group strings.tracker_event strings.tracker_mode; do
|
||||||
echo
|
echo
|
||||||
echo $i
|
echo $i
|
||||||
echo `echo $i | tr 'a-z_.' '-'`
|
echo `echo $i | tr 'a-z_.' '-'`
|
||||||
|
|||||||
@@ -188,6 +188,8 @@ libsub_root_a_SOURCES = \
|
|||||||
command_local.cc \
|
command_local.cc \
|
||||||
command_logging.cc \
|
command_logging.cc \
|
||||||
command_network.cc \
|
command_network.cc \
|
||||||
|
encryption_config.cc \
|
||||||
|
encryption_config.h \
|
||||||
command_peer.cc \
|
command_peer.cc \
|
||||||
command_throttle.cc \
|
command_throttle.cc \
|
||||||
command_tracker.cc \
|
command_tracker.cc \
|
||||||
|
|||||||
@@ -448,7 +448,8 @@ initialize_command_dynamic() {
|
|||||||
CMD2_ANY ("strings.choke_heuristics.upload", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
|
CMD2_ANY ("strings.choke_heuristics.upload", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_UPLOAD));
|
||||||
CMD2_ANY ("strings.choke_heuristics.download", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
|
CMD2_ANY ("strings.choke_heuristics.download", std::bind(&torrent::option_list_strings, torrent::OPTION_CHOKE_HEURISTICS_DOWNLOAD));
|
||||||
CMD2_ANY ("strings.connection_type", std::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
|
CMD2_ANY ("strings.connection_type", std::bind(&torrent::option_list_strings, torrent::OPTION_CONNECTION_TYPE));
|
||||||
CMD2_ANY ("strings.encryption", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION));
|
CMD2_ANY ("strings.encryption.handshake", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION_MODE));
|
||||||
|
CMD2_ANY ("strings.encryption.stream", std::bind(&torrent::option_list_strings, torrent::OPTION_ENCRYPTION_MODE));
|
||||||
CMD2_ANY ("strings.ip_filter", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
|
CMD2_ANY ("strings.ip_filter", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_FILTER));
|
||||||
CMD2_ANY ("strings.ip_tos", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
|
CMD2_ANY ("strings.ip_tos", std::bind(&torrent::option_list_strings, torrent::OPTION_IP_TOS));
|
||||||
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
|
CMD2_ANY ("strings.log_group", std::bind(&torrent::option_list_strings, torrent::OPTION_LOG_GROUP));
|
||||||
@@ -472,7 +473,8 @@ initialize_command_dynamic() {
|
|||||||
rpc::rpc.mark_safe("strings.choke_heuristics.upload");
|
rpc::rpc.mark_safe("strings.choke_heuristics.upload");
|
||||||
rpc::rpc.mark_safe("strings.choke_heuristics.download");
|
rpc::rpc.mark_safe("strings.choke_heuristics.download");
|
||||||
rpc::rpc.mark_safe("strings.connection_type");
|
rpc::rpc.mark_safe("strings.connection_type");
|
||||||
rpc::rpc.mark_safe("strings.encryption");
|
rpc::rpc.mark_safe("strings.encryption.handshake");
|
||||||
|
rpc::rpc.mark_safe("strings.encryption.stream");
|
||||||
rpc::rpc.mark_safe("strings.ip_filter");
|
rpc::rpc.mark_safe("strings.ip_filter");
|
||||||
rpc::rpc.mark_safe("strings.ip_tos");
|
rpc::rpc.mark_safe("strings.ip_tos");
|
||||||
rpc::rpc.mark_safe("strings.log_group");
|
rpc::rpc.mark_safe("strings.log_group");
|
||||||
|
|||||||
+3
-19
@@ -17,6 +17,7 @@
|
|||||||
#include <torrent/utils/log.h>
|
#include <torrent/utils/log.h>
|
||||||
#include <torrent/utils/option_strings.h>
|
#include <torrent/utils/option_strings.h>
|
||||||
|
|
||||||
|
#include "encryption_config.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "control.h"
|
#include "control.h"
|
||||||
#include "command_helpers.h"
|
#include "command_helpers.h"
|
||||||
@@ -32,24 +33,6 @@
|
|||||||
#include <systemd/sd-daemon.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
torrent::Object
|
|
||||||
apply_encryption(const torrent::Object::list_type& args) {
|
|
||||||
uint32_t options_mask = torrent::runtime::NetworkConfig::encryption_none;
|
|
||||||
|
|
||||||
for (const auto& arg : args) {
|
|
||||||
uint32_t opt = torrent::option_find_string(torrent::OPTION_ENCRYPTION, arg.as_string().c_str());
|
|
||||||
|
|
||||||
if (opt == torrent::runtime::NetworkConfig::encryption_none)
|
|
||||||
options_mask = torrent::runtime::NetworkConfig::encryption_none;
|
|
||||||
else
|
|
||||||
options_mask |= opt;
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent::runtime::network_config()->set_encryption_options(options_mask);
|
|
||||||
|
|
||||||
return torrent::Object();
|
|
||||||
}
|
|
||||||
|
|
||||||
torrent::Object
|
torrent::Object
|
||||||
apply_tos(const torrent::Object::string_type& arg) {
|
apply_tos(const torrent::Object::string_type& arg) {
|
||||||
rpc::command_base::value_type value;
|
rpc::command_base::value_type value;
|
||||||
@@ -230,7 +213,8 @@ initialize_command_network() {
|
|||||||
CMD_ANY_VALUE_V ("network.listen.backlog.set", [nw_config](auto, auto& value) { return nw_config->set_listen_backlog(value); });
|
CMD_ANY_VALUE_V ("network.listen.backlog.set", [nw_config](auto, auto& value) { return nw_config->set_listen_backlog(value); });
|
||||||
|
|
||||||
CMD_VAR_BOOL ("protocol.pex", true);
|
CMD_VAR_BOOL ("protocol.pex", true);
|
||||||
CMD_ANY_LIST ("protocol.encryption.set", [](auto, auto& args) { return apply_encryption(args); });
|
|
||||||
|
encryption_config::initialize_commands();
|
||||||
|
|
||||||
CMD_VAR_STRING ("protocol.connection.leech", "leech");
|
CMD_VAR_STRING ("protocol.connection.leech", "leech");
|
||||||
CMD_VAR_STRING ("protocol.connection.seed", "seed");
|
CMD_VAR_STRING ("protocol.connection.seed", "seed");
|
||||||
|
|||||||
@@ -16,6 +16,21 @@
|
|||||||
|
|
||||||
namespace display {
|
namespace display {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
char
|
||||||
|
connection_type_char(const torrent::Peer* p) {
|
||||||
|
if (p->is_encrypted())
|
||||||
|
return p->is_incoming() ? 'R' : 'L';
|
||||||
|
|
||||||
|
if (p->is_obfuscated())
|
||||||
|
return p->is_incoming() ? 'H' : 'h';
|
||||||
|
|
||||||
|
return p->is_incoming() ? 'r' : 'l';
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) :
|
WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) :
|
||||||
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
|
Window(new Canvas, 0, 0, 0, extent_full, extent_full),
|
||||||
m_download(d),
|
m_download(d),
|
||||||
@@ -35,6 +50,7 @@ WindowPeerList::redraw() {
|
|||||||
m_canvas->print(x, y, "UP"); x += 7;
|
m_canvas->print(x, y, "UP"); x += 7;
|
||||||
m_canvas->print(x, y, "DOWN"); x += 7;
|
m_canvas->print(x, y, "DOWN"); x += 7;
|
||||||
m_canvas->print(x, y, "PEER"); x += 7;
|
m_canvas->print(x, y, "PEER"); x += 7;
|
||||||
|
// CT: R/H/r or L/h/l (RC4 / handshake-only / plain) + peer type (u/p/ )
|
||||||
m_canvas->print(x, y, "CT/RE/LO"); x += 10;
|
m_canvas->print(x, y, "CT/RE/LO"); x += 10;
|
||||||
m_canvas->print(x, y, "QS"); x += 6;
|
m_canvas->print(x, y, "QS"); x += 6;
|
||||||
m_canvas->print(x, y, "DONE"); x += 6;
|
m_canvas->print(x, y, "DONE"); x += 6;
|
||||||
@@ -95,7 +111,7 @@ WindowPeerList::redraw() {
|
|||||||
peerType = ' ';
|
peerType = ' ';
|
||||||
|
|
||||||
m_canvas->print(x, y, "%c%c/%c%c/%c%c",
|
m_canvas->print(x, y, "%c%c/%c%c/%c%c",
|
||||||
p->is_encrypted() ? (p->is_incoming() ? 'R' : 'L') : (p->is_incoming() ? 'r' : 'l'),
|
connection_type_char(p),
|
||||||
peerType,
|
peerType,
|
||||||
p->is_down_choked() ? std::tolower(remoteChoked) : remoteChoked,
|
p->is_down_choked() ? std::tolower(remoteChoked) : remoteChoked,
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "encryption_config.h"
|
||||||
|
|
||||||
|
#include <torrent/runtime/network_config.h>
|
||||||
|
#include <torrent/runtime/runtime.h>
|
||||||
|
#include <torrent/utils/option_strings.h>
|
||||||
|
|
||||||
|
#include "command_helpers.h"
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
namespace encryption_config {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Policy
|
||||||
|
current_policy() {
|
||||||
|
return torrent::runtime::network_config()->encryption_policy();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Policy
|
||||||
|
default_policy() {
|
||||||
|
Policy policy;
|
||||||
|
policy.handshake = Policy::Mode::allow;
|
||||||
|
policy.stream = Policy::Mode::allow;
|
||||||
|
return policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mode_to_string(Policy::Mode value) {
|
||||||
|
return torrent::option_to_str_or_throw(torrent::OPTION_ENCRYPTION_MODE,
|
||||||
|
static_cast<unsigned int>(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
apply_mode_value(Policy& policy, Policy::Mode Policy::*field, const std::string& value) {
|
||||||
|
policy.*field = static_cast<Policy::Mode>(
|
||||||
|
torrent::option_find_string_str(torrent::OPTION_ENCRYPTION_MODE, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
summary_string(const Policy& policy) {
|
||||||
|
return "handshake=" + mode_to_string(policy.handshake)
|
||||||
|
+ " stream=" + mode_to_string(policy.stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
apply_policy(const Policy& policy) {
|
||||||
|
torrent::runtime::network_config()->set_encryption_policy(policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
torrent::Object
|
||||||
|
apply_handshake_set(const std::string& value) {
|
||||||
|
Policy policy = current_policy();
|
||||||
|
apply_mode_value(policy, &Policy::handshake, value);
|
||||||
|
apply_policy(policy);
|
||||||
|
return torrent::Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
torrent::Object
|
||||||
|
apply_stream_set(const std::string& value) {
|
||||||
|
Policy policy = current_policy();
|
||||||
|
apply_mode_value(policy, &Policy::stream, value);
|
||||||
|
apply_policy(policy);
|
||||||
|
return torrent::Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
initialize_commands() {
|
||||||
|
apply_policy(default_policy());
|
||||||
|
|
||||||
|
CMD2_ANY("protocol.encryption", [](auto, auto) { return summary_string(current_policy()); });
|
||||||
|
|
||||||
|
CMD2_ANY("protocol.encryption.handshake", [](auto, auto) { return mode_to_string(current_policy().handshake); });
|
||||||
|
CMD2_ANY_STRING_V("protocol.encryption.handshake.set", [](auto, auto& str) { return apply_handshake_set(str); });
|
||||||
|
|
||||||
|
CMD2_ANY("protocol.encryption.stream", [](auto, auto) { return mode_to_string(current_policy().stream); });
|
||||||
|
CMD2_ANY_STRING_V("protocol.encryption.stream.set", [](auto, auto& str) { return apply_stream_set(str); });
|
||||||
|
|
||||||
|
rpc::rpc.mark_safe("protocol.encryption");
|
||||||
|
rpc::rpc.mark_safe("protocol.encryption.handshake");
|
||||||
|
rpc::rpc.mark_safe("protocol.encryption.handshake.set");
|
||||||
|
rpc::rpc.mark_safe("protocol.encryption.stream");
|
||||||
|
rpc::rpc.mark_safe("protocol.encryption.stream.set");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace encryption_config
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef RTORRENT_ENCRYPTION_CONFIG_H
|
||||||
|
#define RTORRENT_ENCRYPTION_CONFIG_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <torrent/runtime/encryption_policy.h>
|
||||||
|
#include <torrent/object.h>
|
||||||
|
|
||||||
|
namespace encryption_config {
|
||||||
|
|
||||||
|
using Policy = torrent::EncryptionPolicy;
|
||||||
|
|
||||||
|
Policy default_policy();
|
||||||
|
|
||||||
|
std::string mode_to_string(Policy::Mode value);
|
||||||
|
void apply_mode_value(Policy& policy, Policy::Mode Policy::*field, const std::string& value);
|
||||||
|
|
||||||
|
std::string summary_string(const Policy& policy);
|
||||||
|
|
||||||
|
void apply_policy(const Policy& policy);
|
||||||
|
torrent::Object apply_handshake_set(const std::string& value);
|
||||||
|
torrent::Object apply_stream_set(const std::string& value);
|
||||||
|
|
||||||
|
void initialize_commands();
|
||||||
|
|
||||||
|
} // namespace encryption_config
|
||||||
|
|
||||||
|
#endif
|
||||||
+2
-3
@@ -298,7 +298,8 @@ main(int argc, char** argv) {
|
|||||||
"schedule = low_diskspace,5,60,((close_low_diskspace,500M))\n"
|
"schedule = low_diskspace,5,60,((close_low_diskspace,500M))\n"
|
||||||
"schedule = prune_file_status,3600,86400,((system.file_status_cache.prune))\n"
|
"schedule = prune_file_status,3600,86400,((system.file_status_cache.prune))\n"
|
||||||
|
|
||||||
"protocol.encryption.set=allow_incoming,prefer_plaintext,enable_retry\n"
|
"protocol.encryption.handshake.set=allow\n"
|
||||||
|
"protocol.encryption.stream.set=allow\n"
|
||||||
|
|
||||||
"ui.color.focus.set=reverse\n"
|
"ui.color.focus.set=reverse\n"
|
||||||
);
|
);
|
||||||
@@ -318,8 +319,6 @@ main(int argc, char** argv) {
|
|||||||
CMD_REDIRECT("ratio.max.set", "group.seeding.ratio.max.set");
|
CMD_REDIRECT("ratio.max.set", "group.seeding.ratio.max.set");
|
||||||
CMD_REDIRECT("ratio.upload.set", "group.seeding.ratio.upload.set");
|
CMD_REDIRECT("ratio.upload.set", "group.seeding.ratio.upload.set");
|
||||||
|
|
||||||
CMD_REDIRECT("encryption", "protocol.encryption.set");
|
|
||||||
|
|
||||||
CMD_REDIRECT("check_hash", "pieces.hash.on_completion.set");
|
CMD_REDIRECT("check_hash", "pieces.hash.on_completion.set");
|
||||||
|
|
||||||
CMD_REDIRECT("connection_leech", "protocol.connection.leech.set");
|
CMD_REDIRECT("connection_leech", "protocol.connection.leech.set");
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ ElementPeerList::create_info() {
|
|||||||
element->push_column("Client:", te_command("p.client_version="));
|
element->push_column("Client:", te_command("p.client_version="));
|
||||||
element->push_column("Options:", te_command("p.options_str="));
|
element->push_column("Options:", te_command("p.options_str="));
|
||||||
element->push_column("Connected:", te_command("if=$p.is_incoming=,incoming,outgoing"));
|
element->push_column("Connected:", te_command("if=$p.is_incoming=,incoming,outgoing"));
|
||||||
element->push_column("Encrypted:", te_command("if=$p.is_encrypted=,yes,$p.is_obfuscated=,handshake,no"));
|
element->push_column("Encrypted:", te_command("if=$p.is_encrypted=,yes,$if=$p.is_obfuscated=\\,handshake\\,no"));
|
||||||
|
|
||||||
element->push_back("");
|
element->push_back("");
|
||||||
element->push_column("Snubbed:", te_command("if=$p.is_snubbed=,yes,no"));
|
element->push_column("Snubbed:", te_command("if=$p.is_snubbed=,yes,no"));
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ rtorrent_Test_Rpc_SOURCES = $(rtorrent_Test_Common) \
|
|||||||
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
rtorrent_Test_Src_SOURCES = $(rtorrent_Test_Common) \
|
||||||
src/test_command_dynamic.cc \
|
src/test_command_dynamic.cc \
|
||||||
src/test_command_dynamic.h \
|
src/test_command_dynamic.h \
|
||||||
|
src/test_encryption_config.cc \
|
||||||
|
src/test_encryption_config.h \
|
||||||
src/test_watch_ready_queue.cc \
|
src/test_watch_ready_queue.cc \
|
||||||
src/test_watch_ready_queue.h
|
src/test_watch_ready_queue.h
|
||||||
|
|
||||||
|
|||||||
@@ -170,19 +170,18 @@ TestParseOptions::test_flag_libtorrent() {
|
|||||||
FLAG_LT_LOG_ASSERT_ERROR("resume_data|rpc_dump");
|
FLAG_LT_LOG_ASSERT_ERROR("resume_data|rpc_dump");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLAGS_LT_ENCRYPTION_ASSERT(flags, result) \
|
#define FLAGS_LT_IP_TOS_ASSERT(flags, result) \
|
||||||
CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_ENCRYPTION, std::placeholders::_1)) == (result))
|
CPPUNIT_ASSERT(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_IP_TOS, std::placeholders::_1)) == (result))
|
||||||
|
|
||||||
#define FLAGS_LT_ENCRYPTION_ASSERT_ERROR(flags) \
|
#define FLAGS_LT_IP_TOS_ASSERT_ERROR(flags) \
|
||||||
ASSERT_CATCH_INPUT_ERROR(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_ENCRYPTION, std::placeholders::_1)))
|
ASSERT_CATCH_INPUT_ERROR(rpc::parse_option_flags(flags, std::bind(&torrent::option_find_string_str, torrent::OPTION_IP_TOS, std::placeholders::_1)))
|
||||||
|
|
||||||
void
|
void
|
||||||
TestParseOptions::test_flags_libtorrent() {
|
TestParseOptions::test_flags_libtorrent() {
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT("", torrent::runtime::NetworkConfig::encryption_none);
|
FLAGS_LT_IP_TOS_ASSERT("throughput", torrent::option_find_string(torrent::OPTION_IP_TOS, "throughput"));
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT("none", torrent::runtime::NetworkConfig::encryption_none);
|
FLAGS_LT_IP_TOS_ASSERT("lowdelay | throughput",
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT("require_rc4", torrent::runtime::NetworkConfig::encryption_require_RC4);
|
torrent::option_find_string(torrent::OPTION_IP_TOS, "lowdelay")
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT("require_RC4", torrent::runtime::NetworkConfig::encryption_require_RC4);
|
| torrent::option_find_string(torrent::OPTION_IP_TOS, "throughput"));
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT("require_RC4 | enable_retry", torrent::runtime::NetworkConfig::encryption_require_RC4 | torrent::runtime::NetworkConfig::encryption_enable_retry);
|
|
||||||
|
|
||||||
FLAGS_LT_ENCRYPTION_ASSERT_ERROR("require_");
|
FLAGS_LT_IP_TOS_ASSERT_ERROR("throughput_");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "test/src/test_encryption_config.h"
|
||||||
|
|
||||||
|
#include <torrent/runtime/encryption_policy.h>
|
||||||
|
|
||||||
|
#include "encryption_config.h"
|
||||||
|
|
||||||
|
CPPUNIT_TEST_SUITE_REGISTRATION(TestEncryptionConfig);
|
||||||
|
|
||||||
|
void
|
||||||
|
TestEncryptionConfig::test_default_policy() {
|
||||||
|
const auto policy = encryption_config::default_policy();
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT(policy.handshake == encryption_config::Policy::Mode::allow);
|
||||||
|
CPPUNIT_ASSERT(policy.stream == encryption_config::Policy::Mode::allow);
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("handshake=allow stream=allow"),
|
||||||
|
encryption_config::summary_string(policy));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TestEncryptionConfig::test_granular_round_trip() {
|
||||||
|
auto round_trip_handshake = [](const std::string& value) {
|
||||||
|
encryption_config::Policy policy;
|
||||||
|
encryption_config::apply_mode_value(policy, &encryption_config::Policy::handshake, value);
|
||||||
|
return encryption_config::mode_to_string(policy.handshake);
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("deny"), round_trip_handshake("deny"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("allow"), round_trip_handshake("allow"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("prefer"), round_trip_handshake("prefer"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("require"), round_trip_handshake("require"));
|
||||||
|
|
||||||
|
auto round_trip_stream = [](const std::string& value) {
|
||||||
|
encryption_config::Policy policy;
|
||||||
|
encryption_config::apply_mode_value(policy, &encryption_config::Policy::stream, value);
|
||||||
|
return encryption_config::mode_to_string(policy.stream);
|
||||||
|
};
|
||||||
|
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("deny"), round_trip_stream("deny"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("allow"), round_trip_stream("allow"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("prefer"), round_trip_stream("prefer"));
|
||||||
|
CPPUNIT_ASSERT_EQUAL(std::string("require"), round_trip_stream("require"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include "test/helpers/test_fixture.h"
|
||||||
|
|
||||||
|
class TestEncryptionConfig : public test_fixture {
|
||||||
|
CPPUNIT_TEST_SUITE(TestEncryptionConfig);
|
||||||
|
CPPUNIT_TEST(test_default_policy);
|
||||||
|
CPPUNIT_TEST(test_granular_round_trip);
|
||||||
|
CPPUNIT_TEST_SUITE_END();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void test_default_policy();
|
||||||
|
void test_granular_round_trip();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user