From c653c72dc84b7c5fe99f2aa189e9cf1da80a9ed5 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 12 Jan 2015 17:46:20 +0900 Subject: [PATCH] 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. --- doc/manual-src/en/aria2c.rst | 10 ++++++++++ src/DefaultBtAnnounce.cc | 3 ++- src/InitiatorMSEHandshakeCommand.cc | 4 +++- src/MSEHandshake.cc | 9 ++++++--- src/OptionHandlerFactory.cc | 12 ++++++++++++ src/ReceiverMSEHandshakeCommand.cc | 4 +++- src/prefs.cc | 1 + src/prefs.h | 2 ++ src/usage_text.h | 8 ++++++++ 9 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 003f3cef..666750d7 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -625,6 +625,15 @@ BitTorrent Specific Options tracker. Although this function is named ``external``, it can accept 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] 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-exclude-tracker <--bt-exclude-tracker>` * :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-max-peers <--bt-max-peers>` * :option:`bt-metadata-only <--bt-metadata-only>` diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc index a5a73bb0..f7d491cf 100644 --- a/src/DefaultBtAnnounce.cc +++ b/src/DefaultBtAnnounce.cc @@ -189,7 +189,8 @@ std::string DefaultBtAnnounce::getAnnounceUrl() { uri += "&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"; } else { uri += "&supportcrypto=1"; diff --git a/src/InitiatorMSEHandshakeCommand.cc b/src/InitiatorMSEHandshakeCommand.cc index c8a3681a..b91553f6 100644 --- a/src/InitiatorMSEHandshakeCommand.cc +++ b/src/InitiatorMSEHandshakeCommand.cc @@ -216,7 +216,8 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) // established. tryNewPeer(); 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" " BitTorrent handshake is disabled by preference.", getCuid())); @@ -239,6 +240,7 @@ bool InitiatorMSEHandshakeCommand::prepareForNextPeer(time_t wait) void InitiatorMSEHandshakeCommand::onAbort() { if(sequence_ == INITIATOR_SEND_KEY || + getOption()->getAsBool(PREF_BT_FORCE_ENCRYPTION) || getOption()->getAsBool(PREF_BT_REQUIRE_CRYPTO)) { peerStorage_->returnPeer(getPeer()); } diff --git a/src/MSEHandshake.cc b/src/MSEHandshake.cc index c4d3c98a..3b3f67fc 100644 --- a/src/MSEHandshake.cc +++ b/src/MSEHandshake.cc @@ -284,7 +284,8 @@ void MSEHandshake::sendInitiatorStep2() ptr += sizeof(VC); // crypto_provide 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_ARC4; @@ -347,7 +348,8 @@ bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength() //verifyCryptoSelect unsigned char* rbufptr = rbuf_; 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) { A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer prefers plaintext.", cuid_)); @@ -447,7 +449,8 @@ bool MSEHandshake::receiveReceiverHashAndPadCLength decryptor_->encrypt(CRYPTO_BITFIELD_LENGTH, rbufptr, rbufptr); // TODO choose the crypto type based on the preference. // 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) { A2_LOG_DEBUG(fmt("CUID#%" PRId64 " - peer provides plaintext.", cuid_)); diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index f2f4eec9..8542900c 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -1757,6 +1757,18 @@ std::vector OptionHandlerFactory::createOptionHandlers() op->setChangeOptionForReserved(true); 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 (PREF_BT_KEEP_ALIVE_INTERVAL, diff --git a/src/ReceiverMSEHandshakeCommand.cc b/src/ReceiverMSEHandshakeCommand.cc index f0c611d4..02205383 100644 --- a/src/ReceiverMSEHandshakeCommand.cc +++ b/src/ReceiverMSEHandshakeCommand.cc @@ -96,7 +96,9 @@ bool ReceiverMSEHandshakeCommand::executeInternal() sequence_ = RECEIVER_WAIT_KEY; break; 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 ("The legacy BitTorrent handshake is not acceptable by the" " preference."); diff --git a/src/prefs.cc b/src/prefs.cc index 2332bd57..ba8adfd2 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -549,6 +549,7 @@ PrefPtr PREF_BT_EXCLUDE_TRACKER = makePref("bt-exclude-tracker"); PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE = makePref("bt-remove-unselected-file"); PrefPtr PREF_BT_DETACH_SEED_ONLY = makePref("bt-detach-seed-only"); +PrefPtr PREF_BT_FORCE_ENCRYPTION = makePref("bt-force-encryption"); /** * Metalink related preferences diff --git a/src/prefs.h b/src/prefs.h index a4b5bfdf..75b676a8 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -486,6 +486,8 @@ extern PrefPtr PREF_BT_EXCLUDE_TRACKER; extern PrefPtr PREF_BT_REMOVE_UNSELECTED_FILE; // values: true |false extern PrefPtr PREF_BT_DETACH_SEED_ONLY; +// values: true | false +extern PrefPtr PREF_BT_FORCE_ENCRYPTION; /** * Metalink related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 1b139b13..c45480da 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -1013,3 +1013,11 @@ " recognized as active download in RPC method.") #define TEXT_MIN_TLS_VERSION \ _(" --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.")