Browse Source

Merge pull request #703 from PurpleI2P/openssl

recent changes
pull/63/merge
orignal 8 years ago committed by GitHub
parent
commit
7419f992e7
  1. 28
      Crypto.cpp
  2. 11
      Crypto.h
  3. 11
      Destination.cpp
  4. 2
      Makefile
  5. 2
      SSUSession.cpp
  6. 20
      Transports.cpp
  7. 39
      TunnelEndpoint.cpp
  8. 5
      TunnelEndpoint.h
  9. 30
      Win32/installer.iss
  10. 2
      android/AndroidManifest.xml
  11. 41
      docs/usage.md
  12. 2
      version.h

28
Crypto.cpp

@ -227,10 +227,8 @@ namespace crypto
DHKeys::DHKeys (): m_IsUpdated (true) DHKeys::DHKeys (): m_IsUpdated (true)
{ {
m_DH = DH_new (); m_DH = DH_new ();
m_DH->p = BN_dup (elgp); DH_set0_pqg (m_DH, BN_dup (elgp), NULL, BN_dup (elgg));
m_DH->g = BN_dup (elgg); DH_set0_key (m_DH, NULL, NULL);
m_DH->priv_key = NULL;
m_DH->pub_key = NULL;
} }
DHKeys::~DHKeys () DHKeys::~DHKeys ()
@ -240,27 +238,31 @@ namespace crypto
void DHKeys::GenerateKeys (uint8_t * priv, uint8_t * pub) void DHKeys::GenerateKeys (uint8_t * priv, uint8_t * pub)
{ {
if (m_DH->priv_key) { BN_free (m_DH->priv_key); m_DH->priv_key = NULL; }; BIGNUM * priv_key = NULL, * pub_key = NULL;
if (m_DH->pub_key) { BN_free (m_DH->pub_key); m_DH->pub_key = NULL; };
#if !defined(__x86_64__) // use short exponent for non x64 #if !defined(__x86_64__) // use short exponent for non x64
m_DH->priv_key = BN_new (); priv_key = BN_new ();
BN_rand (m_DH->priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1); BN_rand (priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1);
#endif #endif
if (g_ElggTable) if (g_ElggTable)
{ {
#if defined(__x86_64__) #if defined(__x86_64__)
m_DH->priv_key = BN_new (); priv_key = BN_new ();
BN_rand (m_DH->priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1); BN_rand (priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1);
#endif #endif
auto ctx = BN_CTX_new (); auto ctx = BN_CTX_new ();
m_DH->pub_key = ElggPow (m_DH->priv_key, g_ElggTable, ctx); pub_key = ElggPow (priv_key, g_ElggTable, ctx);
DH_set0_key (m_DH, pub_key, priv_key);
BN_CTX_free (ctx); BN_CTX_free (ctx);
} }
else else
{
DH_set0_key (m_DH, NULL, priv_key);
DH_generate_key (m_DH); DH_generate_key (m_DH);
DH_get0_key (m_DH, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key);
}
if (priv) bn2buf (m_DH->priv_key, priv, 256); if (priv) bn2buf (priv_key, priv, 256);
if (pub) bn2buf (m_DH->pub_key, pub, 256); if (pub) bn2buf (pub_key, pub, 256);
m_IsUpdated = true; m_IsUpdated = true;
} }

11
Crypto.h

@ -301,6 +301,17 @@ inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
inline void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) inline void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
{ *n = r->n; *e = r->e; *d = r->d; } { *n = r->n; *e = r->e; *d = r->d; }
inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
{ dh->p = p; dh->q = q; dh->g = g; return 1; }
inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
{
if (dh->pub_key) BN_free (dh->pub_key);
if (dh->priv_key) BN_free (dh->priv_key);
dh->pub_key = pub_key; dh->priv_key = priv_key; return 1;
}
inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
{ *pub_key = dh->pub_key; *priv_key = dh->priv_key; }
#endif #endif
} }

11
Destination.cpp

