2008-02-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

Added --bt-min-crypto-level and --bt-require-crypto options.
	* src/OptionHandlerFactory.cc
	* src/MSEHandshake.cc
	* src/HelpItemFactory.cc
	* src/option_processing.cc
	* src/ReceiverMSEHandshakeCommand.cc
	* src/prefs.h
	* src/DefaultBtAnnounce.cc
	* src/InitiatorMSEHandshakeCommand.cc
	* src/usage_text.h
	* test/MSEHandshakeTest.cc
pull/1/head
Tatsuhiro Tsujikawa 2008-02-18 13:41:58 +00:00
parent c37539eb25
commit 20cd2e5246
13 changed files with 236 additions and 20 deletions

View File

@ -1,3 +1,17 @@
2008-02-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Added --bt-min-crypto-level and --bt-require-crypto options.
* src/OptionHandlerFactory.cc
* src/MSEHandshake.cc
* src/HelpItemFactory.cc
* src/option_processing.cc
* src/ReceiverMSEHandshakeCommand.cc
* src/prefs.h
* src/DefaultBtAnnounce.cc
* src/InitiatorMSEHandshakeCommand.cc
* src/usage_text.h
* test/MSEHandshakeTest.cc
2008-02-18 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Bump version number to 0.13.0b

View File

@ -51,6 +51,7 @@
#include "BtRuntime.h"
#include "PeerStorage.h"
#include "Peer.h"
#include "Option.h"
namespace aria2 {
@ -160,7 +161,11 @@ std::string DefaultBtAnnounce::getAnnounceUrl() {
url += std::string("&")+"trackerid="+Util::torrentUrlencode((const unsigned char*)trackerId.c_str(),
trackerId.size());
}
url += "&supportcrypto=1";
if(option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
url += "&requirecrypto=1";
} else {
url += "&supportcrypto=1";
}
return url;
}

View File

