Add --bt-force-encryption option

This option requires BitTorrent message payload encryption with
arc4. This is a shorthand of --bt-requre-crypto
--bt-min-crypto-level=arc4.  If true is given, deny legacy BitTorrent
handshake and only use Obfuscation handshake and always encrypt
message payload. This option defaults to false.
pull/324/head
Tatsuhiro Tsujikawa 2015-01-12 17:46:20 +09:00
parent cc36df2625
commit c653c72dc8
9 changed files with 47 additions and 6 deletions

View File

@ -625,6 +625,15 @@ BitTorrent Specific Options
tracker. Although this function is named ``external``, it can accept tracker. Although this function is named ``external``, it can accept
any kind of IP addresses. IPADDRESS must be a numeric IP address. any kind of IP addresses. IPADDRESS must be a numeric IP address.
.. option:: --bt-force-encryption[=true|false]
Requires BitTorrent message payload encryption with arc4. This is a
shorthand of :option:`--bt-requre-crypto`
:option:`--bt-min-crypto-level`\=arc4. This option does not change
the option value of those options. If ``true`` is given, deny
legacy BitTorrent handshake and only use Obfuscation handshake and
always encrypt message payload. Default: ``false``
.. option:: --bt-hash-check-seed[=true|false] .. option:: --bt-hash-check-seed[=true|false]
If ``true`` is given, after hash check using :option:`--check-integrity <-V>` option and If ``true`` is given, after hash check using :option:`--check-integrity <-V>` option and
@ -1894,6 +1903,7 @@ of URIs. These optional lines must start with white space(s).
* :option:`bt-enable-lpd <--bt-enable-lpd>` * :option:`bt-enable-lpd <--bt-enable-lpd>`
* :option:`bt-exclude-tracker <--bt-exclude-tracker>` * :option:`bt-exclude-tracker <--bt-exclude-tracker>`
* :option:`bt-external-ip <--bt-external-ip>` * :option:`bt-external-ip <--bt-external-ip>`
* :option:`bt-force-encryption <--bt-force-encryption>`
* :option:`bt-hash-check-seed <--bt-hash-check-seed>` * :option:`bt-hash-check-seed <--bt-hash-check-seed>`
* :option:`bt-max-peers <--bt-max-peers>` * :option:`bt-max-peers <--bt-max-peers>`
* :option:`bt-metadata-only <--bt-metadata-only>` * :option:`bt-metadata-only <--bt-metadata-only>`

View File

@ -189,7 +189,8 @@ std::string DefaultBtAnnounce::getAnnounceUrl() {
uri += "&trackerid="; uri += "&trackerid=";
uri += util::torrentPercentEncode(trackerId_); uri += util::torrentPercentEncode(trackerId_);
} }
if(option_->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { if(option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) ||
option_->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
uri += "&requirecrypto=1"; uri += "&requirecrypto=1";
} else { } else {
uri += "&supportcrypto=1"; uri += "&supportcrypto=1";

View File

@ -216,7 +216,8 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait)
// established. // established.
tryNewPeer(); tryNewPeer();
return true; return true;
} else if(getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { } else if(getOption()->getAsBool(PREF_BT_FORCE_ENCRYPTION) ||
getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
A2_LOG_INFO(fmt("CUID#%" PRId64 " - Establishing connection using legacy" A2_LOG_INFO(fmt("CUID#%" PRId64 " - Establishing connection using legacy"
" BitTorrent handshake is disabled by preference.", " BitTorrent handshake is disabled by preference.",
getCuid())); getCuid()));
@ -239,6 +240,7 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait)
void InitiatorMSEHandshakeCommand::onAbort() void InitiatorMSEHandshakeCommand::onAbort()
{ {
if(sequence_ == INITIATOR_SEND_KEY || if(sequence_ == INITIATOR_SEND_KEY ||
getOption()->getAsBool(PREF_BT_FORCE_ENCRYPTION) ||
getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
peerStorage_->returnPeer(getPeer()); peerStorage_->returnPeer(getPeer());
} }

View File

@ -284,7 +284,8 @@ void MSEHandshake::sendInitiatorStep2()
ptr += sizeof(VC); ptr += sizeof(VC);
// crypto_provide // crypto_provide
memset(ptr, 0, CRYPTO_BITFIELD_LENGTH); memset(ptr, 0, CRYPTO_BITFIELD_LENGTH);
if(option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) { if(!option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
ptr[3] = CRYPTO_PLAIN_TEXT; ptr[3] = CRYPTO_PLAIN_TEXT;
} }
ptr[3] |= CRYPTO_ARC4; ptr[3] |= CRYPTO_ARC4;
@ -347,7 +348,8 @@ bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength()
//verifyCryptoSelect //verifyCryptoSelect
unsigned char* rbufptr = rbuf_; unsigned char* rbufptr = rbuf_;
decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr); decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
if(rbufptr[3]&CRYPTO_PLAIN_TEXT && if((rbufptr[3]&CRYPTO_PLAIN_TEXT) &&
!option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) { option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer prefers plaintext.", A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer prefers plaintext.",
cuid_)); cuid_));
@ -447,7 +449,8 @@ bool MSEHandshake::receiveReceiverHashAndPadCLength
decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr); decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr);
// TODO choose the crypto type based on the preference. // TODO choose the crypto type based on the preference.
// For now, choose ARC4. // For now, choose ARC4.
if(rbufptr[3]&CRYPTO_PLAIN_TEXT && if((rbufptr[3]&CRYPTO_PLAIN_TEXT) &&
!option_->getAsBool(PREF_BT_FORCE_ENCRYPTION) &&
option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) { option_->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer provides plaintext.", A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer provides plaintext.",
cuid_)); cuid_));