@ -277,19 +277,20 @@ namespace client
LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore");
offset += 36; offset += 36;
} }
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet; std::shared_ptr<i2p::data::LeaseSet> leaseSet;
if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet if (buf[DATABASE_STORE_TYPE_OFFSET] == 1) // LeaseSet
{ {
LogPrint (eLogDebug, "Destination: Remote LeaseSet"); LogPrint (eLogDebug, "Destination: Remote LeaseSet");
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex); std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (buf + DATABASE_STORE_KEY_OFFSET); auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end ()) if (it != m_RemoteLeaseSets.end ())
{ {
leaseSet = it->second; leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset)) if (leaseSet->IsNewer (buf + offset, len - offset))
{ {
leaseSet->Update (buf + offset, len - offset); leaseSet->Update (buf + offset, len - offset);
if (leaseSet->IsValid ()) if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
else else
{ {
@ -304,12 +305,12 @@ namespace client
else else
{ {
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset);
if (leaseSet->IsValid ()) if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
{ {
if (leaseSet->GetIdentHash () != GetIdentHash ()) if (leaseSet->GetIdentHash () != GetIdentHash ())
{ {
LogPrint (eLogDebug, "Destination: New remote LeaseSet added"); LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; m_RemoteLeaseSets[key] = leaseSet;
} }
else else
LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped"); LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
@ -324,7 +325,7 @@ namespace client
else else
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped"); LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
auto it1 = m_LeaseSetRequests.find (buf + DATABASE_STORE_KEY_OFFSET); auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ()) if (it1 != m_LeaseSetRequests.end ())
{ {
it1->second->requestTimeoutTimer.cancel (); it1->second->requestTimeoutTimer.cancel ();

2
Makefile

@ -94,7 +94,7 @@ strip: $(I2PD) $(SHLIB_CLIENT) $(SHLIB)
strip $^ strip $^
LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl) LATEST_TAG=$(shell git describe --tags --abbrev=0 openssl)
BRANCH=$(shell git branch --no-color | cut -c 3-) BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
dist: dist:
git archive --format=tar.gz -9 --worktree-attributes \ git archive --format=tar.gz -9 --worktree-attributes \
--prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz --prefix=i2pd_$(LATEST_TAG)/ $(LATEST_TAG) -o i2pd_$(LATEST_TAG).tar.gz

2
SSUSession.cpp

@ -1111,7 +1111,7 @@ namespace transport
RAND_bytes ((uint8_t *)&nonce, 4); RAND_bytes ((uint8_t *)&nonce, 4);
if (!nonce) nonce = 1; if (!nonce) nonce = 1;
m_IsPeerTest = false; m_IsPeerTest = false;
m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1); m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1, shared_from_this ());
SendPeerTest (nonce, boost::asio::ip::address(), 0, address->key, false, false); // address and port always zero for Alice SendPeerTest (nonce, boost::asio::ip::address(), 0, address->key, false, false); // address and port always zero for Alice
} }

20
Transports.cpp

@ -48,11 +48,22 @@ namespace transport
{ {
while (m_IsRunning) while (m_IsRunning)
{ {
int num; int num, total = 0;
while ((num = m_QueueSize - m_Queue.size ()) > 0) while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 20)
{
CreateDHKeysPairs (num); CreateDHKeysPairs (num);
std::unique_lock<std::mutex> l(m_AcquiredMutex); total += num;
m_Acquired.wait (l); // wait for element gets aquired }
if (total >= 20)
{
LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time");
std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break
}
else
{
std::unique_lock<std::mutex> l(m_AcquiredMutex);
m_Acquired.wait (l); // wait for element gets aquired
}
} }
} }
@ -60,7 +71,6 @@ namespace transport
{ {
if (num > 0) if (num > 0)
{ {
i2p::crypto::DHKeys dh;
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
{ {
auto pair = std::make_shared<i2p::crypto::DHKeys> (); auto pair = std::make_shared<i2p::crypto::DHKeys> ();

39
TunnelEndpoint.cpp

@ -117,7 +117,7 @@ namespace tunnel
m.nextFragmentNum = 1; m.nextFragmentNum = 1;
auto ret = m_IncompleteMessages.insert (std::pair<uint32_t, TunnelMessageBlockEx>(msgID, m)); auto ret = m_IncompleteMessages.insert (std::pair<uint32_t, TunnelMessageBlockEx>(msgID, m));
if (ret.second) if (ret.second)
HandleOutOfSequenceFragment (msgID, ret.first->second); HandleOutOfSequenceFragments (msgID, ret.first->second);
else else
LogPrint (eLogError, "TunnelMessage: Incomplete message ", msgID, " already exists"); LogPrint (eLogError, "TunnelMessage: Incomplete message ", msgID, " already exists");
} }
@ -168,7 +168,7 @@ namespace tunnel
else else
{ {
msg.nextFragmentNum++; msg.nextFragmentNum++;
HandleOutOfSequenceFragment (msgID, msg); HandleOutOfSequenceFragments (msgID, msg);
} }
} }
else else
@ -192,19 +192,31 @@ namespace tunnel
void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data) void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data)
{ {
auto it = m_OutOfSequenceFragments.find (msgID); if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {fragmentNum, isLastFragment, data}}).second)
if (it == m_OutOfSequenceFragments.end ()) LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID);
m_OutOfSequenceFragments.insert (std::pair<uint32_t, Fragment> (msgID, {fragmentNum, isLastFragment, data}));
} }
void TunnelEndpoint::HandleOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg) void TunnelEndpoint::HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg)
{ {
auto it = m_OutOfSequenceFragments.find (msgID); while (ConcatNextOutOfSequenceFragment (msgID, msg))
{
if (!msg.nextFragmentNum) // message complete
{
HandleNextMessage (msg);
m_IncompleteMessages.erase (msgID);
break;
}
}
}
bool TunnelEndpoint::ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg)
{
auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum});
if (it != m_OutOfSequenceFragments.end ()) if (it != m_OutOfSequenceFragments.end ())
{ {
if (it->second.fragmentNum == msg.nextFragmentNum) if (it->second.fragmentNum == msg.nextFragmentNum)
{ {
LogPrint (eLogWarning, "TunnelMessage: Out-of-sequence fragment ", (int)it->second.fragmentNum, " of message ", msgID, " found"); LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)it->second.fragmentNum, " of message ", msgID, " found");
size_t size = it->second.data->GetLength (); size_t size = it->second.data->GetLength ();
if (msg.data->len + size > msg.data->maxLen) if (msg.data->len + size > msg.data->maxLen)
{ {
@ -214,18 +226,19 @@ namespace tunnel
msg.data = newMsg; msg.data = newMsg;
} }
if (msg.data->Concat (it->second.data->GetBuffer (), size) < size) // concatenate out-of-sync fragment if (msg.data->Concat (it->second.data->GetBuffer (), size) < size) // concatenate out-of-sync fragment
LogPrint (eLogError, "Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen); LogPrint (eLogError, "TunnelMessage: Tunnel endpoint I2NP buffer overflow ", msg.data->maxLen);
if (it->second.isLastFragment) if (it->second.isLastFragment)
{
// message complete // message complete
HandleNextMessage (msg); msg.nextFragmentNum = 0;
m_IncompleteMessages.erase (msgID);
}
else else
msg.nextFragmentNum++; msg.nextFragmentNum++;
m_OutOfSequenceFragments.erase (it); m_OutOfSequenceFragments.erase (it);
return true;
} }
else
LogPrint (eLogError, "Tunnel message: next fragment ", (int)it->second.fragmentNum, " of message ", msgID, " mismatch. ", (int)msg.nextFragmentNum, " expected");
} }
return false;
} }
void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg)