@ -351,6 +351,16 @@ TagContainerHandle HelpItemFactory::createHelpItems()
item->addTag(TAG_BITTORRENT);
tc->addItem(item);
}
{
HelpItemHandle item = new HelpItem(PREF_BT_MIN_CRYPTO_LEVEL, TEXT_BT_MIN_CRYPTO_LEVEL, V_PLAIN);
item->addTag(TAG_BITTORRENT);
tc->addItem(item);
}
{
HelpItemHandle item = new HelpItem(PREF_BT_REQUIRE_CRYPTO, TEXT_BT_REQUIRE_CRYPTO, V_FALSE);
item->addTag(TAG_BITTORRENT);
tc->addItem(item);
}
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
{

View File

@ -145,17 +145,34 @@ bool InitiatorMSEHandshakeCommand::executeInternal() {
bool InitiatorMSEHandshakeCommand::prepareForNextPeer(int32_t wait)
{
// try legacy BitTorrent handshake if preference allows it.
// TODO preference is not created yet.
logger->info("CUID#%d - Retry using legacy BitTorrent handshake.", cuid);
Command* command =
new PeerInitiateConnectionCommand(cuid, _requestGroup, peer, e, btContext,
false);
e->commands.push_back(command);
return true;
if(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
logger->info("CUID#%d - Establishing connection using legacy BitTorrent handshake is disabled by preference.", cuid);
if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) {
SharedHandle<Peer> peer = peerStorage->getUnusedPeer();
peer->usedBy(CUIDCounterSingletonHolder::instance()->newID());
Command* command =
new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e,
btContext);
e->commands.push_back(command);
}
return true;
} else {
// try legacy BitTorrent handshake
logger->info("CUID#%d - Retry using legacy BitTorrent handshake.", cuid);
Command* command =
new PeerInitiateConnectionCommand(cuid, _requestGroup, peer, e, btContext,
false);
e->commands.push_back(command);
return true;
}
}
void InitiatorMSEHandshakeCommand::onAbort(Exception* ex) {}
void InitiatorMSEHandshakeCommand::onAbort(Exception* ex)
{
if(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
peerStorage->returnPeer(peer);
}
}
bool InitiatorMSEHandshakeCommand::exitBeforeExecute()
{

View File

@ -48,6 +48,8 @@
#include "Util.h"
#include "BtRegistry.h"
#include "BtContext.h"
#include "prefs.h"
#include "Option.h"
#include <cstring>
#include <cassert>
@ -256,7 +258,10 @@ void MSEHandshake::sendInitiatorStep2()
// crypto_provide
unsigned char cryptoProvide[4];
memset(cryptoProvide, 0, sizeof(cryptoProvide));
cryptoProvide[3] = CRYPTO_PLAIN_TEXT | CRYPTO_ARC4;
if(_option->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
cryptoProvide[3] = CRYPTO_PLAIN_TEXT;
}
cryptoProvide[3] |= CRYPTO_ARC4;
memcpy(buffer+8, cryptoProvide, sizeof(cryptoProvide));
// len(padC)
@ -328,7 +333,8 @@ bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength()
unsigned char cryptoSelect[CRYPTO_BITFIELD_LENGTH];
_decryptor->decrypt(cryptoSelect, sizeof(cryptoSelect),
rbufptr, sizeof(cryptoSelect));
if(cryptoSelect[3]&CRYPTO_PLAIN_TEXT) {
if(cryptoSelect[3]&CRYPTO_PLAIN_TEXT &&
_option->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
_logger->debug("CUID#%d - peer prefers plaintext.", _cuid);
_negotiatedCryptoType = CRYPTO_PLAIN_TEXT;
}
@ -440,11 +446,11 @@ bool MSEHandshake::receiveReceiverHashAndPadCLength()
rbufptr, sizeof(cryptoProvide));
// TODO choose the crypto type based on the preference.
// For now, choose ARC4.
if(cryptoProvide[3]&CRYPTO_PLAIN_TEXT) {
if(cryptoProvide[3]&CRYPTO_PLAIN_TEXT &&
_option->get(PREF_BT_MIN_CRYPTO_LEVEL) == V_PLAIN) {
_logger->debug("CUID#%d - peer provides plaintext.", _cuid);
_negotiatedCryptoType = CRYPTO_PLAIN_TEXT;
}
if(cryptoProvide[3]&CRYPTO_ARC4) {
} else if(cryptoProvide[3]&CRYPTO_ARC4) {
_logger->debug("CUID#%d - peer provides ARC4.", _cuid);
_negotiatedCryptoType = CRYPTO_ARC4;
}
@ -476,6 +482,9 @@ bool MSEHandshake::receiveReceiverIALength()
bool MSEHandshake::receiveReceiverIA()
{
if(_iaLength == 0) {
return true;
}
int32_t r = _iaLength-_rbufLength;
if(r > receiveNBytes(r)) {
return false;

View File

@ -119,6 +119,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
PREF_DHT_ENTRY_POINT_HOST,
PREF_DHT_ENTRY_POINT_PORT));
handlers.push_back(new NumberOptionHandler(PREF_STOP, 0, 35000000));
handlers.push_back(new ParameterOptionHandler(PREF_BT_MIN_CRYPTO_LEVEL, V_PLAIN, V_ARC4));
handlers.push_back(new BooleanOptionHandler(PREF_BT_REQUIRE_CRYPTO));
return handlers;
}

View File

@ -86,6 +86,9 @@ bool ReceiverMSEHandshakeCommand::executeInternal()
_sequence = RECEIVER_WAIT_KEY;
break;
case MSEHandshake::HANDSHAKE_LEGACY: {
if(e->option->getAsBool(PREF_BT_REQUIRE_CRYPTO)) {
throw new DlAbortEx("The legacy BitTorrent handshake is not acceptable by the preference.");
}
Command* c = new PeerReceiveHandshakeCommand(cuid, peer, e, socket);
e->commands.push_back(c);
return true;

View File

@ -140,6 +140,8 @@ Option* option_processing(int argc, char* const argv[])
op->put(PREF_ENABLE_DHT, V_FALSE);
op->put(PREF_DHT_LISTEN_PORT, "6881-6999");
op->put(PREF_DHT_FILE_PATH, Util::getHomeDir()+"/.aria2/dht.dat");
op->put(PREF_BT_MIN_CRYPTO_LEVEL, V_PLAIN);
op->put(PREF_BT_REQUIRE_CRYPTO, V_FALSE);
// following options are not parsed by OptionHandler and not stored in Option.
bool noConf = false;
@ -221,6 +223,8 @@ Option* option_processing(int argc, char* const argv[])
{ "enable-dht", optional_argument, &lopt, 27 },
{ "dht-listen-port", required_argument, &lopt, 28 },
{ "dht-entry-point", required_argument, &lopt, 29 },
{ PREF_BT_MIN_CRYPTO_LEVEL, required_argument, &lopt, 30 },
{ PREF_BT_REQUIRE_CRYPTO, required_argument, &lopt, 31 },
#endif // ENABLE_BITTORRENT
#ifdef ENABLE_METALINK
{ "metalink-file", required_argument, NULL, 'M' },
@ -325,6 +329,12 @@ Option* option_processing(int argc, char* const argv[])
case 29:
cmdstream << PREF_DHT_ENTRY_POINT << "=" << optarg << "\n";
break;
case 30:
cmdstream << PREF_BT_MIN_CRYPTO_LEVEL << "=" << optarg << "\n";
break;
case 31:
cmdstream << PREF_BT_REQUIRE_CRYPTO << "=" << optarg << "\n";
break;
case 100:
cmdstream << PREF_METALINK_VERSION << "=" << optarg << "\n";
break;

View File

@ -228,6 +228,12 @@
#define PREF_DHT_ENTRY_POINT "dht-entry-point"
// values: a string
#define PREF_DHT_FILE_PATH "dht-file-path"
// values: plain | arc4
#define PREF_BT_MIN_CRYPTO_LEVEL "bt-min-crypto-level"
# define V_PLAIN "plain"
# define V_ARC4 "arc4"
// values:: true | false
#define PREF_BT_REQUIRE_CRYPTO "bt-require-crypto"
/**
* Metalink related preferences

View File

@ -267,6 +267,15 @@ _(" --dht-listen-port... Set UDP listening port for DHT.\n"\
#define TEXT_DHT_ENTRY_POINT \
_(" --dht-entry-point=HOST:PORT Set host and port as an entry point to DHT\n"\
" network.")
#define TEXT_BT_MIN_CRYPTO_LEVEL \
_(" --bt-min-crypto-level=plain|arc4 Set minimum level of encryption method.\n"\
" If several encryption methods are provided by a\n"\
" peer, aria2 chooses a lowest one which satisfies\n"\
" given level.")
#define TEXT_BT_REQUIRE_CRYPTO \
_(" --bt-require-crypto=true|false If true is given, aria2 doesn't accept and\n"\
" establish connection with legacy BitTorrent\n"\
" handshake. Thus always use Obfuscation handshake.")
#define TEXT_METALINK_FILE \
_(" -M, --metalink-file=METALINK_FILE The file path to the .metalink file.")
#define TEXT_METALINK_SERVERS \

127
test/MSEHandshakeTest.cc Normal file
View File

@ -0,0 +1,127 @@
#include "MSEHandshake.h"
#include "Exception.h"
#include "Util.h"
#include "prefs.h"
#include "Socket.h"
#include "Option.h"
#include "BtRegistry.h"
#include "MockBtContext.h"
#include "FileEntry.h"
#include <cppunit/extensions/HelperMacros.h>
namespace aria2 {
class MSEHandshakeTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(MSEHandshakeTest);
CPPUNIT_TEST(testHandshake);
CPPUNIT_TEST_SUITE_END();
private:
SharedHandle<MockBtContext> _btctx;
void doHandshake(const SharedHandle<MSEHandshake>& initiator,
const SharedHandle<MSEHandshake>& receiver);
public:
void setUp()
{
_btctx = new MockBtContext();
unsigned char infoHash[20];
memset(infoHash, 0, sizeof(infoHash));
_btctx->setInfoHash(infoHash);
BtRegistry::unregisterAll();
BtRegistry::registerBtContext(_btctx->getInfoHashAsString(), _btctx);
}
void tearDown()
{
BtRegistry::unregisterAll();
}
void testHandshake();
};
CPPUNIT_TEST_SUITE_REGISTRATION(MSEHandshakeTest);
static std::pair<SocketCore*, SocketCore*> createSocketPair()
{
SocketCore* initiatorSock = new SocketCore();
SocketCore receiverServerSock;
receiverServerSock.bind(0);
receiverServerSock.beginListen();
std::pair<std::string, int32_t> receiverAddrInfo;
receiverServerSock.getAddrInfo(receiverAddrInfo);
initiatorSock->establishConnection("127.0.0.1", receiverAddrInfo.second);
initiatorSock->setBlockingMode();
SocketCore* receiverSock = receiverServerSock.acceptConnection();
receiverSock->setBlockingMode();
return std::pair<SocketCore*, SocketCore*>(initiatorSock, receiverSock);
}
void MSEHandshakeTest::doHandshake(const SharedHandle<MSEHandshake>& initiator, const SharedHandle<MSEHandshake>& receiver)
{
initiator->sendPublicKey();
while(!receiver->receivePublicKey());
receiver->sendPublicKey();
while(!initiator->receivePublicKey());
initiator->initCipher(_btctx->getInfoHash());
initiator->sendInitiatorStep2();
while(!receiver->findReceiverHashMarker());
while(!receiver->receiveReceiverHashAndPadCLength());
while(!receiver->receivePad());
while(!receiver->receiveReceiverIALength());
while(!receiver->receiveReceiverIA());
receiver->sendReceiverStep2();
while(!initiator->findInitiatorVCMarker());
while(!initiator->receiveInitiatorCryptoSelectAndPadDLength());
while(!initiator->receivePad());
}
static MSEHandshake* createMSEHandshake(SocketCore* socket, bool initiator, const Option* option)
{
MSEHandshake* h = new MSEHandshake(1, socket, option);
h->initEncryptionFacility(initiator);
return h;
}
void MSEHandshakeTest::testHandshake()
{
{
Option op;
op.put(PREF_BT_MIN_CRYPTO_LEVEL, V_PLAIN);
std::pair<SocketCore*, SocketCore*> sockPair = createSocketPair();
SharedHandle<MSEHandshake> initiator = createMSEHandshake(sockPair.first, true, &op);
SharedHandle<MSEHandshake> receiver = createMSEHandshake(sockPair.second, false, &op);
doHandshake(initiator, receiver);
CPPUNIT_ASSERT_EQUAL(MSEHandshake::CRYPTO_PLAIN_TEXT, initiator->getNegotiatedCryptoType());
CPPUNIT_ASSERT_EQUAL(MSEHandshake::CRYPTO_PLAIN_TEXT, receiver->getNegotiatedCryptoType());
}
{
Option op;
op.put(PREF_BT_MIN_CRYPTO_LEVEL, V_ARC4);
std::pair<SocketCore*, SocketCore*> sockPair = createSocketPair();
SharedHandle<MSEHandshake> initiator = createMSEHandshake(sockPair.first, true, &op);
SharedHandle<MSEHandshake> receiver = createMSEHandshake(sockPair.second, false, &op);
doHandshake(initiator, receiver);
CPPUNIT_ASSERT_EQUAL(MSEHandshake::CRYPTO_ARC4, initiator->getNegotiatedCryptoType());
CPPUNIT_ASSERT_EQUAL(MSEHandshake::CRYPTO_ARC4, receiver->getNegotiatedCryptoType());
}
}
} // namespace aria2

View File

@ -130,7 +130,8 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
DHTRoutingTableSerializerTest.cc\
DHTRoutingTableDeserializerTest.cc\
DHKeyExchangeTest.cc\
ARC4Test.cc
ARC4Test.cc\
MSEHandshakeTest.cc
endif # ENABLE_BITTORRENT
if ENABLE_METALINK

View File

@ -115,7 +115,8 @@ check_PROGRAMS = $(am__EXEEXT_1)
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializerTest.cc\
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.cc\
@ENABLE_BITTORRENT_TRUE@ DHKeyExchangeTest.cc\
@ENABLE_BITTORRENT_TRUE@ ARC4Test.cc
@ENABLE_BITTORRENT_TRUE@ ARC4Test.cc\
@ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.cc
@ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
@ -210,8 +211,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
DHTTokenTrackerTest.cc XORCloserTest.cc DHTIDCloserTest.cc \
DHTRoutingTableSerializerTest.cc \
DHTRoutingTableDeserializerTest.cc DHKeyExchangeTest.cc \
ARC4Test.cc MetalinkerTest.cc MetalinkEntryTest.cc \
Metalink2RequestGroupTest.cc \
ARC4Test.cc MSEHandshakeTest.cc MetalinkerTest.cc \
MetalinkEntryTest.cc Metalink2RequestGroupTest.cc \
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
MetalinkParserControllerTest.cc MetalinkProcessorTest.cc
@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
@ -289,7 +290,8 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializerTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHKeyExchangeTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT)
@ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ MSEHandshakeTest.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
@ -710,6 +712,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidatorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidatorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ListTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshakeTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelperTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtilTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalink2RequestGroupTest.Po@am__quote@