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
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>`

View File

@ -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";

View File

@ -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());
}

View File

@ -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_));

View File

@ -1757,6 +1757,18 @@ std::vector<OptionHandler*> 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,

View File

@ -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.");

View File

@ -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

View File

@ -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

View File

@ -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.")