summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog40
-rw-r--r--src/ARC4Decryptor.h45
-rw-r--r--src/ARC4Encryptor.h45
-rw-r--r--src/BtRegistry.cc5
-rw-r--r--src/BtRegistry.h2
-rw-r--r--src/DHKeyExchange.h45
-rw-r--r--src/DefaultBtAnnounce.cc1
-rw-r--r--src/HandleRegistry.h11
-rw-r--r--src/InitiatorMSEHandshakeCommand.cc165
-rw-r--r--src/InitiatorMSEHandshakeCommand.h80
-rw-r--r--src/LibgcryptARC4Context.h96
-rw-r--r--src/LibgcryptARC4Decryptor.h77
-rw-r--r--src/LibgcryptARC4Encryptor.h77
-rw-r--r--src/LibgcryptDHKeyExchange.h164
-rw-r--r--src/LibsslARC4Context.h96
-rw-r--r--src/LibsslARC4Decryptor.h77
-rw-r--r--src/LibsslARC4Encryptor.h77
-rw-r--r--src/LibsslDHKeyExchange.h171
-rw-r--r--src/MSEHandshake.cc591
-rw-r--r--src/MSEHandshake.h179
-rw-r--r--src/Makefile.am5
-rw-r--r--src/Makefile.in36
-rw-r--r--src/PeerAbstractCommand.cc4
-rw-r--r--src/PeerAbstractCommand.h1
-rw-r--r--src/PeerConnection.cc64
-rw-r--r--src/PeerConnection.h15
-rw-r--r--src/PeerInitiateConnectionCommand.cc47
-rw-r--r--src/PeerInitiateConnectionCommand.h6
-rw-r--r--src/PeerInteractionCommand.cc5
-rw-r--r--src/PeerInteractionCommand.h1
-rw-r--r--src/PeerListenCommand.cc16
-rw-r--r--src/PeerReceiveHandshakeCommand.cc11
-rw-r--r--src/PeerReceiveHandshakeCommand.h3
-rw-r--r--src/ReceiverMSEHandshakeCommand.cc157
-rw-r--r--src/ReceiverMSEHandshakeCommand.h76
-rw-r--r--src/SocketCore.h14
-rw-r--r--test/ARC4Test.cc51
-rw-r--r--test/DHKeyExchangeTest.cc52
-rw-r--r--test/DefaultBtAnnounceTest.cc38
-rw-r--r--test/Makefile.am4
-rw-r--r--test/Makefile.in15
41 files changed, 2569 insertions, 96 deletions
diff --git a/ChangeLog b/ChangeLog
index 3625f166..e0c86091 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2008-02-16 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
+
+ Added Message Stream Encryption(MSE) support.
+ Currently, aria2 accepts incoming connections with Obfuscation Header
+ and legacy BitTorrent Header and establishes connections with
+ Obfuscation Header first and if failed then retry with legacy
+ BitTorrent header. If plain text and ARC4 is provided, aria2 always
+ choose ARC4. The new option to change the default behavior is planned.
+ For tracker extension, "supportcrypto=1" is added statically.
+ * src/PeerInitiateConnectionCommand.{h, cc}
+ * src/PeerConnection.{h, cc}
+ * src/HandleRegistry.h
+ * src/SocketCore.h
+ * src/PeerReceiveHandshakeCommand.{h, cc}
+ * src/BtRegistry.{h, cc}
+ * src/PeerListenCommand.cc
+ * src/InitiatorMSEHandshakeCommand.{h, cc}
+ * src/ReceiverMSEHandshakeCommand.{h, cc}
+ * src/MSEHandshake.{h, cc}
+ * src/ARC4Encryptor.h
+ * src/ARC4Decryptor.h
+ * src/LibgcryptARC4Encryptor.h
+ * src/LibgcryptARC4Decryptor.h
+ * src/LibgcryptARC4Context.h
+ * src/LibsslARC4Encryptor.h
+ * src/LibsslARC4Decryptor.h
+ * src/LibsslARC4Context.h
+ * src/DHKeyExchange.h
+ * src/LibgcryptDHKeyExchange.h
+ * src/LibsslDHKeyExchange.h
+ * src/DefaultBtAnnounce.cc: Just added "supportcrypto=1" parameter.
+ * test/DefaultBtAnnounceTest.cc
+ * test/ARC4Test.cc
+ * test/DHKeyExchangeTest.cc
+
+ Removed prepareForRetry() because it is not used.
+ * src/PeerAbstractCommand.{h, cc}
+ * src/PeerInteractionCommand.{h, cc}
+ * src/PeerInitiateConnectionCommand.{h, cc}
+
2008-02-13 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Added the ability to load nodes from torrent file. These nodes are
diff --git a/src/ARC4Decryptor.h b/src/ARC4Decryptor.h
new file mode 100644
index 00000000..39dc25cf
--- /dev/null
+++ b/src/ARC4Decryptor.h
@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_ARC4_DECRYPTOR_H_
+#define _D_ARC4_DECRYPTOR_H_
+
+#include "common.h"
+#ifdef HAVE_LIBGCRYPT
+# include "LibgcryptARC4Decryptor.h"
+#elif HAVE_LIBSSL
+# include "LibsslARC4Decryptor.h"
+#endif // HAVE_LIBSSL
+
+#endif // _D_ARC4_DECRYPTOR_H_
diff --git a/src/ARC4Encryptor.h b/src/ARC4Encryptor.h
new file mode 100644
index 00000000..1335b493
--- /dev/null
+++ b/src/ARC4Encryptor.h
@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_ARC4_ENCRYPTOR_H_
+#define _D_ARC4_ENCRYPTOR_H_
+
+#include "common.h"
+#ifdef HAVE_LIBGCRYPT
+# include "LibgcryptARC4Encryptor.h"
+#elif HAVE_LIBSSL
+# include "LibsslARC4Encryptor.h"
+#endif // HAVE_LIBSSL
+
+#endif // _D_ARC4_ENCRYPTOR_H_
diff --git a/src/BtRegistry.cc b/src/BtRegistry.cc
index 86e9c3b2..1a9b334f 100644
--- a/src/BtRegistry.cc
+++ b/src/BtRegistry.cc
@@ -131,6 +131,11 @@ BtRegistry::registerBtContext(const std::string& key,
btContextMap.registerHandle(key, btContext);
}
+std::deque<SharedHandle<BtContext> > BtRegistry::getAllBtContext()
+{
+ return btContextMap.getAll();
+}
+
PeerObjectClusterHandle
BtRegistry::getPeerObjectCluster(const std::string& key)
{
diff --git a/src/BtRegistry.h b/src/BtRegistry.h
index 70b3f29c..2ef55d47 100644
--- a/src/BtRegistry.h
+++ b/src/BtRegistry.h
@@ -99,6 +99,8 @@ public:
static void registerBtProgressInfoFile(const std::string& key,
const SharedHandle<BtProgressInfoFile>& btProgressInfoFile);
+ static std::deque<SharedHandle<BtContext> > getAllBtContext();
+
// for PeerObject
static PeerObjectClusterHandle
getPeerObjectCluster(const std::string& key);
diff --git a/src/DHKeyExchange.h b/src/DHKeyExchange.h
new file mode 100644
index 00000000..1cd5cf96
--- /dev/null
+++ b/src/DHKeyExchange.h
@@ -0,0 +1,45 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_DH_KEY_EXCHANGE_H_
+#define _D_DH_KEY_EXCHANGE_H_
+
+#include "common.h"
+#ifdef HAVE_LIBGCRYPT
+# include "LibgcryptDHKeyExchange.h"
+#elif HAVE_LIBSSL
+# include "LibsslDHKeyExchange.h"
+#endif // HAVE_LIBSSL
+
+#endif // _D_DH_KEY_EXCHANGE_H_
diff --git a/src/DefaultBtAnnounce.cc b/src/DefaultBtAnnounce.cc
index 809a65f2..a804a476 100644
--- a/src/DefaultBtAnnounce.cc
+++ b/src/DefaultBtAnnounce.cc
@@ -160,6 +160,7 @@ std::string DefaultBtAnnounce::getAnnounceUrl() {
url += std::string("&")+"trackerid="+Util::torrentUrlencode((const unsigned char*)trackerId.c_str(),
trackerId.size());
}
+ url += "&supportcrypto=1";
return url;
}
diff --git a/src/HandleRegistry.h b/src/HandleRegistry.h
index c0747347..26ddacb3 100644
--- a/src/HandleRegistry.h
+++ b/src/HandleRegistry.h
@@ -38,6 +38,7 @@
#include "common.h"
#include "SharedHandle.h"
#include <map>
+#include <deque>
namespace aria2 {
@@ -66,6 +67,16 @@ public:
}
}
+ std::deque<SharedHandle<T> > getAll()
+ {
+ std::deque<SharedHandle<T> > l;
+ for(typename HandleMap::const_iterator itr = handleMap.begin(); itr != handleMap.end(); ++itr) {
+ const typename HandleMap::value_type& p = *itr;
+ l.push_back(p.second);
+ }
+ return l;
+ }
+
void clear() {
handleMap.clear();
}
diff --git a/src/InitiatorMSEHandshakeCommand.cc b/src/InitiatorMSEHandshakeCommand.cc
new file mode 100644
index 00000000..79c11a24
--- /dev/null
+++ b/src/InitiatorMSEHandshakeCommand.cc
@@ -0,0 +1,165 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "InitiatorMSEHandshakeCommand.h"
+#include "PeerInitiateConnectionCommand.h"
+#include "PeerInteractionCommand.h"
+#include "DownloadEngine.h"
+#include "DlAbortEx.h"
+#include "message.h"
+#include "prefs.h"
+#include "CUIDCounter.h"
+#include "Socket.h"
+#include "Logger.h"
+#include "Peer.h"
+#include "PeerConnection.h"
+#include "BtContext.h"
+#include "BtRuntime.h"
+#include "PieceStorage.h"
+#include "PeerStorage.h"
+#include "BtAnnounce.h"
+#include "BtProgressInfoFile.h"
+#include "Option.h"
+#include "MSEHandshake.h"
+#include "ARC4Encryptor.h"
+#include "ARC4Decryptor.h"
+
+namespace aria2 {
+
+InitiatorMSEHandshakeCommand::InitiatorMSEHandshakeCommand
+(int32_t cuid,
+ RequestGroup* requestGroup,
+ const SharedHandle<Peer>& p,
+ DownloadEngine* e,
+ const SharedHandle<BtContext>& btContext,
+ const SharedHandle<SocketCore>& s):
+
+ PeerAbstractCommand(cuid, p, e, s),
+ BtContextAwareCommand(btContext),
+ RequestGroupAware(requestGroup),
+ _sequence(INITIATOR_SEND_KEY),
+ _mseHandshake(new MSEHandshake(cuid, socket, e->option))
+{
+ disableReadCheckSocket();
+ setWriteCheckSocket(socket);
+ setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
+
+ btRuntime->increaseConnections();
+}
+
+InitiatorMSEHandshakeCommand::~InitiatorMSEHandshakeCommand()
+{
+ btRuntime->decreaseConnections();
+
+ delete _mseHandshake;
+}
+
+bool InitiatorMSEHandshakeCommand::executeInternal() {
+ switch(_sequence) {
+ case INITIATOR_SEND_KEY: {
+ if(!socket->isWritable(0)) {
+ break;
+ }
+ disableWriteCheckSocket();
+ setReadCheckSocket(socket);
+ socket->setBlockingMode();
+ setTimeout(e->option->getAsInt(PREF_BT_TIMEOUT));
+ _mseHandshake->initEncryptionFacility(true);
+ _mseHandshake->sendPublicKey();
+ _sequence = INITIATOR_WAIT_KEY;
+ break;
+ }
+ case INITIATOR_WAIT_KEY: {
+ if(_mseHandshake->receivePublicKey()) {
+ _mseHandshake->initCipher(btContext->getInfoHash());
+ _mseHandshake->sendInitiatorStep2();
+ _sequence = INITIATOR_FIND_VC_MARKER;
+ }
+ break;
+ }
+ case INITIATOR_FIND_VC_MARKER: {
+ if(_mseHandshake->findInitiatorVCMarker()) {
+ _sequence = INITIATOR_RECEIVE_PAD_D_LENGTH;
+ }
+ break;
+ }
+ case INITIATOR_RECEIVE_PAD_D_LENGTH: {
+ if(_mseHandshake->receiveInitiatorCryptoSelectAndPadDLength()) {
+ _sequence = INITIATOR_RECEIVE_PAD_D;
+ }
+ break;
+ }
+ case INITIATOR_RECEIVE_PAD_D: {
+ if(_mseHandshake->receivePad()) {
+ SharedHandle<PeerConnection> peerConnection =
+ new PeerConnection(cuid, socket, e->option);
+ if(_mseHandshake->getNegotiatedCryptoType() == MSEHandshake::CRYPTO_ARC4) {
+ peerConnection->enableEncryption(_mseHandshake->getEncryptor(),
+ _mseHandshake->getDecryptor());
+ }
+ Command* c =
+ new PeerInteractionCommand(cuid, _requestGroup, peer, e, btContext,
+ socket,
+ PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE,
+ peerConnection);
+ e->commands.push_back(c);
+ return true;
+ }
+ break;
+ }
+ }
+ e->commands.push_back(this);
+ return false;
+}
+
+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;
+}
+
+void InitiatorMSEHandshakeCommand::onAbort(Exception* ex) {}
+
+bool InitiatorMSEHandshakeCommand::exitBeforeExecute()
+{
+ return btRuntime->isHalt();
+}
+
+} // namespace aria2
diff --git a/src/InitiatorMSEHandshakeCommand.h b/src/InitiatorMSEHandshakeCommand.h
new file mode 100644
index 00000000..a24e04e3
--- /dev/null
+++ b/src/InitiatorMSEHandshakeCommand.h
@@ -0,0 +1,80 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_INITIATOR_MSE_HANDSHAKE_COMMAND_H_
+#define _D_INITIATOR_MSE_HANDSHAKE_COMMAND_H_
+
+#include "PeerAbstractCommand.h"
+#include "RequestGroupAware.h"
+#include "BtContextAwareCommand.h"
+
+namespace aria2 {
+
+class MSEHandshake;
+
+class InitiatorMSEHandshakeCommand : public PeerAbstractCommand,
+ public BtContextAwareCommand,
+ public RequestGroupAware
+{
+public:
+ enum Seq {
+ INITIATOR_SEND_KEY,
+ INITIATOR_WAIT_KEY,
+ INITIATOR_FIND_VC_MARKER,
+ INITIATOR_RECEIVE_PAD_D_LENGTH,
+ INITIATOR_RECEIVE_PAD_D,
+ };
+private:
+ Seq _sequence;
+ MSEHandshake* _mseHandshake;
+protected:
+ virtual bool executeInternal();
+ virtual bool prepareForNextPeer(int32_t wait);
+ virtual void onAbort(Exception* ex);
+ virtual bool exitBeforeExecute();
+public:
+ InitiatorMSEHandshakeCommand(int32_t cuid,
+ RequestGroup* requestGroup,
+ const SharedHandle<Peer>& peer,
+ DownloadEngine* e,
+ const SharedHandle<BtContext>& btContext,
+ const SharedHandle<SocketCore>& s);
+
+ virtual ~InitiatorMSEHandshakeCommand();
+
+};
+
+} // namespace aria2
+
+#endif // _D_INITIATOR_MSE_HANDSHAKE_COMMAND_H_
diff --git a/src/LibgcryptARC4Context.h b/src/LibgcryptARC4Context.h
new file mode 100644
index 00000000..7dbfa4f1
--- /dev/null
+++ b/src/LibgcryptARC4Context.h
@@ -0,0 +1,96 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBGCRYPT_ARC4_CONTEXT_H_
+#define _D_LIBGCRYPT_ARC4_CONTEXT_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include <gcrypt.h>
+
+namespace aria2 {
+
+class LibgcryptARC4Context {
+private:
+ gcry_cipher_hd_t _cipherCtx;
+
+ void handleError(gcry_error_t errno) const
+ {
+ throw new DlAbortEx("Exception in libgcrypt routine(ARC4Context class): %s",
+ gcry_strerror(errno));
+ }
+public:
+ LibgcryptARC4Context():_cipherCtx(0) {}
+
+ ~LibgcryptARC4Context()
+ {
+ gcry_cipher_close(_cipherCtx);
+ }
+
+ gcry_cipher_hd_t getCipherContext() const
+ {
+ return _cipherCtx;
+ }
+
+ void init(const unsigned char* key, size_t keyLength)
+ {
+ gcry_cipher_close(_cipherCtx);
+
+ int algo = GCRY_CIPHER_ARCFOUR;
+ int mode = GCRY_CIPHER_MODE_STREAM;
+ unsigned int flags = 0;
+ {
+ gcry_error_t r = gcry_cipher_open(&_cipherCtx, algo, mode, flags);
+ if(r) {
+ handleError(r);
+ }
+ }
+ {
+ gcry_error_t r = gcry_cipher_setkey(_cipherCtx, key, keyLength);
+ if(r) {
+ handleError(r);
+ }
+ }
+ {
+ gcry_error_t r = gcry_cipher_setiv(_cipherCtx, 0, 0);
+ if(r) {
+ handleError(r);
+ }
+ }
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBGCRYPT_ARC4_CONTEXT_H_
diff --git a/src/LibgcryptARC4Decryptor.h b/src/LibgcryptARC4Decryptor.h
new file mode 100644
index 00000000..19e362a5
--- /dev/null
+++ b/src/LibgcryptARC4Decryptor.h
@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBGCRYPT_ARC4_DECRYPTOR_H_
+#define _D_LIBGCRYPT_ARC4_DECRYPTOR_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include "LibgcryptARC4Context.h"
+#include <gcrypt.h>
+
+namespace aria2 {
+
+class ARC4Decryptor {
+private:
+ LibgcryptARC4Context _ctx;
+
+ void handleError(gcry_error_t errno) const
+ {
+ throw new DlAbortEx("Exception in libgcrypt routine(ARC4Decryptor class): %s",
+ gcry_strerror(errno));
+ }
+public:
+ ARC4Decryptor() {}
+
+ ~ARC4Decryptor() {}
+
+ void init(const unsigned char* key, size_t keyLength)
+ {
+ _ctx.init(key, keyLength);
+ }
+
+ void decrypt(unsigned char* out, size_t outLength,
+ const unsigned char* in, size_t inLength)
+ {
+ gcry_error_t r = gcry_cipher_decrypt(_ctx.getCipherContext(),
+ out, outLength, in, inLength);
+ if(r) {
+ handleError(r);
+ }
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBGCRYPT_ARC4_DECRYPTOR_H_
diff --git a/src/LibgcryptARC4Encryptor.h b/src/LibgcryptARC4Encryptor.h
new file mode 100644
index 00000000..2e0c7a16
--- /dev/null
+++ b/src/LibgcryptARC4Encryptor.h
@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBGCRYPT_ARC4_ENCRYPTOR_H_
+#define _D_LIBGCRYPT_ARC4_ENCRYPTOR_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include "LibgcryptARC4Context.h"
+#include <gcrypt.h>
+
+namespace aria2 {
+
+class ARC4Encryptor {
+private:
+ LibgcryptARC4Context _ctx;
+
+ void handleError(gcry_error_t errno) const
+ {
+ throw new DlAbortEx("Exception in libgcrypt routine(ARC4Encryptor class): %s",
+ gcry_strerror(errno));
+ }
+public:
+ ARC4Encryptor() {}
+
+ ~ARC4Encryptor() {}
+
+ void init(const unsigned char* key, size_t keyLength)
+ {
+ _ctx.init(key, keyLength);
+ }
+
+ void encrypt(unsigned char* out, size_t outLength,
+ const unsigned char* in, size_t inLength)
+ {
+ gcry_error_t r = gcry_cipher_encrypt(_ctx.getCipherContext(),
+ out, outLength, in, inLength);
+ if(r) {
+ handleError(r);
+ }
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBGCRYPT_ARC4_ENCRYPTOR_H_
diff --git a/src/LibgcryptDHKeyExchange.h b/src/LibgcryptDHKeyExchange.h
new file mode 100644
index 00000000..f1eb9cb1
--- /dev/null
+++ b/src/LibgcryptDHKeyExchange.h
@@ -0,0 +1,164 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBGCRYPT_DH_KEY_EXCHANGE_H_
+#define _D_LIBGCRYPT_DH_KEY_EXCHANGE_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include <gcrypt.h>
+
+namespace aria2 {
+
+class DHKeyExchange {
+private:
+
+ gcry_mpi_t _prime;
+
+ gcry_mpi_t _generator;
+
+ gcry_mpi_t _privateKey;
+
+ gcry_mpi_t _publicKey;
+
+ void handleError(int errno) const
+ {
+ throw new DlAbortEx("Exception in libgcrypt routine(DHKeyExchange class): %s",
+ gcry_strerror(errno));
+ }
+
+public:
+ DHKeyExchange():_prime(0),
+ _generator(0),
+ _privateKey(0),
+ _publicKey(0) {}
+
+ ~DHKeyExchange()
+ {
+ gcry_mpi_release(_prime);
+ gcry_mpi_release(_generator);
+ gcry_mpi_release(_privateKey);
+ gcry_mpi_release(_publicKey);
+ }
+
+ void init(const unsigned char* prime, const unsigned char* generator,
+ size_t privateKeyBits)
+ {
+ gcry_mpi_release(_prime);
+ gcry_mpi_release(_generator);
+ gcry_mpi_release(_privateKey);
+ {
+ gcry_error_t r = gcry_mpi_scan(&_prime, GCRYMPI_FMT_HEX,
+ prime, 0, 0);
+ if(r) {
+ handleError(r);
+ }
+ }
+ {
+ gcry_error_t r = gcry_mpi_scan(&_generator, GCRYMPI_FMT_HEX,
+ generator, 0, 0);
+ if(r) {
+ handleError(r);
+ }
+ }
+ _privateKey = gcry_mpi_new(0);
+ gcry_mpi_randomize(_privateKey, privateKeyBits, GCRY_STRONG_RANDOM);
+ }
+
+ void generatePublicKey()
+ {
+ gcry_mpi_release(_publicKey);
+ _publicKey = gcry_mpi_new(0);
+ gcry_mpi_powm(_publicKey, _generator, _privateKey, _prime);
+ }
+
+ size_t publicKeyLength() const
+ {
+ return (gcry_mpi_get_nbits(_publicKey)+7)/8;
+ }
+
+ size_t getPublicKey(unsigned char* out, size_t outLength) const
+ {
+ if(outLength < publicKeyLength()) {
+ throw new DlAbortEx("Insufficient buffer for public key. expect:%u, actual:%u",
+ publicKeyLength(), outLength);
+ }
+ size_t nwritten;
+ gcry_error_t r = gcry_mpi_print(GCRYMPI_FMT_USG, out, outLength, &nwritten, _publicKey);
+ if(r) {
+ handleError(r);
+ }
+ return nwritten;
+ }
+
+ void generateNonce(unsigned char* out, size_t outLength) const
+ {
+ gcry_create_nonce(out, outLength);
+ }
+
+ size_t computeSecret(unsigned char* out, size_t outLength,
+ const unsigned char* peerPublicKeyData,
+ size_t peerPublicKeyLength) const
+ {
+ if(outLength < publicKeyLength()) {
+ throw new DlAbortEx("Insufficient buffer for secret. expect:%u, actual:%u",
+ publicKeyLength(), outLength);
+ }
+ gcry_mpi_t peerPublicKey;
+ {
+ gcry_error_t r = gcry_mpi_scan(&peerPublicKey, GCRYMPI_FMT_USG, peerPublicKeyData,
+ peerPublicKeyLength, 0);
+ if(r) {
+ handleError(r);
+ }
+ }
+ gcry_mpi_t secret = gcry_mpi_new(0);
+ gcry_mpi_powm(secret, peerPublicKey, _privateKey, _prime);
+ gcry_mpi_release(peerPublicKey);
+
+ size_t nwritten;
+ {
+ gcry_error_t r = gcry_mpi_print(GCRYMPI_FMT_USG, out, outLength, &nwritten, secret);
+ gcry_mpi_release(secret);
+ if(r) {
+ handleError(r);
+ }
+ }
+ return nwritten;
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBGCRYPT_DH_KEY_EXCHANGE_H_
diff --git a/src/LibsslARC4Context.h b/src/LibsslARC4Context.h
new file mode 100644
index 00000000..27200c19
--- /dev/null
+++ b/src/LibsslARC4Context.h
@@ -0,0 +1,96 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBSSL_ARC4_CONTEXT_H_
+#define _D_LIBSSL_ARC4_CONTEXT_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+namespace aria2 {
+
+class LibsslARC4Context {
+private:
+ EVP_CIPHER_CTX* _cipherCtx;
+
+ void handleError() const
+ {
+ throw new DlAbortEx("Exception in libssl routine(ARC4Context class): %s",
+ ERR_error_string(ERR_get_error(), 0));
+ }
+public:
+ LibsslARC4Context():_cipherCtx(0) {}
+
+ ~LibsslARC4Context()
+ {
+ if(_cipherCtx) {
+ EVP_CIPHER_CTX_cleanup(_cipherCtx);
+ }
+ delete _cipherCtx;
+ }
+
+ EVP_CIPHER_CTX* getCipherContext() const
+ {
+ return _cipherCtx;
+ }
+
+ // enc == 1: encryption
+ // enc == 0: decryption
+ void init(const unsigned char* key, size_t keyLength, int enc)
+ {
+ if(_cipherCtx) {
+ EVP_CIPHER_CTX_cleanup(_cipherCtx);
+ }
+ delete _cipherCtx;
+ _cipherCtx = new EVP_CIPHER_CTX;
+ EVP_CIPHER_CTX_init(_cipherCtx);
+
+ if(!EVP_CipherInit_ex(_cipherCtx, EVP_rc4(), 0, 0, 0, enc)) {
+ handleError();
+ }
+ if(!EVP_CIPHER_CTX_set_key_length(_cipherCtx, keyLength)) {
+ handleError();
+ }
+ if(!EVP_CipherInit_ex(_cipherCtx, 0, 0, key, 0, -1)) {
+ handleError();
+ }
+ }
+
+};
+
+} // namespace aria2
+
+#endif // _D_LIBSSL_ARC4_CONTEXT_H_
diff --git a/src/LibsslARC4Decryptor.h b/src/LibsslARC4Decryptor.h
new file mode 100644
index 00000000..e51808c0
--- /dev/null
+++ b/src/LibsslARC4Decryptor.h
@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBSSL_ARC4_DECRYPTOR_H_
+#define _D_LIBSSL_ARC4_DECRYPTOR_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include "LibsslARC4Context.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+namespace aria2 {
+
+class ARC4Decryptor {
+private:
+ LibsslARC4Context _ctx;
+
+ void handleError() const
+ {
+ throw new DlAbortEx("Exception in libssl routine(ARC4Decryptor class): %s",
+ ERR_error_string(ERR_get_error(), 0));
+ }
+public:
+ ARC4Decryptor() {}
+
+ ~ARC4Decryptor() {}
+
+ void init(const unsigned char* key, size_t keyLength)
+ {
+ _ctx.init(key, keyLength, 0);
+ }
+
+ void decrypt(unsigned char* out, size_t outLength,
+ const unsigned char* in, size_t inLength)
+ {
+ int soutLength = outLength;
+ if(!EVP_CipherUpdate(_ctx.getCipherContext(), out, &soutLength, in, inLength)) {
+ handleError();
+ }
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBSSL_ARC4_DECRYPTOR_H_
diff --git a/src/LibsslARC4Encryptor.h b/src/LibsslARC4Encryptor.h
new file mode 100644
index 00000000..49b8d5dc
--- /dev/null
+++ b/src/LibsslARC4Encryptor.h
@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBSSL_ARC4_ENCRYPTOR_H_
+#define _D_LIBSSL_ARC4_ENCRYPTOR_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include "LibsslARC4Context.h"
+#include <openssl/evp.h>
+#include <openssl/err.h>
+
+namespace aria2 {
+
+class ARC4Encryptor {
+private:
+ LibsslARC4Context _ctx;
+
+ void handleError() const
+ {
+ throw new DlAbortEx("Exception in libssl routine(ARC4Encryptor class): %s",
+ ERR_error_string(ERR_get_error(), 0));
+ }
+public:
+ ARC4Encryptor() {}
+
+ ~ARC4Encryptor() {}
+
+ void init(const unsigned char* key, size_t keyLength)
+ {
+ _ctx.init(key, keyLength, 1);
+ }
+
+ void encrypt(unsigned char* out, size_t outLength,
+ const unsigned char* in, size_t inLength)
+ {
+ int soutLength = outLength;
+ if(!EVP_CipherUpdate(_ctx.getCipherContext(), out, &soutLength, in, inLength)) {
+ handleError();
+ }
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBSSL_ARC4_ENCRYPTOR_H_
diff --git a/src/LibsslDHKeyExchange.h b/src/LibsslDHKeyExchange.h
new file mode 100644
index 00000000..1f311d15
--- /dev/null
+++ b/src/LibsslDHKeyExchange.h
@@ -0,0 +1,171 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_LIBSSL_DH_KEY_EXCHANGE_H_
+#define _D_LIBSSL_DH_KEY_EXCHANGE_H_
+
+#include "common.h"
+#include "DlAbortEx.h"
+#include <openssl/dh.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+
+namespace aria2 {
+
+class DHKeyExchange {
+private:
+
+ BN_CTX* _bnCtx;
+
+ BIGNUM* _prime;
+
+ BIGNUM* _generator;
+
+ BIGNUM* _privateKey;
+
+ BIGNUM* _publicKey;
+
+ void handleError() const
+ {
+ throw new DlAbortEx("Exception in libssl routine(DHKeyExchange class): %s",
+ ERR_error_string(ERR_get_error(), 0));
+ }
+
+public:
+ DHKeyExchange():_bnCtx(0),
+ _prime(0),
+ _generator(0),
+ _privateKey(0),
+ _publicKey(0) {}
+
+ ~DHKeyExchange()
+ {
+ BN_CTX_free(_bnCtx);
+ BN_free(_prime);
+ BN_free(_generator);
+ BN_free(_privateKey);
+ BN_free(_publicKey);
+ }
+
+ void init(const unsigned char* prime, const unsigned char* generator,
+ size_t privateKeyBits)
+ {
+ BN_CTX_free(_bnCtx);
+ _bnCtx = BN_CTX_new();
+ if(!_bnCtx) {
+ handleError();
+ }
+
+ BN_free(_prime);
+ _prime = 0;
+ BN_free(_generator);
+ _generator = 0;
+ BN_free(_privateKey);
+ _privateKey = 0;
+
+ if(BN_hex2bn(&_prime, reinterpret_cast<const char*>(prime)) == 0) {
+ handleError();
+ }
+ if(BN_hex2bn(&_generator, reinterpret_cast<const char*>(generator)) == 0) {
+ handleError();
+ }
+ _privateKey = BN_new();
+ if(!BN_rand(_privateKey, privateKeyBits, -1, false)) {
+ handleError();
+ }
+ }
+
+ void generatePublicKey()
+ {
+ BN_free(_publicKey);
+ _publicKey = BN_new();
+ BN_mod_exp(_publicKey, _generator, _privateKey, _prime, _bnCtx);
+ }
+
+ size_t publicKeyLength() const
+ {
+ return BN_num_bytes(_publicKey);
+ }
+
+ size_t getPublicKey(unsigned char* out, size_t outLength) const
+ {
+ if(outLength < publicKeyLength()) {
+ throw new DlAbortEx("Insufficient buffer for public key. expect:%u, actual:%u",
+ publicKeyLength(), outLength);
+ }
+ size_t nwritten = BN_bn2bin(_publicKey, out);
+ if(!nwritten) {
+ handleError();
+ }
+ return nwritten;
+ }
+
+ void generateNonce(unsigned char* out, size_t outLength) const
+ {
+ if(!RAND_bytes(out, outLength)) {
+ handleError();
+ }
+ }
+
+ size_t computeSecret(unsigned char* out, size_t outLength,
+ const unsigned char* peerPublicKeyData,
+ size_t peerPublicKeyLength) const
+ {
+ if(outLength < publicKeyLength()) {
+ throw new DlAbortEx("Insufficient buffer for secret. expect:%u, actual:%u",
+ publicKeyLength(), outLength);
+ }
+
+
+ BIGNUM* peerPublicKey = BN_bin2bn(peerPublicKeyData, peerPublicKeyLength, 0);
+ if(!peerPublicKey) {
+ handleError();
+ }
+
+ BIGNUM* secret = BN_new();
+ BN_mod_exp(secret, peerPublicKey, _privateKey, _prime, _bnCtx);
+ BN_free(peerPublicKey);
+
+ size_t nwritten = BN_bn2bin(secret, out);
+ BN_free(secret);
+ if(!nwritten) {
+ handleError();
+ }
+ return nwritten;
+ }
+};
+
+} // namespace aria2
+
+#endif // _D_LIBSSL_DH_KEY_EXCHANGE_H_
diff --git a/src/MSEHandshake.cc b/src/MSEHandshake.cc
new file mode 100644
index 00000000..63752643
--- /dev/null
+++ b/src/MSEHandshake.cc
@@ -0,0 +1,591 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "MSEHandshake.h"
+#include "message.h"
+#include "DlAbortEx.h"
+#include "LogFactory.h"
+#include "Logger.h"
+#include "BtHandshakeMessage.h"
+#include "Socket.h"
+#include "a2netcompat.h"
+#include "DHKeyExchange.h"
+#include "ARC4Encryptor.h"
+#include "ARC4Decryptor.h"
+#include "MessageDigestHelper.h"
+#include "SimpleRandomizer.h"
+#include "Util.h"
+#include "BtRegistry.h"
+#include "BtContext.h"
+#include <cstring>
+#include <cassert>
+
+namespace aria2 {
+
+const unsigned char* MSEHandshake::PRIME = reinterpret_cast<const unsigned char*>("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563");
+
+const unsigned char* MSEHandshake::GENERATOR = reinterpret_cast<const unsigned char*>("2");
+
+const unsigned char MSEHandshake::VC[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+MSEHandshake::MSEHandshake(int32_t cuid,
+ const SocketHandle& socket,
+ const Option* op):
+ _cuid(cuid),
+ _socket(socket),
+ _option(op),
+ _logger(LogFactory::getInstance()),
+ _rbufLength(0),
+ _negotiatedCryptoType(CRYPTO_NONE),
+ _dh(0),
+ _encryptor(0),
+ _decryptor(0),
+ _initiator(true),
+ _markerIndex(0),
+ _padLength(0),
+ _iaLength(0),
+ _ia(0)
+{}
+
+MSEHandshake::~MSEHandshake()
+{
+ delete _dh;
+ delete [] _ia;
+}
+
+MSEHandshake::HANDSHAKE_TYPE MSEHandshake::identifyHandshakeType()
+{
+ if(!_socket->isReadable(0)) {
+ return HANDSHAKE_NOT_YET;
+ }
+ int32_t bufLength = 20;
+ _socket->peekData(_rbuf, bufLength);
+ if(bufLength != 20) {
+ return HANDSHAKE_NOT_YET;
+ }
+ if(_rbuf[0] == BtHandshakeMessage::PSTR_LENGTH &&
+ memcmp(BtHandshakeMessage::BT_PSTR, _rbuf+1, 19) == 0) {
+ _logger->debug("CUID#%d - This is legacy BitTorrent handshake.", _cuid);
+ return HANDSHAKE_LEGACY;
+ } else {
+ _logger->debug("CUID#%d - This may be encrypted BitTorrent handshake.", _cuid);
+ return HANDSHAKE_ENCRYPTED;
+ }
+}
+
+void MSEHandshake::initEncryptionFacility(bool initiator)
+{
+ delete _dh;
+ _dh = new DHKeyExchange();
+ _dh->init(PRIME, GENERATOR, 160);
+ _dh->generatePublicKey();
+ _logger->debug("CUID#%d - DH initialized.", _cuid);
+
+ _initiator = initiator;
+}
+
+void MSEHandshake::sendPublicKey()
+{
+ _logger->debug("CUID#%d - Sending public key.", _cuid);
+ unsigned char buffer[KEY_LENGTH+MAX_PAD_LENGTH];
+ _dh->getPublicKey(buffer, KEY_LENGTH);
+
+ size_t padLength = SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
+ _dh->generateNonce(buffer+KEY_LENGTH, padLength);
+ _socket->writeData(buffer, KEY_LENGTH+padLength);
+}
+
+bool MSEHandshake::receivePublicKey()
+{
+ int32_t r = KEY_LENGTH-_rbufLength;
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ _logger->debug("CUID#%d - public key received.", _cuid);
+ // TODO handle exception. in catch, resbufLength = 0;
+ _dh->computeSecret(_secret, sizeof(_secret), _rbuf, _rbufLength);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+void MSEHandshake::initCipher(const unsigned char* infoHash)
+{
+ memcpy(_infoHash, infoHash, INFO_HASH_LENGTH);
+ //Initialize cipher
+ unsigned char s[4+KEY_LENGTH+INFO_HASH_LENGTH];
+ memcpy(s, _initiator?"keyA":"keyB", 4);
+ memcpy(s+4, _secret, KEY_LENGTH);
+ memcpy(s+4+KEY_LENGTH, infoHash, INFO_HASH_LENGTH);
+
+ unsigned char localCipherKey[20];
+ MessageDigestHelper::digest(localCipherKey, sizeof(localCipherKey), "sha1",
+ s, sizeof(s));
+ _encryptor = new ARC4Encryptor();
+ _encryptor->init(localCipherKey, sizeof(localCipherKey));
+
+ unsigned char peerCipherKey[20];
+ memcpy(s, _initiator?"keyB":"keyA", 4);
+ MessageDigestHelper::digest(peerCipherKey, sizeof(peerCipherKey), "sha1",
+ s, sizeof(s));
+ _decryptor = new ARC4Decryptor();
+ _decryptor->init(peerCipherKey, sizeof(peerCipherKey));
+
+ // discard first 1024 bytes ARC4 output.
+ unsigned char from[1024];
+ unsigned char to[1024];
+ _encryptor->encrypt(to, 1024, from, 1024);
+ _decryptor->decrypt(to, 1024, from, 1024);
+
+ if(_initiator) {
+ ARC4Encryptor enc;
+ enc.init(peerCipherKey, sizeof(peerCipherKey));
+ // discard first 1024 bytes ARC4 output.
+ enc.encrypt(to, 1024, from, 1024);
+ enc.encrypt(_initiatorVCMarker, sizeof(_initiatorVCMarker), VC, sizeof(VC));
+ }
+}
+
+ssize_t MSEHandshake::readDataAndDecrypt(unsigned char* data, size_t length)
+{
+ unsigned char temp[MAX_BUFFER_LENGTH];
+ assert(MAX_BUFFER_LENGTH >= length);
+ int32_t rlength = length;
+ _socket->readData(temp, rlength);
+ _decryptor->decrypt(data, rlength, temp, rlength);
+ return rlength;
+}
+
+void MSEHandshake::encryptAndSendData(const unsigned char* data, size_t length)
+{
+ unsigned char temp[4096];
+ const unsigned char* dptr = data;
+ size_t s;
+ size_t r = length;
+ while(r > 0) {
+ s = r > sizeof(temp)?sizeof(temp):r;
+ _encryptor->encrypt(temp, s, dptr, s);
+ _socket->writeData(temp, s);
+ dptr += s;
+ r -= s;
+ }
+}
+
+void MSEHandshake::createReq1Hash(unsigned char* md) const
+{
+ unsigned char buffer[100];
+ memcpy(buffer, "req1", 4);
+ memcpy(buffer+4, _secret, KEY_LENGTH);
+ MessageDigestHelper::digest(md, 20, "sha1", buffer, 4+KEY_LENGTH);
+}
+
+void MSEHandshake::createReq23Hash(unsigned char* md, const unsigned char* infoHash) const
+{
+ unsigned char x[24];
+ memcpy(x, "req2", 4);
+ memcpy(x+4, infoHash, INFO_HASH_LENGTH);
+ unsigned char xh[20];
+ MessageDigestHelper::digest(xh, sizeof(xh), "sha1", x, sizeof(x));
+
+ unsigned char y[4+96];
+ memcpy(y, "req3", 4);
+ memcpy(y+4, _secret, KEY_LENGTH);
+ unsigned char yh[20];
+ MessageDigestHelper::digest(yh, sizeof(yh), "sha1", y, sizeof(y));
+
+ for(size_t i = 0; i < 20; ++i) {
+ md[i] = xh[i]^yh[i];
+ }
+}
+
+uint16_t MSEHandshake::decodeLength16(const unsigned char* buffer)
+{
+ uint16_t be;
+ _decryptor->decrypt(reinterpret_cast<unsigned char*>(&be),
+ sizeof(be),
+ buffer, sizeof(be));
+ return ntohs(be);
+}
+
+void MSEHandshake::sendInitiatorStep2()
+{
+ _logger->debug("CUID#%d - Sending negotiation step2.", _cuid);
+ unsigned char md[20];
+ createReq1Hash(md);
+ _socket->writeData(md, sizeof(md));
+
+ createReq23Hash(md, _infoHash);
+ _socket->writeData(md, sizeof(md));
+
+ {
+ unsigned char buffer[8+4+2+MAX_PAD_LENGTH+2];
+
+ // VC
+ memcpy(buffer, VC, sizeof(VC));
+ // crypto_provide
+ unsigned char cryptoProvide[4];
+ memset(cryptoProvide, 0, sizeof(cryptoProvide));
+ cryptoProvide[3] = CRYPTO_PLAIN_TEXT | CRYPTO_ARC4;
+ memcpy(buffer+8, cryptoProvide, sizeof(cryptoProvide));
+
+ // len(padC)
+ uint16_t padCLength = SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
+ {
+ uint16_t padCLengthBE = htons(padCLength);
+ memcpy(buffer+8+4, &padCLengthBE, sizeof(padCLengthBE));
+ }
+ // padC
+ memset(buffer+8+4+2, 0, padCLength);
+ // len(IA)
+ // currently, IA is zero-length.
+ uint16_t iaLength = 0;
+ {
+ uint16_t iaLengthBE = htons(iaLength);
+ memcpy(buffer+8+4+2+padCLength, &iaLengthBE, sizeof(iaLengthBE));
+ }
+ encryptAndSendData(buffer, 8+4+2+padCLength+2);
+ }
+}
+
+// This function reads exactly until the end of VC marker is reached.
+bool MSEHandshake::findInitiatorVCMarker()
+{
+ // 616 is synchronization point of initiator
+ int32_t r = 616-KEY_LENGTH-_rbufLength;
+ if(!_socket->isReadable(0)) {
+ return false;
+ }
+ _socket->peekData(_rbuf+_rbufLength, r);
+ if(r == 0) {
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ // find vc
+ {
+ std::string buf(&_rbuf[0], &_rbuf[_rbufLength+r]);
+ std::string vc(&_initiatorVCMarker[0], &_initiatorVCMarker[VC_LENGTH]);
+ if((_markerIndex = buf.find(vc)) == std::string::npos) {
+ if(616-KEY_LENGTH <= _rbufLength+r) {
+ throw new DlAbortEx("Failed to find VC marker.");
+ } else {
+ _socket->readData(_rbuf+_rbufLength, r);
+ _rbufLength += r;
+ return false;
+ }
+ }
+ }
+ assert(_markerIndex+VC_LENGTH-_rbufLength <= (size_t)r);
+ int32_t toRead = _markerIndex+VC_LENGTH-_rbufLength;
+ _socket->readData(_rbuf+_rbufLength, toRead);
+ _rbufLength += toRead;
+
+ _logger->debug("CUID#%d - VC marker found at %u", _cuid, _markerIndex);
+ verifyVC(_rbuf+_markerIndex);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::receiveInitiatorCryptoSelectAndPadDLength()
+{
+ int32_t r = CRYPTO_BITFIELD_LENGTH+2/* PadD length*/-_rbufLength;
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ //verifyCryptoSelect
+ unsigned char* rbufptr = _rbuf;
+ {
+ unsigned char cryptoSelect[CRYPTO_BITFIELD_LENGTH];
+ _decryptor->decrypt(cryptoSelect, sizeof(cryptoSelect),
+ rbufptr, sizeof(cryptoSelect));
+ if(cryptoSelect[3]&CRYPTO_PLAIN_TEXT) {
+ _logger->debug("CUID#%d - peer prefers plaintext.", _cuid);
+ _negotiatedCryptoType = CRYPTO_PLAIN_TEXT;
+ }
+ if(cryptoSelect[3]&CRYPTO_ARC4) {
+ _logger->debug("CUID#%d - peer prefers ARC4", _cuid);
+ _negotiatedCryptoType = CRYPTO_ARC4;
+ }
+ if(_negotiatedCryptoType == CRYPTO_NONE) {
+ throw new DlAbortEx("CUID#%d - No supported crypto type selected.", _cuid);
+ }
+ }
+ // padD length
+ rbufptr += CRYPTO_BITFIELD_LENGTH;
+ _padLength = verifyPadLength(rbufptr, "PadD");
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::receivePad()
+{
+ if(_padLength == 0) {
+ return true;
+ }
+ int32_t r = _padLength-_rbufLength;
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ unsigned char temp[MAX_PAD_LENGTH];
+ _decryptor->decrypt(temp, _padLength, _rbuf, _padLength);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::findReceiverHashMarker()
+{
+ // 628 is synchronization limit of receiver.
+ int32_t r = 628-KEY_LENGTH-_rbufLength;
+ if(!_socket->isReadable(0)) {
+ return false;
+ }
+ _socket->peekData(_rbuf+_rbufLength, r);
+ if(r == 0) {
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ // find hash('req1', S), S is _secret.
+ {
+ std::string buf(&_rbuf[0], &_rbuf[_rbufLength+r]);
+ unsigned char md[20];
+ createReq1Hash(md);
+ std::string req1(&md[0], &md[sizeof(md)]);
+ if((_markerIndex = buf.find(req1)) == std::string::npos) {
+ if(628-KEY_LENGTH <= _rbufLength+r) {
+ throw new DlAbortEx("Failed to find hash marker.");
+ } else {
+ _socket->readData(_rbuf+_rbufLength, r);
+ _rbufLength += r;
+ return false;
+ }
+ }
+ }
+ assert(_markerIndex+20-_rbufLength <= (size_t)r);
+ int32_t toRead = _markerIndex+20-_rbufLength;
+ _socket->readData(_rbuf+_rbufLength, toRead);
+ _rbufLength += toRead;
+
+ _logger->debug("CUID#%d - Hash marker found at %u.", _cuid, _markerIndex);
+ verifyReq1Hash(_rbuf+_markerIndex);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::receiveReceiverHashAndPadCLength()
+{
+ int32_t r = 20+VC_LENGTH+CRYPTO_BITFIELD_LENGTH+2/*PadC length*/-_rbufLength;
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ // resolve info hash
+ std::deque<SharedHandle<BtContext> > btContexts = BtRegistry::getAllBtContext();
+ // pointing to the position of HASH('req2', SKEY) xor HASH('req3', S)
+ unsigned char* rbufptr = _rbuf;
+ SharedHandle<BtContext> btContext = 0;
+ for(std::deque<SharedHandle<BtContext> >::const_iterator i = btContexts.begin();
+ i != btContexts.end(); ++i) {
+ unsigned char md[20];
+ createReq23Hash(md, (*i)->getInfoHash());
+ if(memcmp(md, rbufptr, sizeof(md)) == 0) {
+ _logger->debug("CUID#%d - info hash found: %s", _cuid, (*i)->getInfoHashAsString().c_str());
+ btContext = *i;
+ break;
+ }
+ }
+ if(btContext.isNull()) {
+ throw new DlAbortEx("Unknown info hash.");
+ }
+ initCipher(btContext->getInfoHash());
+
+ // decrypt VC
+ rbufptr += 20;
+ verifyVC(rbufptr);
+ // decrypt crypto_provide
+ rbufptr += VC_LENGTH;
+ {
+ unsigned char cryptoProvide[4];
+ _decryptor->decrypt(cryptoProvide, sizeof(cryptoProvide),
+ rbufptr, sizeof(cryptoProvide));
+ // TODO choose the crypto type based on the preference.
+ // For now, choose ARC4.
+ if(cryptoProvide[3]&CRYPTO_PLAIN_TEXT) {
+ _logger->debug("CUID#%d - peer provides plaintext.", _cuid);
+ _negotiatedCryptoType = CRYPTO_PLAIN_TEXT;
+ }
+ if(cryptoProvide[3]&CRYPTO_ARC4) {
+ _logger->debug("CUID#%d - peer provides ARC4.", _cuid);
+ _negotiatedCryptoType = CRYPTO_ARC4;
+ }
+ if(_negotiatedCryptoType == CRYPTO_NONE) {
+ throw new DlAbortEx("CUID#%d - No supported crypto type provided.", _cuid);
+ }
+ }
+ // decrypt PadC length
+ rbufptr += CRYPTO_BITFIELD_LENGTH;
+ _padLength = verifyPadLength(rbufptr, "PadC");
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::receiveReceiverIALength()
+{
+ int32_t r = 2-_rbufLength;
+ assert(r > 0);
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ _iaLength = decodeLength16(_rbuf);
+ _logger->debug("CUID#%d - len(IA)=%u.", _cuid, _iaLength);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+bool MSEHandshake::receiveReceiverIA()
+{
+ int32_t r = _iaLength-_rbufLength;
+ if(r > receiveNBytes(r)) {
+ return false;
+ }
+ delete [] _ia;
+ _ia = new unsigned char[_iaLength];
+ _decryptor->decrypt(_ia, _iaLength, _rbuf, _iaLength);
+ _logger->debug("CUID#%d - IA received.", _cuid);
+ // reset _rbufLength
+ _rbufLength = 0;
+ return true;
+}
+
+void MSEHandshake::sendReceiverStep2()
+{
+ unsigned char buffer[8+4+2+MAX_PAD_LENGTH];
+ // VC
+ memcpy(buffer, VC, sizeof(VC));
+ // crypto_select
+ unsigned char cryptoSelect[4];
+ memset(cryptoSelect, 0, sizeof(cryptoSelect));
+ cryptoSelect[3] = _negotiatedCryptoType;
+ memcpy(buffer+8, cryptoSelect, sizeof(cryptoSelect));
+ // len(padD)
+ uint16_t padDLength = SimpleRandomizer::getInstance()->getRandomNumber(MAX_PAD_LENGTH+1);
+ {
+ uint16_t padDLengthBE = htons(padDLength);
+ memcpy(buffer+8+4, &padDLengthBE, sizeof(padDLengthBE));
+ }
+ // padD, all zeroed
+ memset(buffer+8+4+2, 0, padDLength);
+ encryptAndSendData(buffer, 8+4+2+padDLength);
+}
+
+uint16_t MSEHandshake::verifyPadLength(const unsigned char* padlenbuf, const std::string& padName)
+{
+ _logger->debug("CUID#%d - Veryfying Pad length for %s", _cuid, padName.c_str());
+
+ uint16_t padLength = decodeLength16(padlenbuf);
+ _logger->debug("CUID#%d - len(%s)=%u", _cuid, padName.c_str(), padLength);
+ if(padLength > 512) {
+ throw new DlAbortEx("Too large %s length: %u", padName.c_str(), padLength);
+ }
+ return padLength;
+}
+
+void MSEHandshake::verifyVC(const unsigned char* vcbuf)
+{
+ _logger->debug("CUID#%d - Veryfying VC.", _cuid);
+ unsigned char vc[VC_LENGTH];
+ _decryptor->decrypt(vc, sizeof(vc), vcbuf, sizeof(vc));
+ if(memcmp(VC, vc, sizeof(VC)) != 0) {
+ throw new DlAbortEx("Invalid VC: %s", Util::toHex(vc, VC_LENGTH).c_str());
+ }
+}
+
+void MSEHandshake::verifyReq1Hash(const unsigned char* req1buf)
+{
+ _logger->debug("CUID#%d - Verifying req hash.", _cuid);
+ unsigned char md[20];
+ createReq1Hash(md);
+ if(memcmp(md, req1buf, sizeof(md)) != 0) {
+ throw new DlAbortEx("Invalid req1 hash found.");
+ }
+}
+
+ssize_t MSEHandshake::receiveNBytes(size_t bytes)
+{
+ int32_t r = bytes;
+ if(r > 0) {
+ if(!_socket->isReadable(0)) {
+ return 0;
+ }
+ _socket->readData(_rbuf+_rbufLength, r);
+ if(r == 0) {
+ throw new DlAbortEx(EX_EOF_FROM_PEER);
+ }
+ _rbufLength += r;
+ }
+ return r;
+}
+
+const unsigned char* MSEHandshake::getIA() const
+{
+ return _ia;
+}
+
+size_t MSEHandshake::getIALength() const
+{
+ return _iaLength;
+}
+
+const unsigned char* MSEHandshake::getInfoHash() const
+{
+ return _infoHash;
+}
+
+MSEHandshake::CRYPTO_TYPE MSEHandshake::getNegotiatedCryptoType() const
+{
+ return _negotiatedCryptoType;
+}
+
+SharedHandle<ARC4Encryptor> MSEHandshake::getEncryptor() const
+{
+ return _encryptor;
+}
+
+SharedHandle<ARC4Decryptor> MSEHandshake::getDecryptor() const
+{
+ return _decryptor;
+}
+
+} // namespace aria2
diff --git a/src/MSEHandshake.h b/src/MSEHandshake.h
new file mode 100644
index 00000000..4017186f
--- /dev/null
+++ b/src/MSEHandshake.h
@@ -0,0 +1,179 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_MSE_HANDSHAKE_H_
+#define _D_MSE_HANDSHAKE_H_
+
+#include "common.h"
+#include "SharedHandle.h"
+#include "BtConstants.h"
+
+namespace aria2 {
+
+class Option;
+class Logger;
+class SocketCore;
+class DHKeyExchange;
+class ARC4Encryptor;
+class ARC4Decryptor;
+
+class MSEHandshake {
+public:
+ enum HANDSHAKE_TYPE {
+ HANDSHAKE_NOT_YET = 0,
+ HANDSHAKE_LEGACY,
+ HANDSHAKE_ENCRYPTED
+ };
+
+ enum CRYPTO_TYPE {
+ CRYPTO_NONE = 0,
+ CRYPTO_PLAIN_TEXT = 0x01,
+ CRYPTO_ARC4 = 0x02
+ };
+
+private:
+ static const size_t PRIME_BITS = 768;
+
+ static const size_t KEY_LENGTH = (PRIME_BITS+7)/8;
+
+ static const size_t MAX_PAD_LENGTH = 512;
+
+ static const size_t VC_LENGTH = 8;
+
+ static const size_t CRYPTO_BITFIELD_LENGTH = 4;
+
+ static const size_t MAX_BUFFER_LENGTH = 6*1024;
+
+ int32_t _cuid;
+ SharedHandle<SocketCore> _socket;
+ const Option* _option;
+ const Logger* _logger;
+
+ unsigned char _rbuf[MAX_BUFFER_LENGTH];
+ size_t _rbufLength;
+
+ CRYPTO_TYPE _negotiatedCryptoType;
+ DHKeyExchange* _dh;
+ SharedHandle<ARC4Encryptor> _encryptor;
+ SharedHandle<ARC4Decryptor> _decryptor;
+ unsigned char _infoHash[INFO_HASH_LENGTH];
+ unsigned char _secret[KEY_LENGTH];
+ bool _initiator;
+ unsigned char _initiatorVCMarker[VC_LENGTH];
+ size_t _markerIndex;
+ uint16_t _padLength;
+ uint16_t _iaLength;
+ unsigned char* _ia;
+
+ static const unsigned char* PRIME;
+
+ static const unsigned char* GENERATOR;
+
+ static const unsigned char VC[VC_LENGTH];
+
+ ssize_t readDataAndDecrypt(unsigned char* data, size_t length);
+
+ void encryptAndSendData(const unsigned char* data, size_t length);
+
+ void createReq1Hash(unsigned char* md) const;
+
+ void createReq23Hash(unsigned char* md, const unsigned char* infoHash) const;
+
+ uint16_t decodeLength16(const unsigned char* buffer);
+
+ uint16_t decodeLength16(const char* buffer)
+ {
+ return decodeLength16(reinterpret_cast<const unsigned char*>(buffer));
+ }
+
+ uint16_t verifyPadLength(const unsigned char* padlenbuf,
+ const std::string& padName);
+
+ void verifyVC(const unsigned char* vcbuf);
+
+ void verifyReq1Hash(const unsigned char* req1buf);
+
+ ssize_t receiveNBytes(size_t bytes);
+
+public:
+ MSEHandshake(int32_t cuid, const SharedHandle<SocketCore>& socket,
+ const Option* op);
+
+ ~MSEHandshake();
+
+ HANDSHAKE_TYPE identifyHandshakeType();
+
+ void initEncryptionFacility(bool initiator);
+
+ void sendPublicKey();
+
+ bool receivePublicKey();
+
+ void initCipher(const unsigned char* infoHash);
+
+ void sendInitiatorStep2();
+
+ bool findInitiatorVCMarker();
+
+ bool receiveInitiatorCryptoSelectAndPadDLength();
+
+ bool receivePad();
+
+ bool findReceiverHashMarker();
+
+ bool receiveReceiverHashAndPadCLength();
+
+ bool receiveReceiverIALength();
+
+ bool receiveReceiverIA();
+
+ void sendReceiverStep2();
+
+ // returns plain text IA
+ const unsigned char* getIA() const;
+
+ size_t getIALength() const;
+
+ const unsigned char* getInfoHash() const;
+
+ CRYPTO_TYPE getNegotiatedCryptoType() const;
+
+ SharedHandle<ARC4Encryptor> getEncryptor() const;
+
+ SharedHandle<ARC4Decryptor> getDecryptor() const;
+};
+
+} // namespace aria2
+
+#endif // _D_MSE_HANDSHAKE_H_
diff --git a/src/Makefile.am b/src/Makefile.am
index 3d6770e2..82e2b8a3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -310,7 +310,10 @@ SRCS += MetaEntry.h\
DHTRoutingTableSerializer.cc\
DHTRoutingTableDeserializer.cc\
DHTAutoSaveCommand.cc\
- DHTRegistry.cc
+ DHTRegistry.cc\
+ InitiatorMSEHandshakeCommand.cc\
+ ReceiverMSEHandshakeCommand.cc\
+ MSEHandshake.cc
endif # ENABLE_BITTORRENT
if ENABLE_METALINK
diff --git a/src/Makefile.in b/src/Makefile.in
index 9aa9c76a..cfff1640 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -188,7 +188,10 @@ bin_PROGRAMS = aria2c$(EXEEXT)
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializer.cc\
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializer.cc\
@ENABLE_BITTORRENT_TRUE@ DHTAutoSaveCommand.cc\
-@ENABLE_BITTORRENT_TRUE@ DHTRegistry.cc
+@ENABLE_BITTORRENT_TRUE@ DHTRegistry.cc\
+@ENABLE_BITTORRENT_TRUE@ InitiatorMSEHandshakeCommand.cc\
+@ENABLE_BITTORRENT_TRUE@ ReceiverMSEHandshakeCommand.cc\
+@ENABLE_BITTORRENT_TRUE@ MSEHandshake.cc
@ENABLE_METALINK_TRUE@am__append_3 = Metalinker.cc Metalinker.h\
@ENABLE_METALINK_TRUE@ MetalinkEntry.cc MetalinkEntry.h\
@@ -440,17 +443,18 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
DHTBucketRefreshCommand.cc DHTPeerAnnounceCommand.cc \
DHTReplaceNodeTask.cc DHTEntryPointNameResolveCommand.cc \
DHTRoutingTableSerializer.cc DHTRoutingTableDeserializer.cc \
- DHTAutoSaveCommand.cc DHTRegistry.cc Metalinker.cc \
- Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
- MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
- MetalinkProcessorFactory.cc MetalinkParserController.cc \
- MetalinkParserStateMachine.cc InitialMetalinkParserState.cc \
- MetalinkMetalinkParserState.cc FilesMetalinkParserState.cc \
- FileMetalinkParserState.cc SizeMetalinkParserState.cc \
- VersionMetalinkParserState.cc LanguageMetalinkParserState.cc \
- OSMetalinkParserState.cc VerificationMetalinkParserState.cc \
- HashMetalinkParserState.cc PiecesMetalinkParserState.cc \
- PieceHashMetalinkParserState.cc \
+ DHTAutoSaveCommand.cc DHTRegistry.cc \
+ InitiatorMSEHandshakeCommand.cc ReceiverMSEHandshakeCommand.cc \
+ MSEHandshake.cc Metalinker.cc Metalinker.h MetalinkEntry.cc \
+ MetalinkEntry.h MetalinkResource.cc MetalinkResource.h \
+ MetalinkProcessor.h MetalinkProcessorFactory.cc \
+ MetalinkParserController.cc MetalinkParserStateMachine.cc \
+ InitialMetalinkParserState.cc MetalinkMetalinkParserState.cc \
+ FilesMetalinkParserState.cc FileMetalinkParserState.cc \
+ SizeMetalinkParserState.cc VersionMetalinkParserState.cc \
+ LanguageMetalinkParserState.cc OSMetalinkParserState.cc \
+ VerificationMetalinkParserState.cc HashMetalinkParserState.cc \
+ PiecesMetalinkParserState.cc PieceHashMetalinkParserState.cc \
ResourcesMetalinkParserState.cc URLMetalinkParserState.cc \
FinMetalinkParserState.cc SkipTagMetalinkParserState.cc \
Metalink2RequestGroup.cc Metalink2RequestGroup.h \
@@ -571,7 +575,10 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializer.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializer.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTAutoSaveCommand.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ DHTRegistry.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@ DHTRegistry.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ InitiatorMSEHandshakeCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ ReceiverMSEHandshakeCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ MSEHandshake.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = Metalinker.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntry.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkResource.$(OBJEXT) \
@@ -1267,11 +1274,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/HttpResponseCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitialMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiateConnectionCommandFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/InitiatorMSEHandshakeCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChecksumValidator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IteratableChunkChecksumValidator.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LanguageMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/List.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MSEHandshake.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MemoryBufferPreDownloadHandler.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MessageDigestHelper.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@
@@ -1315,6 +1324,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PiecesMetalinkParserState.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Platform.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RealtimeCommand.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ReceiverMSEHandshakeCommand.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Request.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroup.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RequestGroupAware.Po@am__quote@
diff --git a/src/PeerAbstractCommand.cc b/src/PeerAbstractCommand.cc
index 6ec06fd2..a3793843 100644
--- a/src/PeerAbstractCommand.cc
+++ b/src/PeerAbstractCommand.cc
@@ -106,10 +106,6 @@ bool PeerAbstractCommand::prepareForNextPeer(int32_t wait) {
return true;
}
-bool PeerAbstractCommand::prepareForRetry(int32_t wait) {
- return true;
-}
-
void PeerAbstractCommand::disableReadCheckSocket() {
if(checkSocketIsReadable) {
e->deleteSocketForReadCheck(readCheckTarget, this);
diff --git a/src/PeerAbstractCommand.h b/src/PeerAbstractCommand.h
index e75fd954..4e532ada 100644
--- a/src/PeerAbstractCommand.h
+++ b/src/PeerAbstractCommand.h
@@ -57,7 +57,6 @@ protected:
void setTimeout(int32_t timeout) { this->timeout = timeout; }
virtual bool prepareForNextPeer(int32_t wait);
- virtual bool prepareForRetry(int32_t wait);
virtual void onAbort(Exception* ex) {};
virtual bool exitBeforeExecute() = 0;
virtual bool executeInternal() = 0;
diff --git a/src/PeerConnection.cc b/src/PeerConnection.cc
index 83c6737d..e528ec1c 100644
--- a/src/PeerConnection.cc
+++ b/src/PeerConnection.cc
@@ -40,7 +40,11 @@
#include "BtHandshakeMessage.h"
#include "Socket.h"
#include "a2netcompat.h"
+#include "ARC4Encryptor.h"
+#include "ARC4Decryptor.h"
#include <cstring>
+#include <cassert>
+#include <algorithm>
namespace aria2 {
@@ -53,7 +57,10 @@ PeerConnection::PeerConnection(int32_t cuid,
logger(LogFactory::getInstance()),
resbufLength(0),
currentPayloadLength(0),
- lenbufLength(0)
+ lenbufLength(0),
+ _encryptionEnabled(false),
+ _encryptor(0),
+ _decryptor(0)
{}
PeerConnection::~PeerConnection() {}
@@ -62,7 +69,7 @@ int32_t PeerConnection::sendMessage(const unsigned char* data, int32_t dataLengt
int32_t writtenLength = 0;
if(socket->isWritable(0)) {
// TODO fix this
- socket->writeData((const char*)data, dataLength);
+ sendData(data, dataLength, _encryptionEnabled);
writtenLength += dataLength;
}
return writtenLength;
@@ -76,7 +83,7 @@ bool PeerConnection::receiveMessage(unsigned char* data, int32_t& dataLength) {
// read payload size, 32bit unsigned integer
int32_t remaining = 4-lenbufLength;
int32_t temp = remaining;
- socket->readData(lenbuf+lenbufLength, remaining);
+ readData(lenbuf+lenbufLength, remaining, _encryptionEnabled);
if(remaining == 0) {
// we got EOF
logger->debug("CUID#%d - In PeerConnection::receiveMessage(), remain=%d",
@@ -101,7 +108,7 @@ bool PeerConnection::receiveMessage(unsigned char* data, int32_t& dataLength) {
int32_t remaining = currentPayloadLength-resbufLength;
int32_t temp = remaining;
if(remaining > 0) {
- socket->readData(resbuf+resbufLength, remaining);
+ readData(resbuf+resbufLength, remaining, _encryptionEnabled);
if(remaining == 0) {
// we got EOF
logger->debug("CUID#%d - In PeerConnection::receiveMessage(), payloadlen=%d, remaining=%d",
@@ -132,7 +139,7 @@ bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength,
bool retval = true;
if(remaining > 0) {
int32_t temp = remaining;
- socket->readData(resbuf+resbufLength, remaining);
+ readData(resbuf+resbufLength, remaining, _encryptionEnabled);
if(remaining == 0) {
// we got EOF
logger->debug("CUID#%d - In PeerConnection::receiveHandshake(), remain=%d",
@@ -153,4 +160,51 @@ bool PeerConnection::receiveHandshake(unsigned char* data, int32_t& dataLength,
return retval;
}
+void PeerConnection::readData(char* data, int32_t& length, bool encryption)
+{
+ if(encryption) {
+ unsigned char* cdata = reinterpret_cast<unsigned char*>(data);
+ unsigned char temp[MAX_PAYLOAD_LEN];
+ assert(MAX_PAYLOAD_LEN >= length);
+ socket->readData(temp, length);
+ _decryptor->decrypt(cdata, length, temp, length);
+ } else {
+ socket->readData(data, length);
+ }
+}
+
+void PeerConnection::sendData(const unsigned char* data, size_t length, bool encryption)
+{
+ if(encryption) {
+ unsigned char temp[4096];
+ const unsigned char* dptr = data;
+ size_t r = length;
+ while(r > 0) {
+ size_t s = std::min(r, sizeof(temp));
+ _encryptor->encrypt(temp, s, dptr, s);
+ socket->writeData(temp, s);
+ dptr += s;
+ r -= s;
+ }
+ } else {
+ socket->writeData(data, length);
+ }
+}
+
+void PeerConnection::enableEncryption(const SharedHandle<ARC4Encryptor>& encryptor,
+ const SharedHandle<ARC4Decryptor>& decryptor)
+{
+ _encryptor = encryptor;
+ _decryptor = decryptor;
+
+ _encryptionEnabled = true;
+}
+
+void PeerConnection::presetBuffer(const unsigned char* data, size_t length)
+{
+ size_t nwrite = std::min((size_t)MAX_PAYLOAD_LEN, length);
+ memcpy(resbuf, data, nwrite);
+ resbufLength = length;
+}
+
} // namespace aria2
diff --git a/src/PeerConnection.h b/src/PeerConnection.h
index 5f254600..5dad0fca 100644
--- a/src/PeerConnection.h
+++ b/src/PeerConnection.h
@@ -43,6 +43,8 @@ namespace aria2 {
class Option;
class Logger;
class SocketCore;
+class ARC4Encryptor;
+class ARC4Decryptor;
// we assume maximum length of incoming message is "piece" message with 16KB
// data. Messages beyond that size are dropped.
@@ -61,6 +63,14 @@ private:
char lenbuf[4];
int32_t lenbufLength;
+ bool _encryptionEnabled;
+ SharedHandle<ARC4Encryptor> _encryptor;
+ SharedHandle<ARC4Decryptor> _decryptor;
+
+ void readData(char* data, int32_t& length, bool encryption);
+
+ void sendData(const unsigned char* data, size_t length, bool encryption);
+
public:
PeerConnection(int32_t cuid, const SharedHandle<SocketCore>& socket, const Option* op);
@@ -78,6 +88,11 @@ public:
* is assigned to 'length'.
*/
bool receiveHandshake(unsigned char* data, int32_t& dataLength, bool peek = false);
+
+ void enableEncryption(const SharedHandle<ARC4Encryptor>& encryptor,
+ const SharedHandle<ARC4Decryptor>& decryptor);
+
+ void presetBuffer(const unsigned char* data, size_t length);
};
typedef SharedHandle<PeerConnection> PeerConnectionHandle;
diff --git a/src/PeerInitiateConnectionCommand.cc b/src/PeerInitiateConnectionCommand.cc
index 500e9acb..498af65e 100644
--- a/src/PeerInitiateConnectionCommand.cc
+++ b/src/PeerInitiateConnectionCommand.cc
@@ -33,8 +33,9 @@
*/
/* copyright --> */
#include "PeerInitiateConnectionCommand.h"
-#include "DownloadEngine.h"
+#include "InitiatorMSEHandshakeCommand.h"
#include "PeerInteractionCommand.h"
+#include "DownloadEngine.h"
#include "DlAbortEx.h"
#include "message.h"
#include "prefs.h"
@@ -56,10 +57,12 @@ PeerInitiateConnectionCommand::PeerInitiateConnectionCommand(int cuid,
RequestGroup* requestGroup,
const PeerHandle& peer,
DownloadEngine* e,
- const BtContextHandle& btContext)
+ const BtContextHandle& btContext,
+ bool mseHandshakeEnabled)
:PeerAbstractCommand(cuid, peer, e),
BtContextAwareCommand(btContext),
- RequestGroupAware(requestGroup)
+ RequestGroupAware(requestGroup),
+ _mseHandshakeEnabled(mseHandshakeEnabled)
{
btRuntime->increaseConnections();
}
@@ -70,19 +73,19 @@ PeerInitiateConnectionCommand::~PeerInitiateConnectionCommand()
}
bool PeerInitiateConnectionCommand::executeInternal() {
- Command* command;
logger->info(MSG_CONNECTING_TO_SERVER, cuid, peer->ipaddr.c_str(),
peer->port);
socket->establishConnection(peer->ipaddr, peer->port);
- command =
- new PeerInteractionCommand(cuid,
- _requestGroup,
- peer,
- e,
- btContext,
- socket,
- PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE);
-
+ Command* command;
+ if(_mseHandshakeEnabled) {
+ command =
+ new InitiatorMSEHandshakeCommand(cuid, _requestGroup, peer, e, btContext,
+ socket);
+ } else {
+ command =
+ new PeerInteractionCommand(cuid, _requestGroup, peer, e, btContext, socket,
+ PeerInteractionCommand::INITIATOR_SEND_HANDSHAKE);
+ }
e->commands.push_back(command);
return true;
}
@@ -92,28 +95,14 @@ bool PeerInitiateConnectionCommand::prepareForNextPeer(int wait) {
if(peerStorage->isPeerAvailable() && btRuntime->lessThanEqMinPeer()) {
PeerHandle peer = peerStorage->getUnusedPeer();
peer->usedBy(CUIDCounterSingletonHolder::instance()->newID());
- PeerInitiateConnectionCommand* command =
- new PeerInitiateConnectionCommand(peer->usedBy(),
- _requestGroup,
- peer,
- e,
+ Command* command =
+ new PeerInitiateConnectionCommand(peer->usedBy(), _requestGroup, peer, e,
btContext);
e->commands.push_back(command);
}
return true;
}
-bool PeerInitiateConnectionCommand::prepareForRetry(int wait) {
- PeerInitiateConnectionCommand* command =
- new PeerInitiateConnectionCommand(cuid,
- _requestGroup,
- peer,
- e,
- btContext);
- e->commands.push_back(command);
- return true;
-}
-
void PeerInitiateConnectionCommand::onAbort(Exception* ex) {
peerStorage->returnPeer(peer);
}
diff --git a/src/PeerInitiateConnectionCommand.h b/src/PeerInitiateConnectionCommand.h
index a3e22ecc..413d2273 100644
--- a/src/PeerInitiateConnectionCommand.h
+++ b/src/PeerInitiateConnectionCommand.h
@@ -45,9 +45,10 @@ class PeerInitiateConnectionCommand : public PeerAbstractCommand,
public BtContextAwareCommand,
public RequestGroupAware
{
+private:
+ bool _mseHandshakeEnabled;
protected:
virtual bool executeInternal();
- virtual bool prepareForRetry(int wait);
virtual bool prepareForNextPeer(int wait);
virtual void onAbort(Exception* ex);
virtual bool exitBeforeExecute();
@@ -57,7 +58,8 @@ public:
RequestGroup* requestGroup,
const SharedHandle<Peer>& peer,
DownloadEngine* e,
- const SharedHandle<BtContext>& btContext);
+ const SharedHandle<BtContext>& btContext,
+ bool mseHandshakeEnabled = true);
virtual ~PeerInitiateConnectionCommand();
};
diff --git a/src/PeerInteractionCommand.cc b/src/PeerInteractionCommand.cc
index 1c241e39..34af2271 100644
--- a/src/PeerInteractionCommand.cc
+++ b/src/PeerInteractionCommand.cc
@@ -259,11 +259,6 @@ bool PeerInteractionCommand::prepareForNextPeer(int32_t wait) {
return true;
}
-bool PeerInteractionCommand::prepareForRetry(int32_t wait) {
- e->commands.push_back(this);
- return false;
-}
-
void PeerInteractionCommand::onAbort(Exception* ex) {
btInteractive->cancelAllPiece();
peerStorage->returnPeer(peer);
diff --git a/src/PeerInteractionCommand.h b/src/PeerInteractionCommand.h
index e27974c0..15bb4d42 100644
--- a/src/PeerInteractionCommand.h
+++ b/src/PeerInteractionCommand.h
@@ -60,7 +60,6 @@ private:
int32_t maxDownloadSpeedLimit;
protected:
virtual bool executeInternal();
- virtual bool prepareForRetry(int32_t wait);
virtual bool prepareForNextPeer(int32_t wait);
virtual void onAbort(Exception* ex);
virtual bool exitBeforeExecute();
diff --git a/src/PeerListenCommand.cc b/src/PeerListenCommand.cc
index 40ddcfa9..f7fd5e7c 100644
--- a/src/PeerListenCommand.cc
+++ b/src/PeerListenCommand.cc
@@ -39,7 +39,7 @@
#include "RecoverableException.h"
#include "CUIDCounter.h"
#include "message.h"
-#include "PeerReceiveHandshakeCommand.h"
+#include "ReceiverMSEHandshakeCommand.h"
#include "Logger.h"
#include "Socket.h"
#include <utility>
@@ -99,17 +99,19 @@ bool PeerListenCommand::execute() {
if(peerInfo.first == localInfo.first) {
continue;
}
+ // Since peerSocket may be in non-blocking mode, make it blocking mode
+ // here.
+ peerSocket->setBlockingMode();
+
PeerHandle peer = new Peer(peerInfo.first, 0);
- PeerReceiveHandshakeCommand* command =
- new PeerReceiveHandshakeCommand(CUIDCounterSingletonHolder::instance()->newID(),
- peer, e, peerSocket);
+ int32_t cuid = CUIDCounterSingletonHolder::instance()->newID();
+ Command* command =
+ new ReceiverMSEHandshakeCommand(cuid, peer, e, peerSocket);
e->commands.push_back(command);
logger->debug("Accepted the connection from %s:%u.",
peer->ipaddr.c_str(),
peer->port);
- logger->debug("Added CUID#%d to receive Bt handshake.",
- command->getCuid());
-
+ logger->debug("Added CUID#%d to receive BitTorrent/MSE handshake.", cuid);
} catch(RecoverableException* ex) {
logger->debug(MSG_ACCEPT_FAILURE, ex, cuid);
delete ex;
diff --git a/src/PeerReceiveHandshakeCommand.cc b/src/PeerReceiveHandshakeCommand.cc
index 7d55fa9f..34b261de 100644
--- a/src/PeerReceiveHandshakeCommand.cc
+++ b/src/PeerReceiveHandshakeCommand.cc
@@ -55,11 +55,16 @@ namespace aria2 {
PeerReceiveHandshakeCommand::PeerReceiveHandshakeCommand(int32_t cuid,
const PeerHandle& peer,
DownloadEngine* e,
- const SocketHandle& s):
+ const SocketHandle& s,
+ const SharedHandle<PeerConnection>& peerConnection):
PeerAbstractCommand(cuid, peer, e, s),
- _peerConnection(new PeerConnection(cuid, s, e->option)),
+ _peerConnection(peerConnection),
_lowestSpeedLimit(20*1024)
-{}
+{
+ if(_peerConnection.isNull()) {
+ _peerConnection = new PeerConnection(cuid, socket, e->option);
+ }
+}
PeerReceiveHandshakeCommand::~PeerReceiveHandshakeCommand() {}
diff --git a/src/PeerReceiveHandshakeCommand.h b/src/PeerReceiveHandshakeCommand.h
index fed9049c..2ab0ab80 100644
--- a/src/PeerReceiveHandshakeCommand.h
+++ b/src/PeerReceiveHandshakeCommand.h
@@ -61,7 +61,8 @@ public:
PeerReceiveHandshakeCommand(int32_t cuid,
const SharedHandle<Peer>& peer,
DownloadEngine* e,
- const SharedHandle<SocketCore>& s);
+ const SharedHandle<SocketCore>& s,
+ const SharedHandle<PeerConnection>& peerConnection = 0);
virtual ~PeerReceiveHandshakeCommand();
diff --git a/src/ReceiverMSEHandshakeCommand.cc b/src/ReceiverMSEHandshakeCommand.cc
new file mode 100644
index 00000000..89cbcd10
--- /dev/null
+++ b/src/ReceiverMSEHandshakeCommand.cc
@@ -0,0 +1,157 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "ReceiverMSEHandshakeCommand.h"
+#include "PeerReceiveHandshakeCommand.h"
+#include "PeerConnection.h"
+#include "DownloadEngine.h"
+#include "BtHandshakeMessage.h"
+#include "DlAbortEx.h"
+#include "Peer.h"
+#include "message.h"
+#include "Socket.h"
+#include "Logger.h"
+#include "prefs.h"
+#include "Option.h"
+#include "MSEHandshake.h"
+#include "ARC4Encryptor.h"
+#include "ARC4Decryptor.h"
+
+namespace aria2 {
+
+ReceiverMSEHandshakeCommand::ReceiverMSEHandshakeCommand
+(int32_t cuid,
+ const SharedHandle<Peer>& peer,
+ DownloadEngine* e,
+ const SharedHandle<SocketCore>& s):
+
+ PeerAbstractCommand(cuid, peer, e, s),
+ _sequence(RECEIVER_IDENTIFY_HANDSHAKE),
+ _mseHandshake(new MSEHandshake(cuid, s, e->option))
+{
+ setTimeout(e->option->getAsInt(PREF_PEER_CONNECTION_TIMEOUT));
+}
+
+ReceiverMSEHandshakeCommand::~ReceiverMSEHandshakeCommand()
+{
+ delete _mseHandshake;
+}
+
+bool ReceiverMSEHandshakeCommand::exitBeforeExecute()
+{
+ return e->isHaltRequested();
+}
+
+bool ReceiverMSEHandshakeCommand::executeInternal()
+{
+ switch(_sequence) {
+ case RECEIVER_IDENTIFY_HANDSHAKE: {
+ MSEHandshake::HANDSHAKE_TYPE type = _mseHandshake->identifyHandshakeType();
+ switch(type) {
+ case MSEHandshake::HANDSHAKE_NOT_YET:
+ break;
+ case MSEHandshake::HANDSHAKE_ENCRYPTED:
+ _mseHandshake->initEncryptionFacility(false);
+ _sequence = RECEIVER_WAIT_KEY;
+ break;
+ case MSEHandshake::HANDSHAKE_LEGACY: {
+ Command* c = new PeerReceiveHandshakeCommand(cuid, peer, e, socket);
+ e->commands.push_back(c);
+ return true;
+ }
+ default:
+ throw new DlAbortEx("Not supported handshake type.");
+ }
+ break;
+ }
+ case RECEIVER_WAIT_KEY: {
+ if(_mseHandshake->receivePublicKey()) {
+ _mseHandshake->sendPublicKey();
+ _sequence = RECEIVER_FIND_HASH_MARKER;
+ }
+ break;
+ }
+ case RECEIVER_FIND_HASH_MARKER: {
+ if(_mseHandshake->findReceiverHashMarker()) {
+ _sequence = RECEIVER_RECEIVE_PAD_C_LENGTH;
+ }
+ break;
+ }
+ case RECEIVER_RECEIVE_PAD_C_LENGTH: {
+ if(_mseHandshake->receiveReceiverHashAndPadCLength()) {
+ _sequence = RECEIVER_RECEIVE_PAD_C;
+ }
+ break;
+ }
+ case RECEIVER_RECEIVE_PAD_C: {
+ if(_mseHandshake->receivePad()) {
+ _sequence = RECEIVER_RECEIVE_IA_LENGTH;
+ }
+ break;
+ }
+ case RECEIVER_RECEIVE_IA_LENGTH: {
+ if(_mseHandshake->receiveReceiverIALength()) {
+ _sequence = RECEIVER_RECEIVE_IA;
+ }
+ break;
+ }
+ case RECEIVER_RECEIVE_IA: {
+ if(_mseHandshake->receiveReceiverIA()) {
+ _mseHandshake->sendReceiverStep2();
+ SharedHandle<PeerConnection> peerConnection =
+ new PeerConnection(cuid, socket, e->option);
+ if(_mseHandshake->getNegotiatedCryptoType() == MSEHandshake::CRYPTO_ARC4) {
+ peerConnection->enableEncryption(_mseHandshake->getEncryptor(),
+ _mseHandshake->getDecryptor());
+ }
+ if(_mseHandshake->getIALength() > 0) {
+ peerConnection->presetBuffer(_mseHandshake->getIA(),
+ _mseHandshake->getIALength());
+ }
+ // TODO add _mseHandshake->getInfoHash() to PeerReceiveHandshakeCommand
+ // as a hint. If this info hash and one in BitTorrent Handshake does not
+ // match, then drop connection.
+ Command* c =
+ new PeerReceiveHandshakeCommand(cuid, peer, e, socket, peerConnection);
+ e->commands.push_back(c);
+ return true;
+ }
+ break;
+ }
+ }
+ e->commands.push_back(this);
+ return false;
+}
+
+} // namespace aria2
diff --git a/src/ReceiverMSEHandshakeCommand.h b/src/ReceiverMSEHandshakeCommand.h
new file mode 100644
index 00000000..1bfae418
--- /dev/null
+++ b/src/ReceiverMSEHandshakeCommand.h
@@ -0,0 +1,76 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_RECEIVER_MSE_HANDSHAKE_COMMAND_H_
+#define _D_RECEIVER_MSE_HANDSHAKE_COMMAND_H_
+
+#include "PeerAbstractCommand.h"
+
+namespace aria2 {
+
+class MSEHandshake;
+class SocketCore;
+class Peer;
+
+class ReceiverMSEHandshakeCommand:public PeerAbstractCommand
+{
+public:
+ enum Seq {
+ RECEIVER_IDENTIFY_HANDSHAKE,
+ RECEIVER_WAIT_KEY,
+ RECEIVER_FIND_HASH_MARKER,
+ RECEIVER_RECEIVE_PAD_C_LENGTH,
+ RECEIVER_RECEIVE_PAD_C,
+ RECEIVER_RECEIVE_IA_LENGTH,
+ RECEIVER_RECEIVE_IA
+ };
+private:
+ Seq _sequence;
+
+ MSEHandshake* _mseHandshake;
+protected:
+ virtual bool executeInternal();
+ virtual bool exitBeforeExecute();
+public:
+ ReceiverMSEHandshakeCommand(int32_t cuid,
+ const SharedHandle<Peer>& peer,
+ DownloadEngine* e,
+ const SharedHandle<SocketCore>& s);
+
+ virtual ~ReceiverMSEHandshakeCommand();
+};
+
+} // namespace aria2
+
+#endif // _D_RECEIVER_MSE_HANDSHAKE_COMMAND_H_
diff --git a/src/SocketCore.h b/src/SocketCore.h
index 992b5bb3..77f71428 100644
--- a/src/SocketCore.h
+++ b/src/SocketCore.h
@@ -180,6 +180,10 @@ public:
{
writeData(msg.c_str(), msg.size());
}
+ void writeData(const unsigned char* data, int32_t len)
+ {
+ writeData(reinterpret_cast<const char*>(data), len);
+ }
void writeData(const char* data, size_t len, const std::string& host, uint16_t port);
@@ -197,6 +201,11 @@ public:
*/
void readData(char* data, int32_t& len);
+ void readData(unsigned char* data, int32_t& len)
+ {
+ readData(reinterpret_cast<char*>(data), len);
+ }
+
ssize_t readDataFrom(char* data, size_t len, struct sockaddr* sender,
socklen_t* senderLength);
@@ -217,6 +226,11 @@ public:
*/
void peekData(char* data, int32_t& len);
+ void peekData(unsigned char* data, int32_t& len)
+ {
+ peekData(reinterpret_cast<char*>(data), len);
+ }
+
/**
* Makes this socket secure.
* If the system has not OpenSSL, then this method do nothing.
diff --git a/test/ARC4Test.cc b/test/ARC4Test.cc
new file mode 100644
index 00000000..1bab1163
--- /dev/null
+++ b/test/ARC4Test.cc
@@ -0,0 +1,51 @@
+#include "ARC4Encryptor.h"
+#include "ARC4Decryptor.h"
+#include "Exception.h"
+#include "Util.h"
+#include "DHTUtil.h"
+#include <cstring>
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace aria2 {
+
+class ARC4Test:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(ARC4Test);
+ CPPUNIT_TEST(testEncryptDecrypt);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp() {}
+
+ void tearDown() {}
+
+ void testEncryptDecrypt();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(ARC4Test);
+
+void ARC4Test::testEncryptDecrypt()
+{
+ ARC4Encryptor enc;
+ ARC4Decryptor dec;
+ const size_t LEN = 20;
+ unsigned char key[LEN];
+ memset(key, 0, LEN);
+ DHTUtil::generateRandomData(key, sizeof(key));
+ enc.init(key, sizeof(key));
+ dec.init(key, sizeof(key));
+
+ unsigned char encrypted[LEN];
+ unsigned char decrypted[LEN];
+ enc.encrypt(encrypted, LEN, key, LEN);
+ dec.decrypt(decrypted, LEN, encrypted, LEN);
+
+ CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0);
+ // once more
+ enc.encrypt(encrypted, LEN, key, LEN);
+ dec.decrypt(decrypted, LEN, encrypted, LEN);
+
+ CPPUNIT_ASSERT(memcmp(key, decrypted, LEN) == 0);
+}
+
+} // namespace aria2
diff --git a/test/DHKeyExchangeTest.cc b/test/DHKeyExchangeTest.cc
new file mode 100644
index 00000000..02479cd6
--- /dev/null
+++ b/test/DHKeyExchangeTest.cc
@@ -0,0 +1,52 @@
+#include "DHKeyExchange.h"
+#include "Exception.h"
+#include "Util.h"
+#include <cppunit/extensions/HelperMacros.h>
+
+namespace aria2 {
+
+class DHKeyExchangeTest:public CppUnit::TestFixture {
+
+ CPPUNIT_TEST_SUITE(DHKeyExchangeTest);
+ CPPUNIT_TEST(testHandshake);
+ CPPUNIT_TEST_SUITE_END();
+public:
+ void setUp() {}
+
+ void tearDown() {}
+
+ void testHandshake();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DHKeyExchangeTest);
+
+void DHKeyExchangeTest::testHandshake()
+{
+ DHKeyExchange dhA;
+ DHKeyExchange dhB;
+
+ const unsigned char* PRIME = reinterpret_cast<const unsigned char*>("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A36210000000000090563");
+
+ const unsigned char* GENERATOR = reinterpret_cast<const unsigned char*>("2");
+
+ dhA.init(PRIME, GENERATOR, 160);
+ dhB.init(PRIME, GENERATOR, 160);
+
+ dhA.generatePublicKey();
+ dhB.generatePublicKey();
+
+ unsigned char publicKeyA[96];
+ unsigned char publicKeyB[96];
+ dhA.getPublicKey(publicKeyA, sizeof(publicKeyA));
+ dhB.getPublicKey(publicKeyB, sizeof(publicKeyB));
+
+ unsigned char secretA[96];
+ unsigned char secretB[96];
+ dhA.computeSecret(secretA, sizeof(secretA), publicKeyB, sizeof(publicKeyB));
+ dhB.computeSecret(secretB, sizeof(secretB), publicKeyA, sizeof(publicKeyA));
+
+ CPPUNIT_ASSERT(memcmp(secretA, secretB, sizeof(secretA)) == 0);
+}
+
+} // namespace aria2
diff --git a/test/DefaultBtAnnounceTest.cc b/test/DefaultBtAnnounceTest.cc
index 2b1548d7..bcaa37ef 100644
--- a/test/DefaultBtAnnounceTest.cc
+++ b/test/DefaultBtAnnounceTest.cc
@@ -113,35 +113,35 @@ void DefaultBtAnnounceTest::testNoMoreAnnounce()
btAnnounce.setRandomizer(new FixedNumberRandomizer());
btAnnounce.generateKey();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceFailure();
- CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_pieceStorage->setAllDownloadFinished(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
- CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_btRuntime->setHalt(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
- CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
@@ -164,23 +164,23 @@ void DefaultBtAnnounceTest::testGetAnnounceUrl()
btAnnounce.setRandomizer(new FixedNumberRandomizer());
btAnnounce.generateKey();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_pieceStorage->setAllDownloadFinished(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_btRuntime->setHalt(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
}
void DefaultBtAnnounceTest::testIsAllAnnounceFailed()
@@ -206,11 +206,11 @@ void DefaultBtAnnounceTest::testIsAllAnnounceFailed()
btAnnounce.setRandomizer(new FixedNumberRandomizer());
btAnnounce.generateKey();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceFailure();
- CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://backup/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceFailure();
@@ -238,17 +238,17 @@ void DefaultBtAnnounceTest::testURLOrderInStoppedEvent()
btAnnounce.setRandomizer(new FixedNumberRandomizer());
btAnnounce.generateKey();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_btRuntime->setHalt(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceFailure();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=0&no_peer_id=1&port=6989&event=stopped&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
}
@@ -268,17 +268,17 @@ void DefaultBtAnnounceTest::testURLOrderInCompletedEvent()
btAnnounce.setRandomizer(new FixedNumberRandomizer());
btAnnounce.generateKey();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=started&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
_pieceStorage->setAllDownloadFinished(true);
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost1/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceFailure();
- CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed"), btAnnounce.getAnnounceUrl());
+ CPPUNIT_ASSERT_EQUAL(std::string("http://localhost2/announce?info_hash=%01%23Eg%89%ab%cd%ef%01%23Eg%89%ab%cd%ef%01%23Eg&peer_id=%2daria2%2dultrafastdltl&uploaded=1572864&downloaded=1310720&left=1572864&compact=1&key=AAAAAAAA&numwant=50&no_peer_id=1&port=6989&event=completed&supportcrypto=1"), btAnnounce.getAnnounceUrl());
btAnnounce.announceSuccess();
}
diff --git a/test/Makefile.am b/test/Makefile.am
index dda77038..64430e12 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -128,7 +128,9 @@ aria2c_SOURCES += BtAllowedFastMessageTest.cc\
XORCloserTest.cc\
DHTIDCloserTest.cc\
DHTRoutingTableSerializerTest.cc\
- DHTRoutingTableDeserializerTest.cc
+ DHTRoutingTableDeserializerTest.cc\
+ DHKeyExchangeTest.cc\
+ ARC4Test.cc
endif # ENABLE_BITTORRENT
if ENABLE_METALINK
diff --git a/test/Makefile.in b/test/Makefile.in
index f5d4e185..66d2845d 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -113,7 +113,9 @@ check_PROGRAMS = $(am__EXEEXT_1)
@ENABLE_BITTORRENT_TRUE@ XORCloserTest.cc\
@ENABLE_BITTORRENT_TRUE@ DHTIDCloserTest.cc\
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializerTest.cc\
-@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.cc
+@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.cc\
+@ENABLE_BITTORRENT_TRUE@ DHKeyExchangeTest.cc\
+@ENABLE_BITTORRENT_TRUE@ ARC4Test.cc
@ENABLE_METALINK_TRUE@am__append_3 = MetalinkerTest.cc\
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.cc\
@@ -207,8 +209,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
DHTPeerAnnounceEntryTest.cc DHTPeerAnnounceStorageTest.cc \
DHTTokenTrackerTest.cc XORCloserTest.cc DHTIDCloserTest.cc \
DHTRoutingTableSerializerTest.cc \
- DHTRoutingTableDeserializerTest.cc MetalinkerTest.cc \
- MetalinkEntryTest.cc Metalink2RequestGroupTest.cc \
+ DHTRoutingTableDeserializerTest.cc DHKeyExchangeTest.cc \
+ ARC4Test.cc MetalinkerTest.cc MetalinkEntryTest.cc \
+ Metalink2RequestGroupTest.cc \
MetalinkPostDownloadHandlerTest.cc MetalinkHelperTest.cc \
MetalinkParserControllerTest.cc MetalinkProcessorTest.cc
@ENABLE_MESSAGE_DIGEST_TRUE@am__objects_1 = \
@@ -284,7 +287,9 @@ am__aria2c_SOURCES_DIST = AllTest.cc SocketCoreTest.cc \
@ENABLE_BITTORRENT_TRUE@ XORCloserTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTIDCloserTest.$(OBJEXT) \
@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableSerializerTest.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@ DHTRoutingTableDeserializerTest.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ DHKeyExchangeTest.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@ ARC4Test.$(OBJEXT)
@ENABLE_METALINK_TRUE@am__objects_3 = MetalinkerTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ MetalinkEntryTest.$(OBJEXT) \
@ENABLE_METALINK_TRUE@ Metalink2RequestGroupTest.$(OBJEXT) \
@@ -619,6 +624,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ARC4Test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AlphaNumberDecoratorTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceListTest.Po@am__quote@
@@ -653,6 +659,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxFactoryTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParserTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHKeyExchangeTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTAnnouncePeerMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTAnnouncePeerReplyMessageTest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DHTBucketTest.Po@am__quote@