View File

@ -1757,6 +1757,18 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
op->setChangeOptionForReserved(true); op->setChangeOptionForReserved(true);
handlers.push_back(op); handlers.push_back(op);
} }
{
OptionHandler* op(new BooleanOptionHandler
(PREF_BT_FORCE_ENCRYPTION,
TEXT_BT_FORCE_ENCRYPTION,
A2_V_FALSE,
OptionHandler::OPT_ARG));
op->addTag(TAG_BITTORRENT);
op->setInitialOption(true);
op->setChangeGlobalOption(true);
op->setChangeOptionForReserved(true);
handlers.push_back(op);
}
{ {
OptionHandler* op(new NumberOptionHandler OptionHandler* op(new NumberOptionHandler
(PREF_BT_KEEP_ALIVE_INTERVAL, (PREF_BT_KEEP_ALIVE_INTERVAL,

View File

@ -96,7 +96,9 @@ bool ReceiverMSEHandshakeCommand::executeInternal()
sequence_ = RECEIVER_WAIT_KEY; sequence_ = RECEIVER_WAIT_KEY;
break; break;
case MSEHandshake::HANDSHAKE_LEGACY: { case MSEHandshake::HANDSHAKE_LEGACY: {
if(getDownloadEngine()->getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)){ const auto option = getDownloadEngine()->getOption();
if(option->getAsBool(PREF_BT_FORCE_ENCRYPTION) ||
option->getAsBool(PREF_BT_REQUIRE_CRYPTO)){
throw DL_ABORT_EX throw DL_ABORT_EX
("The legacy BitTorrent handshake is not acceptable by the" ("The legacy BitTorrent handshake is not acceptable by the"
" preference."); " preference.");

View File

@ -549,6 +549,7 @@ PrefPtr PREF_BT_EXCLUDE_TRACKER = makePref("bt-exclude-tracker");
PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE = PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE =
makePref("bt-remove-unselected-file"); makePref("bt-remove-unselected-file");
PrefPtr PREF_BT_DETACH_SEED_ONLY = makePref("bt-detach-seed-only"); PrefPtr PREF_BT_DETACH_SEED_ONLY = makePref("bt-detach-seed-only");
PrefPtr PREF_BT_FORCE_ENCRYPTION = makePref("bt-force-encryption");
/** /**
* Metalink related preferences * Metalink related preferences

View File

@ -486,6 +486,8 @@ extern PrefPtr PREF_BT_EXCLUDE_TRACKER;
extern PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE; extern PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE;
// values: true |false // values: true |false
extern PrefPtr PREF_BT_DETACH_SEED_ONLY; extern PrefPtr PREF_BT_DETACH_SEED_ONLY;
// values: true | false
extern PrefPtr PREF_BT_FORCE_ENCRYPTION;
/** /**
* Metalink related preferences * Metalink related preferences

View File

@ -1013,3 +1013,11 @@
" recognized as active download in RPC method.") " recognized as active download in RPC method.")
#define TEXT_MIN_TLS_VERSION \ #define TEXT_MIN_TLS_VERSION \
_(" --min-tls-version=VERSION Specify minimum SSL/TLS version to enable.") _(" --min-tls-version=VERSION Specify minimum SSL/TLS version to enable.")
#define TEXT_BT_FORCE_ENCRYPTION \
_(" --bt-force-encryption[=true|false]\n" \
" Requires BitTorrent message payload encryption\n" \
" with arc4. This is a shorthand of\n" \
" --bt-requre-crypto --bt-min-crypto-level=arc4.\n" \
" If true is given, deny legacy BitTorrent\n" \
" handshake and only use Obfuscation handshake and\n" \
" always encrypt message payload.")