5
TunnelEndpoint.h

@ -39,12 +39,13 @@ namespace tunnel
void HandleNextMessage (const TunnelMessageBlock& msg); void HandleNextMessage (const TunnelMessageBlock& msg);
void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data); void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr<I2NPMessage> data);
void HandleOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added
void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg);
private: private:
std::map<uint32_t, TunnelMessageBlockEx> m_IncompleteMessages; std::map<uint32_t, TunnelMessageBlockEx> m_IncompleteMessages;
std::map<uint32_t, Fragment> m_OutOfSequenceFragments; std::map<std::pair<uint32_t, uint8_t>, Fragment> m_OutOfSequenceFragments; // (msgID, fragment#)->fragment
bool m_IsInbound; bool m_IsInbound;
size_t m_NumReceivedBytes; size_t m_NumReceivedBytes;
}; };

30
Win32/installer.iss

@ -1,9 +1,11 @@
#define I2Pd_AppName "i2pd" #define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.10.0" #define I2Pd_ver "2.10.1"
#define I2Pd_Publisher "PurpleI2P"
[Setup] [Setup]
AppName={#I2Pd_AppName} AppName={#I2Pd_AppName}
AppVersion={#I2Pd_ver} AppVersion={#I2Pd_ver}
AppPublisher={#I2Pd_Publisher}
DefaultDirName={pf}\I2Pd DefaultDirName={pf}\I2Pd
DefaultGroupName=I2Pd DefaultGroupName=I2Pd
UninstallDisplayIcon={app}\I2Pd.exe UninstallDisplayIcon={app}\I2Pd.exe
@ -14,19 +16,25 @@ InternalCompressLevel=ultra64
Compression=lzma/ultra64 Compression=lzma/ultra64
SolidCompression=true SolidCompression=true
ArchitecturesInstallIn64BitMode=x64 ArchitecturesInstallIn64BitMode=x64
AppVerName={#I2Pd_AppName}
ExtraDiskSpaceRequired=15
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
AppPublisherURL=http://i2pd.website/
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
[Files] [Files]
Source: "..\i2pd_x86.exe"; DestDir: "{app}"; DestName: "i2pd.exe"; Flags: ignoreversion; Check: not IsWin64 Source: ..\i2pd_x86.exe; DestDir: {app}; DestName: i2pd.exe; Flags: ignoreversion; Check: not IsWin64
Source: "..\i2pd_x64.exe"; DestDir: "{app}"; DestName: "i2pd.exe"; Flags: ignoreversion; Check: IsWin64 Source: ..\i2pd_x64.exe; DestDir: {app}; DestName: i2pd.exe; Flags: ignoreversion; Check: IsWin64
Source: "..\README.md"; DestDir: "{app}"; DestName: "Readme.txt"; Flags: onlyifdoesntexist Source: ..\README.md; DestDir: {app}; DestName: Readme.txt; Flags: onlyifdoesntexist
Source: "..\docs\i2pd.conf"; DestDir: "{userappdata}\i2pd"; Flags: onlyifdoesntexist Source: ..\docs\i2pd.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: "..\docs\subscriptions.txt"; DestDir: "{userappdata}\i2pd"; Flags: onlyifdoesntexist Source: ..\docs\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: "..\docs\tunnels.conf"; DestDir: "{userappdata}\i2pd"; Flags: onlyifdoesntexist Source: ..\docs\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
Source: "..\contrib\*"; DestDir: "{userappdata}\i2pd"; Flags: onlyifdoesntexist recursesubdirs createallsubdirs Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
[Icons] [Icons]
Name: "{group}\I2Pd"; Filename: "{app}\i2pd.exe" Name: {group}\I2Pd; Filename: {app}\i2pd.exe
Name: "{group}\Readme"; Filename: "{app}\Readme.txt" Name: {group}\Readme; Filename: {app}\Readme.txt
[UninstallDelete] [UninstallDelete]
Type: filesandordirs; Name: {app}\* Type: filesandordirs; Name: {app}

2
android/AndroidManifest.xml

@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.purplei2p.i2pd" package="org.purplei2p.i2pd"
android:versionCode="1" android:versionCode="1"
android:versionName="2.10.0"> android:versionName="2.10.1">
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="24"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>

41
docs/usage.md

@ -10,6 +10,47 @@ i2pd can be used for:
and many more. and many more.
## Starting, stopping and reloading configuration
After you have built i2pd from source, just run a binary:
./i2pd
To display all available options:
./i2pd --help
i2pd can be controlled with signals. Process ID by default is written to file `~/.i2pd/i2pd.pid` or `/var/run/i2pd/i2pd.pid`.
You can use `kill` utility to send signals like this:
kill -TERM $( cat /var/run/i2pd/i2pd.pid )
i2pd supports the following signals:
TERM - Graceful shutdown. i2pd will wait for 10 minutes and stop. Send second TERM signal to shutdown i2pd immediately.
HUP - Reload configuration files.
### systemd unit
Some binary Linux packages have a systemd control unit, so it is possible to managage i2pd with it.
Start/stop i2pd:
sudo systemctl start i2pd.service
sudo systemctl stop i2pd.service
Enable/disable i2pd to be started on bootup:
sudo systemctl enable i2pd.service
sudo systemctl disable i2pd.service
## Configuring i2pd
See [configuration page](i2pd.readthedocs.io/page/configuration.html).
## Browsing and hosting websites ## Browsing and hosting websites
### Browse anonymous websites ### Browse anonymous websites

2
version.h

@ -8,7 +8,7 @@
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 10 #define I2PD_VERSION_MINOR 10
#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_MICRO 1
#define I2PD_VERSION_PATCH 0 #define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
#define VERSION I2PD_VERSION #define VERSION I2PD_VERSION

Loading…
Cancel
Save