mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-05 20:43:48 +01:00
commit
c212a30d33
40 changed files with 946 additions and 510 deletions
|
@ -37,7 +37,12 @@ port = 7070
|
||||||
enabled = true
|
enabled = true
|
||||||
address = 127.0.0.1
|
address = 127.0.0.1
|
||||||
port = 4444
|
port = 4444
|
||||||
# keys = http-proxy-keys.dat
|
inbound.length = 1
|
||||||
|
inbound.quantity = 5
|
||||||
|
outbound.length = 1
|
||||||
|
outbound.quantity = 5
|
||||||
|
signaturetype=7
|
||||||
|
keys = proxy-keys.dat
|
||||||
# addresshelper = true
|
# addresshelper = true
|
||||||
# outproxy = http://false.i2p
|
# outproxy = http://false.i2p
|
||||||
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
|
||||||
|
@ -46,7 +51,7 @@ port = 4444
|
||||||
enabled = true
|
enabled = true
|
||||||
address = 127.0.0.1
|
address = 127.0.0.1
|
||||||
port = 4447
|
port = 4447
|
||||||
# keys = socks-proxy-keys.dat
|
keys = proxy-keys.dat
|
||||||
# outproxy.enabled = false
|
# outproxy.enabled = false
|
||||||
# outproxy = 127.0.0.1
|
# outproxy = 127.0.0.1
|
||||||
# outproxyport = 9050
|
# outproxyport = 9050
|
||||||
|
@ -80,3 +85,6 @@ verify = true
|
||||||
|
|
||||||
[limits]
|
[limits]
|
||||||
transittunnels = 50
|
transittunnels = 50
|
||||||
|
|
||||||
|
[persist]
|
||||||
|
profiles = false
|
||||||
|
|
|
@ -58,6 +58,11 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
|
(JNIEnv * env, jclass clazz) {
|
||||||
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv * env, jclass clazz, jboolean isConnected)
|
(JNIEnv * env, jclass clazz, jboolean isConnected)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,9 @@ JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopAcceptingTunnels
|
||||||
(JNIEnv *, jclass);
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startAcceptingTunnels
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_onNetworkStateChanged
|
||||||
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
(JNIEnv * env, jclass clazz, jboolean isConnected);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="app_name">i2pd</string>
|
<string name="app_name">i2pd</string>
|
||||||
<string name="action_stop">Stop</string>
|
<string name="action_stop">Stop</string>
|
||||||
<string name="action_graceful_stop">Graceful Stop</string>
|
<string name="action_graceful_stop">Graceful Stop</string>
|
||||||
|
<string name="action_cancel_graceful_stop">Cancel Graceful Stop</string>
|
||||||
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
<string name="graceful_stop_is_already_in_progress">Graceful stop is already in progress</string>
|
||||||
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
<string name="graceful_stop_is_in_progress">Graceful stop is in progress</string>
|
||||||
<string name="already_stopped">Already stopped</string>
|
<string name="already_stopped">Already stopped</string>
|
||||||
|
|
|
@ -33,6 +33,13 @@ public class DaemonSingleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void startAcceptingTunnels() {
|
||||||
|
if(isStartedOkay()){
|
||||||
|
setState(State.startedOkay);
|
||||||
|
I2PD_JNI.startAcceptingTunnels();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private volatile boolean startedOkay;
|
private volatile boolean startedOkay;
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
|
|
|
@ -13,13 +13,16 @@ import java.io.StringWriter;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -27,12 +30,15 @@ import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
|
||||||
// For future package update checking
|
// For future package update checking
|
||||||
import org.purplei2p.i2pd.BuildConfig;
|
import org.purplei2p.i2pd.BuildConfig;
|
||||||
|
|
||||||
public class I2PDActivity extends Activity {
|
public class I2PDActivity extends Activity {
|
||||||
private static final String TAG = "i2pdActvt";
|
private static final String TAG = "i2pdActvt";
|
||||||
|
private static final int MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE = 1;
|
||||||
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
||||||
|
|
||||||
private TextView textView;
|
private TextView textView;
|
||||||
|
@ -93,6 +99,17 @@ public class I2PDActivity extends Activity {
|
||||||
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||||
daemonStateUpdatedListener.daemonStateUpdate();
|
daemonStateUpdatedListener.daemonStateUpdate();
|
||||||
|
|
||||||
|
// request permissions
|
||||||
|
if (Build.VERSION.SDK_INT >= 23)
|
||||||
|
{
|
||||||
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
||||||
|
{
|
||||||
|
ActivityCompat.requestPermissions(this,
|
||||||
|
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
|
||||||
|
MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// set the app be foreground
|
// set the app be foreground
|
||||||
doBindService();
|
doBindService();
|
||||||
|
|
||||||
|
@ -119,6 +136,24 @@ public class I2PDActivity extends Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
|
||||||
|
{
|
||||||
|
switch (requestCode)
|
||||||
|
{
|
||||||
|
case MY_PERMISSION_REQUEST_WRITE_EXTERNAL_STORAGE:
|
||||||
|
{
|
||||||
|
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
|
||||||
|
Log.e(TAG, "Memory permission granted");
|
||||||
|
else
|
||||||
|
Log.e(TAG, "Memory permission declined");
|
||||||
|
// TODO: terminate
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void cancelGracefulStop() {
|
private static void cancelGracefulStop() {
|
||||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||||
if(gracefulQuitTimer!=null) {
|
if(gracefulQuitTimer!=null) {
|
||||||
|
@ -205,7 +240,16 @@ public class I2PDActivity extends Activity {
|
||||||
i2pdStop();
|
i2pdStop();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_graceful_stop:
|
case R.id.action_graceful_stop:
|
||||||
i2pdGracefulStop();
|
if (getGracefulQuitTimer()!= null)
|
||||||
|
{
|
||||||
|
item.setTitle(R.string.action_graceful_stop);
|
||||||
|
i2pdCancelGracefulStop ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.setTitle(R.string.action_cancel_graceful_stop);
|
||||||
|
i2pdGracefulStop();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +312,32 @@ public class I2PDActivity extends Activity {
|
||||||
|
|
||||||
},"gracInit").start();
|
},"gracInit").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void i2pdCancelGracefulStop()
|
||||||
|
{
|
||||||
|
cancelGracefulStop();
|
||||||
|
Toast.makeText(this, R.string.startedOkay, Toast.LENGTH_SHORT).show();
|
||||||
|
new Thread(new Runnable()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log.d(TAG, "grac stopping cancel");
|
||||||
|
if(daemon.isStartedOkay())
|
||||||
|
daemon.startAcceptingTunnels();
|
||||||
|
else
|
||||||
|
i2pdStop();
|
||||||
|
}
|
||||||
|
catch(Throwable tr)
|
||||||
|
{
|
||||||
|
Log.e(TAG,"",tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},"gracCancel").start();
|
||||||
|
}
|
||||||
|
|
||||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
||||||
|
|
|
@ -12,6 +12,8 @@ public class I2PD_JNI {
|
||||||
|
|
||||||
public static native void stopAcceptingTunnels();
|
public static native void stopAcceptingTunnels();
|
||||||
|
|
||||||
|
public static native void startAcceptingTunnels();
|
||||||
|
|
||||||
public static native void onNetworkStateChanged(boolean isConnected);
|
public static native void onNetworkStateChanged(boolean isConnected);
|
||||||
|
|
||||||
public static void loadLibraries() {
|
public static void loadLibraries() {
|
||||||
|
|
|
@ -93,6 +93,8 @@ ipv6 = false
|
||||||
## Address and port service will listen on
|
## Address and port service will listen on
|
||||||
address = 127.0.0.1
|
address = 127.0.0.1
|
||||||
port = 7070
|
port = 7070
|
||||||
|
## Path to web console, default "/"
|
||||||
|
# webroot = /
|
||||||
## Uncomment following lines to enable Web Console authentication
|
## Uncomment following lines to enable Web Console authentication
|
||||||
# auth = true
|
# auth = true
|
||||||
# user = i2pd
|
# user = i2pd
|
||||||
|
@ -223,3 +225,7 @@ verify = true
|
||||||
# inbound.quantity = 3
|
# inbound.quantity = 3
|
||||||
# outbound.length = 2
|
# outbound.length = 2
|
||||||
# outbound.quantity = 3
|
# outbound.quantity = 3
|
||||||
|
|
||||||
|
[persist]
|
||||||
|
## Save peer profiles on disk (default: true)
|
||||||
|
# profiles = true
|
||||||
|
|
|
@ -55,19 +55,22 @@ make %{?_smp_mflags}
|
||||||
|
|
||||||
%install
|
%install
|
||||||
cd build
|
cd build
|
||||||
|
%if 0%{?mageia}
|
||||||
|
cd build
|
||||||
|
%endif
|
||||||
chrpath -d i2pd
|
chrpath -d i2pd
|
||||||
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
%{__install} -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd
|
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||||
install -d -m 755 %{buildroot}%{_datadir}/i2pd/tunnels.conf.d
|
%{__install} -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.d/README %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d/README
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
||||||
install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
%{__install} -d -m 755 %{buildroot}%{_datadir}/%{name}
|
||||||
|
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/%{name}/certificates
|
||||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||||
ln -s %{_datadir}/i2pd/tunnels.conf.d %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
|
||||||
|
|
||||||
|
|
||||||
%pre
|
%pre
|
||||||
|
@ -90,14 +93,14 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%doc LICENSE README.md
|
%doc LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf contrib/tunnels.d
|
||||||
%{_sbindir}/i2pd
|
%{_sbindir}/i2pd
|
||||||
%{_datadir}/i2pd/certificates
|
|
||||||
%config(noreplace) %{_sysconfdir}/i2pd/*
|
%config(noreplace) %{_sysconfdir}/i2pd/*
|
||||||
%config(noreplace) %{_sysconfdir}/i2pd/tunnels.conf.d/*
|
%{_unitdir}/i2pd.service
|
||||||
/%{_unitdir}/i2pd.service
|
%{_mandir}/man1/i2pd.1*
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
|
||||||
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd
|
||||||
|
%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd
|
||||||
|
%{_datadir}/%{name}/certificates
|
||||||
%{_sharedstatedir}/i2pd/certificates
|
%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,9 @@ make %{?_smp_mflags}
|
||||||
|
|
||||||
%install
|
%install
|
||||||
cd build
|
cd build
|
||||||
|
%if 0%{?mageia}
|
||||||
|
cd build
|
||||||
|
%endif
|
||||||
chrpath -d i2pd
|
chrpath -d i2pd
|
||||||
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd
|
||||||
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
#port = 6668
|
#port = 6668
|
||||||
#destination = irc.postman.i2p
|
#destination = irc.postman.i2p
|
||||||
#destinationport = 6667
|
#destinationport = 6667
|
||||||
#keys = irc-keys.dat
|
#keys = irc-keys.dat
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
In that directory you can store separated config files for every tunnel.
|
# In that directory you can store separated config files for every tunnel.
|
||||||
|
# Please read documentation for more info.
|
||||||
|
#
|
||||||
|
# You can find examples in /usr/share/doc/i2pd/tunnels.d directory
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "UPnP.h"
|
#include "UPnP.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
|
@ -41,6 +42,7 @@ namespace i2p
|
||||||
std::unique_ptr<i2p::http::HTTPServer> httpServer;
|
std::unique_ptr<i2p::http::HTTPServer> httpServer;
|
||||||
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
|
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
|
||||||
std::unique_ptr<i2p::transport::UPnP> UPnP;
|
std::unique_ptr<i2p::transport::UPnP> UPnP;
|
||||||
|
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
|
||||||
#ifdef WITH_EVENTS
|
#ifdef WITH_EVENTS
|
||||||
std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
|
std::unique_ptr<i2p::event::WebsocketServer> m_WebsocketServer;
|
||||||
#endif
|
#endif
|
||||||
|
@ -282,6 +284,13 @@ namespace i2p
|
||||||
d.UPnP->Start ();
|
d.UPnP->Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nettime; i2p::config::GetOption("nettime.enabled", nettime);
|
||||||
|
if (nettime)
|
||||||
|
{
|
||||||
|
d.m_NTPSync = std::unique_ptr<i2p::util::NTPTimeSync>(new i2p::util::NTPTimeSync);
|
||||||
|
d.m_NTPSync->Start ();
|
||||||
|
}
|
||||||
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||||
|
@ -351,11 +360,18 @@ namespace i2p
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
||||||
i2p::tunnel::tunnels.Stop();
|
i2p::tunnel::tunnels.Stop();
|
||||||
|
|
||||||
if (d.UPnP) {
|
if (d.UPnP)
|
||||||
|
{
|
||||||
d.UPnP->Stop ();
|
d.UPnP->Stop ();
|
||||||
d.UPnP = nullptr;
|
d.UPnP = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (d.m_NTPSync)
|
||||||
|
{
|
||||||
|
d.m_NTPSync->Stop ();
|
||||||
|
d.m_NTPSync = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Transports");
|
LogPrint(eLogInfo, "Daemon: stopping Transports");
|
||||||
i2p::transport::transports.Stop();
|
i2p::transport::transports.Stop();
|
||||||
LogPrint(eLogInfo, "Daemon: stopping NetDB");
|
LogPrint(eLogInfo, "Daemon: stopping NetDB");
|
||||||
|
|
|
@ -155,6 +155,8 @@ namespace http {
|
||||||
|
|
||||||
static void ShowPageHead (std::stringstream& s)
|
static void ShowPageHead (std::stringstream& s)
|
||||||
{
|
{
|
||||||
|
std::string webroot;
|
||||||
|
i2p::config::GetOption("http.webroot", webroot);
|
||||||
s <<
|
s <<
|
||||||
"<!DOCTYPE html>\r\n"
|
"<!DOCTYPE html>\r\n"
|
||||||
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
"<html lang=\"en\">\r\n" /* TODO: Add support for locale */
|
||||||
|
@ -173,16 +175,16 @@ namespace http {
|
||||||
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
|
"<div class=header><b>i2pd</b> webconsole</div>\r\n"
|
||||||
"<div class=wrapper>\r\n"
|
"<div class=wrapper>\r\n"
|
||||||
"<div class=left>\r\n"
|
"<div class=left>\r\n"
|
||||||
" <a href=\"/\">Main page</a><br>\r\n<br>\r\n"
|
" <a href=\"" << webroot << "\">Main page</a><br>\r\n<br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_COMMANDS << "\">Router commands</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATIONS << "\">Local destinations</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">LeaseSets</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">Tunnels</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">Transit tunnels</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">Transports</a><br>\r\n"
|
||||||
" <a href=\"/?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">I2P tunnels</a><br>\r\n";
|
||||||
if (i2p::client::context.GetSAMBridge ())
|
if (i2p::client::context.GetSAMBridge ())
|
||||||
s << " <a href=\"/?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">SAM sessions</a><br>\r\n";
|
||||||
s <<
|
s <<
|
||||||
"</div>\r\n"
|
"</div>\r\n"
|
||||||
"<div class=right>";
|
"<div class=right>";
|
||||||
|
@ -321,11 +323,12 @@ namespace http {
|
||||||
|
|
||||||
void ShowLocalDestinations (std::stringstream& s)
|
void ShowLocalDestinations (std::stringstream& s)
|
||||||
{
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
|
s << "<b>Local Destinations:</b><br>\r\n<br>\r\n";
|
||||||
for (auto& it: i2p::client::context.GetDestinations ())
|
for (auto& it: i2p::client::context.GetDestinations ())
|
||||||
{
|
{
|
||||||
auto ident = it.second->GetIdentHash ();
|
auto ident = it.second->GetIdentHash ();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +343,7 @@ namespace http {
|
||||||
{
|
{
|
||||||
auto ident = dest->GetIdentHash ();
|
auto ident = dest->GetIdentHash ();
|
||||||
auto& name = dest->GetNickname ();
|
auto& name = dest->GetNickname ();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_I2CP_LOCAL_DESTINATION << "&i2cp_id=" << it.first << "\">[ ";
|
||||||
s << name << " ]</a> ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"<br>\r\n" << std::endl;
|
s << name << " ]</a> ⇔ " << i2p::client::context.GetAddressBook ().ToAddress(ident) <<"<br>\r\n" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,33 +513,34 @@ namespace http {
|
||||||
|
|
||||||
static void ShowCommands (std::stringstream& s, uint32_t token)
|
static void ShowCommands (std::stringstream& s, uint32_t token)
|
||||||
{
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
/* commands */
|
/* commands */
|
||||||
s << "<b>Router Commands</b><br>\r\n<br>\r\n";
|
s << "<b>Router Commands</b><br>\r\n<br>\r\n";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">Run peer test</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">Run peer test</a><br>\r\n";
|
||||||
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
|
//s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
|
||||||
if (i2p::context.AcceptsTunnels ())
|
if (i2p::context.AcceptsTunnels ())
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">Decline transit tunnels</a><br>\r\n";
|
||||||
else
|
else
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_ENABLE_TRANSIT << "&token=" << token << "\">Accept transit tunnels</a><br>\r\n";
|
||||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||||
if (Daemon.gracefulShutdownInterval)
|
if (Daemon.gracefulShutdownInterval)
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
||||||
else
|
else
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Start graceful shutdown</a><br>\r\n";
|
||||||
#elif defined(WIN32_APP)
|
#elif defined(WIN32_APP)
|
||||||
if (i2p::util::DaemonWin32::Instance().isGraceful)
|
if (i2p::util::DaemonWin32::Instance().isGraceful)
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_CANCEL << "&token=" << token << "\">Cancel graceful shutdown</a><br>";
|
||||||
else
|
else
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_START << "&token=" << token << "\">Graceful shutdown</a><br>\r\n";
|
||||||
#endif
|
#endif
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_SHUTDOWN_NOW << "&token=" << token << "\">Force shutdown</a><br>\r\n";
|
||||||
|
|
||||||
s << "<br>\r\n<b>Logging level</b><br>\r\n";
|
s << "<br>\r\n<b>Logging level</b><br>\r\n";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\">[none]</a> ";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\">[error]</a> ";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\">[warn]</a> ";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\">[info]</a> ";
|
||||||
s << " <a href=\"/?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\">[debug]</a><br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowTransitTunnels (std::stringstream& s)
|
void ShowTransitTunnels (std::stringstream& s)
|
||||||
|
@ -653,6 +657,7 @@ namespace http {
|
||||||
|
|
||||||
void ShowSAMSessions (std::stringstream& s)
|
void ShowSAMSessions (std::stringstream& s)
|
||||||
{
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
auto sam = i2p::client::context.GetSAMBridge ();
|
auto sam = i2p::client::context.GetSAMBridge ();
|
||||||
if (!sam) {
|
if (!sam) {
|
||||||
ShowError(s, "SAM disabled");
|
ShowError(s, "SAM disabled");
|
||||||
|
@ -662,13 +667,14 @@ namespace http {
|
||||||
for (auto& it: sam->GetSessions ())
|
for (auto& it: sam->GetSessions ())
|
||||||
{
|
{
|
||||||
auto& name = it.second->localDestination->GetNickname ();
|
auto& name = it.second->localDestination->GetNickname ();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSION << "&sam_id=" << it.first << "\">";
|
||||||
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
|
s << name << " (" << it.first << ")</a><br>\r\n" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowSAMSession (std::stringstream& s, const std::string& id)
|
static void ShowSAMSession (std::stringstream& s, const std::string& id)
|
||||||
{
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
s << "<b>SAM Session:</b><br>\r\n<br>\r\n";
|
s << "<b>SAM Session:</b><br>\r\n<br>\r\n";
|
||||||
auto sam = i2p::client::context.GetSAMBridge ();
|
auto sam = i2p::client::context.GetSAMBridge ();
|
||||||
if (!sam) {
|
if (!sam) {
|
||||||
|
@ -681,7 +687,7 @@ namespace http {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ident = session->localDestination->GetIdentHash();
|
auto& ident = session->localDestination->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident) << "</a><br>\r\n";
|
||||||
s << "<br>\r\n";
|
s << "<br>\r\n";
|
||||||
s << "<b>Streams:</b><br>\r\n";
|
s << "<b>Streams:</b><br>\r\n";
|
||||||
|
@ -701,11 +707,12 @@ namespace http {
|
||||||
|
|
||||||
void ShowI2PTunnels (std::stringstream& s)
|
void ShowI2PTunnels (std::stringstream& s)
|
||||||
{
|
{
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
|
s << "<b>Client Tunnels:</b><br>\r\n<br>\r\n";
|
||||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇐ ";
|
s << it.second->GetName () << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
|
@ -714,7 +721,7 @@ namespace http {
|
||||||
if (httpProxy)
|
if (httpProxy)
|
||||||
{
|
{
|
||||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << "HTTP Proxy" << "</a> ⇐ ";
|
s << "HTTP Proxy" << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
|
@ -723,7 +730,7 @@ namespace http {
|
||||||
if (socksProxy)
|
if (socksProxy)
|
||||||
{
|
{
|
||||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << "SOCKS Proxy" << "</a> ⇐ ";
|
s << "SOCKS Proxy" << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
|
@ -734,7 +741,7 @@ namespace http {
|
||||||
for (auto& it: serverTunnels)
|
for (auto& it: serverTunnels)
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇒ ";
|
s << it.second->GetName () << "</a> ⇒ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << ":" << it.second->GetLocalPort ();
|
s << ":" << it.second->GetLocalPort ();
|
||||||
|
@ -748,7 +755,7 @@ namespace http {
|
||||||
for (auto& it: clientForwards)
|
for (auto& it: clientForwards)
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇐ ";
|
s << it.second->GetName () << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
|
@ -761,7 +768,7 @@ namespace http {
|
||||||
for (auto& it: serverForwards)
|
for (auto& it: serverForwards)
|
||||||
{
|
{
|
||||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||||
s << "<a href=\"/?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
|
||||||
s << it.second->GetName () << "</a> ⇐ ";
|
s << it.second->GetName () << "</a> ⇐ ";
|
||||||
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
|
||||||
s << "<br>\r\n"<< std::endl;
|
s << "<br>\r\n"<< std::endl;
|
||||||
|
@ -1025,10 +1032,12 @@ namespace http {
|
||||||
ShowError(s, "Unknown command: " + cmd);
|
ShowError(s, "Unknown command: " + cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
|
std::string redirect = "5; url=" + webroot + "?page=commands";
|
||||||
s << "<b>SUCCESS</b>: Command accepted<br><br>\r\n";
|
s << "<b>SUCCESS</b>: Command accepted<br><br>\r\n";
|
||||||
s << "<a href=\"/?page=commands\">Back to commands list</a><br>\r\n";
|
s << "<a href=\"" << webroot << "?page=commands\">Back to commands list</a><br>\r\n";
|
||||||
s << "<p>You will be redirected in 5 seconds</b>";
|
s << "<p>You will be redirected in 5 seconds</b>";
|
||||||
res.add_header("Refresh", "5; url=/?page=commands");
|
res.add_header("Refresh", redirect.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
void HTTPConnection::SendReply (HTTPRes& reply, std::string& content)
|
||||||
|
|
1
debian/docs
vendored
1
debian/docs
vendored
|
@ -2,3 +2,4 @@ README.md
|
||||||
contrib/i2pd.conf
|
contrib/i2pd.conf
|
||||||
contrib/subscriptions.txt
|
contrib/subscriptions.txt
|
||||||
contrib/tunnels.conf
|
contrib/tunnels.conf
|
||||||
|
contrib/tunnels.d
|
||||||
|
|
1
debian/i2pd.dirs
vendored
1
debian/i2pd.dirs
vendored
|
@ -1,3 +1,2 @@
|
||||||
etc/i2pd
|
etc/i2pd
|
||||||
etc/i2pd/tunnels.conf.d
|
|
||||||
var/lib/i2pd
|
var/lib/i2pd
|
||||||
|
|
2
debian/i2pd.install
vendored
2
debian/i2pd.install
vendored
|
@ -3,5 +3,5 @@ contrib/i2pd.conf etc/i2pd/
|
||||||
contrib/tunnels.conf etc/i2pd/
|
contrib/tunnels.conf etc/i2pd/
|
||||||
contrib/subscriptions.txt etc/i2pd/
|
contrib/subscriptions.txt etc/i2pd/
|
||||||
contrib/certificates/ usr/share/i2pd/
|
contrib/certificates/ usr/share/i2pd/
|
||||||
contrib/tunnels.d/ etc/i2pd/tunnels.conf.d
|
contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/
|
||||||
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d
|
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d
|
||||||
|
|
2
debian/i2pd.links
vendored
2
debian/i2pd.links
vendored
|
@ -1,5 +1,5 @@
|
||||||
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
|
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
|
||||||
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
|
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
|
||||||
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
|
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
|
||||||
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.conf.d
|
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d
|
||||||
usr/share/i2pd/certificates var/lib/i2pd/certificates
|
usr/share/i2pd/certificates var/lib/i2pd/certificates
|
||||||
|
|
|
@ -1,21 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2018, The PurpleI2P Project
|
||||||
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
|
*
|
||||||
|
* Kovri go write your own code
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#include "ChaCha20.h"
|
#include "ChaCha20.h"
|
||||||
|
|
||||||
/**
|
#if LEGACY_OPENSSL
|
||||||
This code is licensed under the MCGSI Public License
|
|
||||||
Copyright 2018 Jeff Becker
|
|
||||||
|
|
||||||
Kovri go write your own code
|
|
||||||
|
|
||||||
*/
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
namespace chacha
|
namespace chacha
|
||||||
{
|
{
|
||||||
constexpr int rounds = 20;
|
|
||||||
constexpr std::size_t blocksize = 64;
|
|
||||||
|
|
||||||
void u32t8le(uint32_t v, uint8_t * p)
|
void u32t8le(uint32_t v, uint8_t * p)
|
||||||
{
|
{
|
||||||
p[0] = v & 0xff;
|
p[0] = v & 0xff;
|
||||||
|
@ -48,44 +50,18 @@ void quarterround(uint32_t *x, int a, int b, int c, int d)
|
||||||
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State_t
|
|
||||||
{
|
|
||||||
State_t() {};
|
|
||||||
State_t(State_t &&) = delete;
|
|
||||||
|
|
||||||
State_t & operator += (const State_t & other)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < 16; i++)
|
|
||||||
data[i] += other.data[i];
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Copy(const State_t & other)
|
void Chacha20Block::operator << (const Chacha20State & st)
|
||||||
{
|
{
|
||||||
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
int i;
|
||||||
}
|
for (i = 0; i < 16; i++)
|
||||||
uint32_t data[16];
|
u32t8le(st.data[i], data + (i << 2));
|
||||||
};
|
}
|
||||||
|
|
||||||
struct Block_t
|
void block (Chacha20State &input, int rounds)
|
||||||
{
|
|
||||||
Block_t() {};
|
|
||||||
Block_t(Block_t &&) = delete;
|
|
||||||
|
|
||||||
uint8_t data[blocksize];
|
|
||||||
|
|
||||||
void operator << (const State_t & st)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < 16; i++)
|
|
||||||
u32t8le(st.data[i], data + (i << 2));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void block(const State_t &input, Block_t & block, int rounds)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
State_t x;
|
Chacha20State x;
|
||||||
x.Copy(input);
|
x.Copy(input);
|
||||||
|
|
||||||
for (i = rounds; i > 0; i -= 2)
|
for (i = rounds; i > 0; i -= 2)
|
||||||
|
@ -100,48 +76,61 @@ void block(const State_t &input, Block_t & block, int rounds)
|
||||||
quarterround(x.data, 3, 4, 9, 14);
|
quarterround(x.data, 3, 4, 9, 14);
|
||||||
}
|
}
|
||||||
x += input;
|
x += input;
|
||||||
block << x;
|
input.block << x;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
{
|
||||||
|
state.data[0] = 0x61707865;
|
||||||
|
state.data[1] = 0x3320646e;
|
||||||
|
state.data[2] = 0x79622d32;
|
||||||
|
state.data[3] = 0x6b206574;
|
||||||
|
for (size_t i = 0; i < 8; i++)
|
||||||
|
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
||||||
|
|
||||||
|
state.data[12] = counter;
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
|
||||||
|
{
|
||||||
|
state.data[12] = counter;
|
||||||
|
state.offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
|
||||||
|
{
|
||||||
|
if (state.offset > 0)
|
||||||
|
{
|
||||||
|
// previous block if any
|
||||||
|
auto s = chacha::blocksize - state.offset;
|
||||||
|
if (sz < s) s = sz;
|
||||||
|
for (size_t i = 0; i < s; i++)
|
||||||
|
buf[i] ^= state.block.data[state.offset + i];
|
||||||
|
buf += s;
|
||||||
|
sz -= s;
|
||||||
|
state.offset = 0;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < sz; i += chacha::blocksize)
|
||||||
|
{
|
||||||
|
chacha::block(state, chacha::rounds);
|
||||||
|
state.data[12]++;
|
||||||
|
for (size_t j = i; j < i + chacha::blocksize; j++)
|
||||||
|
{
|
||||||
|
if (j >= sz)
|
||||||
|
{
|
||||||
|
state.offset = j & 0x3F; // % 64
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[j] ^= state.block.data[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace chacha
|
} // namespace chacha
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
|
||||||
{
|
|
||||||
chacha::State_t state;
|
|
||||||
chacha::Block_t block;
|
|
||||||
size_t i, j;
|
|
||||||
|
|
||||||
state.data[0] = 0x61707865;
|
|
||||||
state.data[1] = 0x3320646e;
|
|
||||||
state.data[2] = 0x79622d32;
|
|
||||||
state.data[3] = 0x6b206574;
|
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
|
||||||
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
|
||||||
|
|
||||||
|
|
||||||
state.data[12] = counter;
|
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
|
||||||
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < sz; i += chacha::blocksize)
|
|
||||||
{
|
|
||||||
chacha::block(state, block, chacha::rounds);
|
|
||||||
state.data[12]++;
|
|
||||||
for (j = i; j < i + chacha::blocksize; j++)
|
|
||||||
{
|
|
||||||
if (j >= sz) break;
|
|
||||||
buf[j] ^= block.data[j - i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,72 @@
|
||||||
/**
|
/*
|
||||||
This code is licensed under the MCGSI Public License
|
* Copyright (c) 2013-2018, The PurpleI2P Project
|
||||||
Copyright 2018 Jeff Becker
|
*
|
||||||
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
Kovri go write your own code
|
*
|
||||||
|
* See full license text in LICENSE file at top of project tree
|
||||||
*/
|
*
|
||||||
|
* Kovri go write your own code
|
||||||
|
*
|
||||||
|
*/
|
||||||
#ifndef LIBI2PD_CHACHA20_H
|
#ifndef LIBI2PD_CHACHA20_H
|
||||||
#define LIBI2PD_CHACHA20_H
|
#define LIBI2PD_CHACHA20_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "Crypto.h"
|
||||||
|
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
const std::size_t CHACHA20_KEY_BYTES = 32;
|
const std::size_t CHACHA20_KEY_BYTES = 32;
|
||||||
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
||||||
|
|
||||||
|
namespace chacha
|
||||||
|
{
|
||||||
|
constexpr std::size_t blocksize = 64;
|
||||||
|
constexpr int rounds = 20;
|
||||||
|
|
||||||
/** encrypt buf in place with chacha20 */
|
struct Chacha20State;
|
||||||
void chacha20(uint8_t * buf, size_t sz, const uint8_t * nonce, const uint8_t * key, uint32_t counter=1);
|
struct Chacha20Block
|
||||||
|
{
|
||||||
|
Chacha20Block () {};
|
||||||
|
Chacha20Block (Chacha20Block &&) = delete;
|
||||||
|
|
||||||
|
uint8_t data[blocksize];
|
||||||
|
|
||||||
|
void operator << (const Chacha20State & st);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Chacha20State
|
||||||
|
{
|
||||||
|
Chacha20State (): offset (0) {};
|
||||||
|
Chacha20State (Chacha20State &&) = delete;
|
||||||
|
|
||||||
|
Chacha20State & operator += (const Chacha20State & other)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 16; i++)
|
||||||
|
data[i] += other.data[i];
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Copy(const Chacha20State & other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
||||||
|
}
|
||||||
|
uint32_t data[16];
|
||||||
|
Chacha20Block block;
|
||||||
|
size_t offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
||||||
|
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
|
||||||
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -88,6 +88,7 @@ namespace config {
|
||||||
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
|
("http.pass", value<std::string>()->default_value(""), "Password for basic auth (default: random, see logs)")
|
||||||
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
|
("http.strictheaders", value<bool>()->default_value(true), "Enable strict host checking on WebUI")
|
||||||
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
|
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
|
||||||
|
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description httpproxy("HTTP Proxy options");
|
options_description httpproxy("HTTP Proxy options");
|
||||||
|
@ -236,10 +237,27 @@ namespace config {
|
||||||
options_description ntcp2("NTCP2 Options");
|
options_description ntcp2("NTCP2 Options");
|
||||||
ntcp2.add_options()
|
ntcp2.add_options()
|
||||||
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
|
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
|
||||||
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
|
("ntcp2.published", value<bool>()->default_value(false), "Publish NTCP2 (default: disabled)")
|
||||||
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
|
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
options_description nettime("Time sync options");
|
||||||
|
nettime.add_options()
|
||||||
|
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
|
||||||
|
("nettime.ntpservers", value<std::string>()->default_value(
|
||||||
|
"0.pool.ntp.org,"
|
||||||
|
"1.pool.ntp.org,"
|
||||||
|
"2.pool.ntp.org,"
|
||||||
|
"3.pool.ntp.org"
|
||||||
|
), "Comma separated list of NTCP servers")
|
||||||
|
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
|
||||||
|
;
|
||||||
|
|
||||||
|
options_description persist("Network information persisting options");
|
||||||
|
persist.add_options()
|
||||||
|
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
|
||||||
|
;
|
||||||
|
|
||||||
m_OptionsDesc
|
m_OptionsDesc
|
||||||
.add(general)
|
.add(general)
|
||||||
.add(limits)
|
.add(limits)
|
||||||
|
@ -258,6 +276,8 @@ namespace config {
|
||||||
.add(websocket)
|
.add(websocket)
|
||||||
.add(exploratory)
|
.add(exploratory)
|
||||||
.add(ntcp2)
|
.add(ntcp2)
|
||||||
|
.add(nettime)
|
||||||
|
.add(persist)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1087,62 +1087,62 @@ namespace crypto
|
||||||
if (encrypt && len < msgLen + 16) return false;
|
if (encrypt && len < msgLen + 16) return false;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
#if LEGACY_OPENSSL
|
#if LEGACY_OPENSSL
|
||||||
|
chacha::Chacha20State state;
|
||||||
// generate one time poly key
|
// generate one time poly key
|
||||||
uint8_t polyKey[64];
|
chacha::Chacha20Init (state, nonce, key, 0);
|
||||||
|
uint64_t polyKey[8];
|
||||||
memset(polyKey, 0, sizeof(polyKey));
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
chacha20 (polyKey, 64, nonce, key, 0);
|
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
||||||
|
// create Poly1305 hash
|
||||||
// create Poly1305 message
|
Poly1305 polyHash (polyKey);
|
||||||
if (!ad) adLen = 0;
|
if (!ad) adLen = 0;
|
||||||
std::vector<uint8_t> polyMsg(adLen + msgLen + 3*16);
|
|
||||||
size_t offset = 0;
|
|
||||||
uint8_t padding[16]; memset (padding, 0, 16);
|
uint8_t padding[16]; memset (padding, 0, 16);
|
||||||
if (ad)
|
if (ad)
|
||||||
{
|
{
|
||||||
memcpy (polyMsg.data (), ad, adLen); offset += adLen; // additional authenticated data
|
polyHash.Update (ad, adLen);// additional authenticated data
|
||||||
auto rem = adLen & 0x0F; // %16
|
auto rem = adLen & 0x0F; // %16
|
||||||
if (rem)
|
if (rem)
|
||||||
{
|
{
|
||||||
// padding1
|
// padding1
|
||||||
rem = 16 - rem;
|
rem = 16 - rem;
|
||||||
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
|
polyHash.Update (padding, rem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// encrypt/decrypt data and add to hash
|
// encrypt/decrypt data and add to hash
|
||||||
|
Chacha20SetCounter (state, 1);
|
||||||
if (buf != msg)
|
if (buf != msg)
|
||||||
memcpy (buf, msg, msgLen);
|
memcpy (buf, msg, msgLen);
|
||||||
if (encrypt)
|
if (encrypt)
|
||||||
{
|
{
|
||||||
chacha20 (buf, msgLen, nonce, key, 1); // encrypt
|
chacha::Chacha20Encrypt (state, buf, msgLen); // encrypt
|
||||||
memcpy (polyMsg.data () + offset, buf, msgLen); // after encryption
|
polyHash.Update (buf, msgLen); // after encryption
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy (polyMsg.data () + offset, buf, msgLen); // before decryption
|
polyHash.Update (buf, msgLen); // before decryption
|
||||||
chacha20 (buf, msgLen, nonce, key, 1); // decrypt
|
chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt
|
||||||
}
|
}
|
||||||
offset += msgLen; // encrypted data
|
|
||||||
|
|
||||||
auto rem = msgLen & 0x0F; // %16
|
auto rem = msgLen & 0x0F; // %16
|
||||||
if (rem)
|
if (rem)
|
||||||
{
|
{
|
||||||
// padding2
|
// padding2
|
||||||
rem = 16 - rem;
|
rem = 16 - rem;
|
||||||
memcpy (polyMsg.data () + offset, padding, rem); offset += rem;
|
polyHash.Update (padding, rem);
|
||||||
}
|
}
|
||||||
htole64buf (polyMsg.data () + offset, adLen); offset += 8;
|
// adLen and msgLen
|
||||||
htole64buf (polyMsg.data () + offset, msgLen); offset += 8;
|
htole64buf (padding, adLen);
|
||||||
|
htole64buf (padding + 8, msgLen);
|
||||||
|
polyHash.Update (padding, 16);
|
||||||
|
|
||||||
if (encrypt)
|
if (encrypt)
|
||||||
{
|
|
||||||
// calculate Poly1305 tag and write in after encrypted data
|
// calculate Poly1305 tag and write in after encrypted data
|
||||||
Poly1305HMAC ((uint32_t *)(buf + msgLen), (uint32_t *)polyKey, polyMsg.data (), offset);
|
polyHash.Finish ((uint64_t *)(buf + msgLen));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t tag[8];
|
uint64_t tag[4];
|
||||||
// calculate Poly1305 tag
|
// calculate Poly1305 tag
|
||||||
Poly1305HMAC (tag, (uint32_t *)polyKey, polyMsg.data (), offset);
|
polyHash.Finish (tag);
|
||||||
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
|
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1174,6 +1174,56 @@ namespace crypto
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AEADChaCha20Poly1305Encrypt (std::vector<std::pair<void*, std::size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac)
|
||||||
|
{
|
||||||
|
if (bufs.empty ()) return;
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
|
chacha::Chacha20State state;
|
||||||
|
// generate one time poly key
|
||||||
|
chacha::Chacha20Init (state, nonce, key, 0);
|
||||||
|
uint64_t polyKey[8];
|
||||||
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
|
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
||||||
|
Poly1305 polyHash (polyKey);
|
||||||
|
// encrypt buffers
|
||||||
|
Chacha20SetCounter (state, 1);
|
||||||
|
size_t size = 0;
|
||||||
|
for (auto& it: bufs)
|
||||||
|
{
|
||||||
|
chacha::Chacha20Encrypt (state, (uint8_t *)it.first, it.second);
|
||||||
|
polyHash.Update ((uint8_t *)it.first, it.second); // after encryption
|
||||||
|
size += it.second;
|
||||||
|
}
|
||||||
|
// padding
|
||||||
|
uint8_t padding[16];
|
||||||
|
memset (padding, 0, 16);
|
||||||
|
auto rem = size & 0x0F; // %16
|
||||||
|
if (rem)
|
||||||
|
{
|
||||||
|
// padding2
|
||||||
|
rem = 16 - rem;
|
||||||
|
polyHash.Update (padding, rem);
|
||||||
|
}
|
||||||
|
// adLen and msgLen
|
||||||
|
// adLen is always zero
|
||||||
|
htole64buf (padding + 8, size);
|
||||||
|
polyHash.Update (padding, 16);
|
||||||
|
// MAC
|
||||||
|
polyHash.Finish ((uint64_t *)mac);
|
||||||
|
#else
|
||||||
|
int outlen = 0;
|
||||||
|
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||||
|
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||||
|
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||||
|
for (auto& it: bufs)
|
||||||
|
EVP_EncryptUpdate(ctx, (uint8_t *)it.first, &outlen, (uint8_t *)it.first, it.second);
|
||||||
|
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||||
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
||||||
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
|
|
||||||
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
|
@ -108,35 +109,16 @@ namespace crypto
|
||||||
|
|
||||||
void operator^=(const ChipherBlock& other) // XOR
|
void operator^=(const ChipherBlock& other) // XOR
|
||||||
{
|
{
|
||||||
#ifdef __AVX__
|
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
||||||
if (i2p::cpu::avx)
|
{
|
||||||
{
|
for (int i = 0; i < 4; i++)
|
||||||
__asm__
|
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
|
||||||
(
|
}
|
||||||
"vmovups (%[buf]), %%xmm0 \n"
|
|
||||||
"vmovups (%[other]), %%xmm1 \n"
|
|
||||||
"vxorps %%xmm0, %%xmm1, %%xmm0 \n"
|
|
||||||
"vmovups %%xmm0, (%[buf]) \n"
|
|
||||||
:
|
|
||||||
: [buf]"r"(buf), [other]"r"(other.buf)
|
|
||||||
: "%xmm0", "%xmm1", "memory"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
#endif
|
{
|
||||||
{
|
for (int i = 0; i < 16; i++)
|
||||||
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
buf[i] ^= other.buf[i];
|
||||||
{
|
}
|
||||||
// we are good to cast to uint32_t *
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
((uint32_t *)buf)[i] ^= ((uint32_t *)other.buf)[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
buf[i] ^= other.buf[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -301,6 +283,8 @@ namespace crypto
|
||||||
// AEAD/ChaCha20/Poly1305
|
// AEAD/ChaCha20/Poly1305
|
||||||
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
|
bool AEADChaCha20Poly1305 (const uint8_t * msg, size_t msgLen, const uint8_t * ad, size_t adLen, const uint8_t * key, const uint8_t * nonce, uint8_t * buf, size_t len, bool encrypt); // msgLen is len without tag
|
||||||
|
|
||||||
|
void AEADChaCha20Poly1305Encrypt (std::vector<std::pair<void*, std::size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation);
|
void InitCrypto (bool precomputation);
|
||||||
void TerminateCrypto ();
|
void TerminateCrypto ();
|
||||||
|
|
|
@ -411,6 +411,7 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !OPENSSL_X25519
|
||||||
BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
|
BIGNUM * Ed25519::ScalarMul (const BIGNUM * u, const BIGNUM * k, BN_CTX * ctx) const
|
||||||
{
|
{
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
|
@ -488,6 +489,7 @@ namespace crypto
|
||||||
EncodeBN (q1, buf, 32);
|
EncodeBN (q1, buf, 32);
|
||||||
BN_free (p1); BN_free (n); BN_free (q1);
|
BN_free (p1); BN_free (n); BN_free (q1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
|
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
|
#include "Crypto.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -75,8 +76,10 @@ namespace crypto
|
||||||
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
|
EDDSAPoint GeneratePublicKey (const uint8_t * expandedPrivateKey, BN_CTX * ctx) const;
|
||||||
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
||||||
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
#if !OPENSSL_X25519
|
||||||
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
|
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
|
||||||
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
|
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
|
||||||
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
||||||
|
@ -100,8 +103,10 @@ namespace crypto
|
||||||
BIGNUM * DecodeBN (const uint8_t * buf) const;
|
BIGNUM * DecodeBN (const uint8_t * buf) const;
|
||||||
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
|
void EncodeBN (const BIGNUM * bn, uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
|
#if !OPENSSL_X25519
|
||||||
// for x25519
|
// for x25519
|
||||||
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
|
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace i2p
|
||||||
|
|
||||||
enum I2NPMessageType
|
enum I2NPMessageType
|
||||||
{
|
{
|
||||||
|
eI2NPDummyMsg = 0,
|
||||||
eI2NPDatabaseStore = 1,
|
eI2NPDatabaseStore = 1,
|
||||||
eI2NPDatabaseLookup = 2,
|
eI2NPDatabaseLookup = 2,
|
||||||
eI2NPDatabaseSearchReply = 3,
|
eI2NPDatabaseSearchReply = 3,
|
||||||
|
|
|
@ -695,8 +695,7 @@ namespace transport
|
||||||
SendTerminationAndTerminate (eNTCP2IncorrectSParameter);
|
SendTerminationAndTerminate (eNTCP2IncorrectSParameter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice
|
||||||
i2p::data::netdb.AddRouterInfo (buf.data () + 4, size - 1); // TODO: should insert ri and not parse it twice
|
|
||||||
// TODO: process options
|
// TODO: process options
|
||||||
|
|
||||||
// ready to communicate
|
// ready to communicate
|
||||||
|
@ -861,7 +860,7 @@ namespace transport
|
||||||
case eNTCP2BlkRouterInfo:
|
case eNTCP2BlkRouterInfo:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]);
|
LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]);
|
||||||
i2p::data::netdb.AddRouterInfo (frame + offset + 1, size - 1);
|
i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset, size));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eNTCP2BlkI2NPMessage:
|
case eNTCP2BlkI2NPMessage:
|
||||||
|
@ -873,6 +872,7 @@ namespace transport
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto nextMsg = NewI2NPMessage (size);
|
auto nextMsg = NewI2NPMessage (size);
|
||||||
|
nextMsg->Align (12); // for possible tunnel msg
|
||||||
nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header
|
nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header
|
||||||
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
|
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
|
||||||
nextMsg->FromNTCP2 ();
|
nextMsg->FromNTCP2 ();
|
||||||
|
|
|
@ -73,6 +73,8 @@ namespace transport
|
||||||
eNTCP2Banned, // 17
|
eNTCP2Banned, // 17
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// RouterInfo flags
|
||||||
|
const uint8_t NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
|
||||||
|
|
||||||
typedef std::array<uint8_t, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE> NTCP2FrameBuffer;
|
typedef std::array<uint8_t, NTCP2_UNENCRYPTED_FRAME_MAX_SIZE> NTCP2FrameBuffer;
|
||||||
struct NTCP2Establisher
|
struct NTCP2Establisher
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "I2NPProtocol.h"
|
#include "I2NPProtocol.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
|
#include "NTCP2.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Garlic.h"
|
#include "Garlic.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
|
@ -25,7 +26,7 @@ namespace data
|
||||||
{
|
{
|
||||||
NetDb netdb;
|
NetDb netdb;
|
||||||
|
|
||||||
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false)
|
NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_PersistProfiles (true), m_HiddenMode(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,10 +44,12 @@ namespace data
|
||||||
m_Families.LoadCertificates ();
|
m_Families.LoadCertificates ();
|
||||||
Load ();
|
Load ();
|
||||||
|
|
||||||
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
uint16_t threshold; i2p::config::GetOption("reseed.threshold", threshold);
|
||||||
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
if (m_RouterInfos.size () < threshold) // reseed if # of router less than threshold
|
||||||
Reseed ();
|
Reseed ();
|
||||||
|
|
||||||
|
i2p::config::GetOption("persist.profiles", m_PersistProfiles);
|
||||||
|
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread = new std::thread (std::bind (&NetDb::Run, this));
|
m_Thread = new std::thread (std::bind (&NetDb::Run, this));
|
||||||
}
|
}
|
||||||
|
@ -55,8 +58,9 @@ namespace data
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
{
|
{
|
||||||
for (auto& it: m_RouterInfos)
|
if (m_PersistProfiles)
|
||||||
it.second->SaveProfile ();
|
for (auto& it: m_RouterInfos)
|
||||||
|
it.second->SaveProfile ();
|
||||||
DeleteObsoleteProfiles ();
|
DeleteObsoleteProfiles ();
|
||||||
m_RouterInfos.clear ();
|
m_RouterInfos.clear ();
|
||||||
m_Floodfills.clear ();
|
m_Floodfills.clear ();
|
||||||
|
@ -98,6 +102,10 @@ namespace data
|
||||||
case eI2NPDatabaseLookup:
|
case eI2NPDatabaseLookup:
|
||||||
HandleDatabaseLookupMsg (msg);
|
HandleDatabaseLookupMsg (msg);
|
||||||
break;
|
break;
|
||||||
|
case eI2NPDummyMsg:
|
||||||
|
// plain RouterInfo from NTCP2 with flags for now
|
||||||
|
HandleNTCP2RouterInfoMsg (msg);
|
||||||
|
break;
|
||||||
default: // WTF?
|
default: // WTF?
|
||||||
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
|
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
|
||||||
//i2p::HandleI2NPMessage (msg);
|
//i2p::HandleI2NPMessage (msg);
|
||||||
|
@ -162,22 +170,38 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::SetHidden(bool hide)
|
||||||
|
{
|
||||||
|
// TODO: remove reachable addresses from router info
|
||||||
|
m_HiddenMode = hide;
|
||||||
|
}
|
||||||
|
|
||||||
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||||
|
{
|
||||||
|
bool updated;
|
||||||
|
AddRouterInfo (buf, len, updated);
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated)
|
||||||
{
|
{
|
||||||
IdentityEx identity;
|
IdentityEx identity;
|
||||||
if (identity.FromBuffer (buf, len))
|
if (identity.FromBuffer (buf, len))
|
||||||
return AddRouterInfo (identity.GetIdentHash (), buf, len);
|
return AddRouterInfo (identity.GetIdentHash (), buf, len, updated);
|
||||||
return false;
|
updated = false;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::SetHidden(bool hide) {
|
|
||||||
// TODO: remove reachable addresses from router info
|
|
||||||
m_HiddenMode = hide;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
bool updated = true;
|
bool updated;
|
||||||
|
AddRouterInfo (ident, buf, len, updated);
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated)
|
||||||
|
{
|
||||||
|
updated = true;
|
||||||
auto r = FindRouter (ident);
|
auto r = FindRouter (ident);
|
||||||
if (r)
|
if (r)
|
||||||
{
|
{
|
||||||
|
@ -223,7 +247,7 @@ namespace data
|
||||||
}
|
}
|
||||||
// take care about requested destination
|
// take care about requested destination
|
||||||
m_Requests.RequestComplete (ident, r);
|
m_Requests.RequestComplete (ident, r);
|
||||||
return updated;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len,
|
bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len,
|
||||||
|
@ -518,7 +542,7 @@ namespace data
|
||||||
{
|
{
|
||||||
if (it->second->IsUnreachable ())
|
if (it->second->IsUnreachable ())
|
||||||
{
|
{
|
||||||
it->second->SaveProfile ();
|
if (m_PersistProfiles) it->second->SaveProfile ();
|
||||||
it = m_RouterInfos.erase (it);
|
it = m_RouterInfos.erase (it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -570,6 +594,17 @@ namespace data
|
||||||
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
|
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m)
|
||||||
|
{
|
||||||
|
uint8_t flood = m->GetPayload ()[0] & NTCP2_ROUTER_INFO_FLAG_REQUEST_FLOOD;
|
||||||
|
bool updated;
|
||||||
|
auto ri = AddRouterInfo (m->GetPayload () + 1, m->GetPayloadLength () - 1, updated); // without flags
|
||||||
|
if (flood && updated && context.IsFloodfill () && ri)
|
||||||
|
{
|
||||||
|
auto floodMsg = CreateDatabaseStoreMsg (ri, 0); // replyToken = 0
|
||||||
|
Flood (ri->GetIdentHash (), floodMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NetDb::HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> m)
|
void NetDb::HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> m)
|
||||||
{
|
{
|
||||||
|
@ -649,22 +684,7 @@ namespace data
|
||||||
{
|
{
|
||||||
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
|
memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen);
|
||||||
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore);
|
||||||
std::set<IdentHash> excluded;
|
Flood (ident, floodMsg);
|
||||||
excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself
|
|
||||||
excluded.insert (ident); // don't flood back
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
auto floodfill = GetClosestFloodfill (ident, excluded);
|
|
||||||
if (floodfill)
|
|
||||||
{
|
|
||||||
auto h = floodfill->GetIdentHash();
|
|
||||||
LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64());
|
|
||||||
transports.SendMessage (h, CopyI2NPMessage(floodMsg));
|
|
||||||
excluded.insert (h);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len);
|
LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len);
|
||||||
|
@ -965,6 +985,26 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::Flood (const IdentHash& ident, std::shared_ptr<I2NPMessage> floodMsg)
|
||||||
|
{
|
||||||
|
std::set<IdentHash> excluded;
|
||||||
|
excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself
|
||||||
|
excluded.insert (ident); // don't flood back
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
auto floodfill = GetClosestFloodfill (ident, excluded);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
auto h = floodfill->GetIdentHash();
|
||||||
|
LogPrint(eLogDebug, "NetDb: Flood lease set for ", ident.ToBase32(), " to ", h.ToBase64());
|
||||||
|
transports.SendMessage (h, CopyI2NPMessage(floodMsg));
|
||||||
|
excluded.insert (h);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter () const
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouter () const
|
||||||
{
|
{
|
||||||
return GetRandomRouter (
|
return GetRandomRouter (
|
||||||
|
|
|
@ -65,7 +65,8 @@ namespace data
|
||||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||||
|
@ -110,13 +111,16 @@ namespace data
|
||||||
void Run (); // exploratory thread
|
void Run (); // exploratory thread
|
||||||
void Explore (int numDestinations);
|
void Explore (int numDestinations);
|
||||||
void Publish ();
|
void Publish ();
|
||||||
|
void Flood (const IdentHash& ident, std::shared_ptr<I2NPMessage> floodMsg);
|
||||||
void ManageLeaseSets ();
|
void ManageLeaseSets ();
|
||||||
void ManageRequests ();
|
void ManageRequests ();
|
||||||
|
|
||||||
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
|
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
|
||||||
|
|
||||||
template<typename Filter>
|
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
|
||||||
|
template<typename Filter>
|
||||||
|
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -140,6 +144,8 @@ namespace data
|
||||||
friend class NetDbRequests;
|
friend class NetDbRequests;
|
||||||
NetDbRequests m_Requests;
|
NetDbRequests m_Requests;
|
||||||
|
|
||||||
|
bool m_PersistProfiles;
|
||||||
|
|
||||||
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
||||||
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
||||||
|
|
||||||
|
|
|
@ -6,246 +6,20 @@
|
||||||
Kovri go write your own code
|
Kovri go write your own code
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
namespace poly1305
|
|
||||||
|
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz)
|
||||||
{
|
{
|
||||||
|
Poly1305 p(key);
|
||||||
struct LongBlock
|
|
||||||
{
|
|
||||||
unsigned long data[17];
|
|
||||||
operator unsigned long * ()
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Block
|
|
||||||
{
|
|
||||||
unsigned char data[17];
|
|
||||||
|
|
||||||
operator uint8_t * ()
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block & operator += (const Block & other)
|
|
||||||
{
|
|
||||||
unsigned short u;
|
|
||||||
unsigned int i;
|
|
||||||
for(u = 0, i = 0; i < 17; i++)
|
|
||||||
{
|
|
||||||
u += (unsigned short) data[i] + (unsigned short) other.data[i];
|
|
||||||
data[i] = (unsigned char) u & 0xff;
|
|
||||||
u >>= 8;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block & operator %=(const LongBlock & other)
|
|
||||||
{
|
|
||||||
unsigned long u;
|
|
||||||
unsigned int i;
|
|
||||||
u = 0;
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
u += other.data[i];
|
|
||||||
data[i] = (unsigned char)u & 0xff;
|
|
||||||
u >>= 8;
|
|
||||||
}
|
|
||||||
u += other.data[16];
|
|
||||||
data[16] = (unsigned char)u & 0x03;
|
|
||||||
u >>= 2;
|
|
||||||
u += (u << 2);
|
|
||||||
for (i = 0; i < 16; i++) {
|
|
||||||
u += data[i];
|
|
||||||
data[i] = (unsigned char)u & 0xff;
|
|
||||||
u >>= 8;
|
|
||||||
}
|
|
||||||
data[16] += (unsigned char)u;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block & operator = (const Block & other)
|
|
||||||
{
|
|
||||||
memcpy(data, other.data, sizeof(data));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Block & operator ~ ()
|
|
||||||
{
|
|
||||||
static const Block minusp = {
|
|
||||||
0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0xfc
|
|
||||||
};
|
|
||||||
Block orig;
|
|
||||||
unsigned char neg;
|
|
||||||
unsigned int i;
|
|
||||||
orig = *this;
|
|
||||||
*this += minusp;
|
|
||||||
neg = -(data[16] >> 7);
|
|
||||||
for(i = 0; i < 17; i++)
|
|
||||||
data[i] ^= neg & (orig.data[i] ^ data[i]);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PutKey(const uint8_t * key)
|
|
||||||
{
|
|
||||||
data[0] = key[0] & 0xff;
|
|
||||||
data[1] = key[1] & 0xff;
|
|
||||||
data[2] = key[2] & 0xff;
|
|
||||||
data[3] = key[3] & 0x0f;
|
|
||||||
data[4] = key[4] & 0xfc;
|
|
||||||
data[5] = key[5] & 0xff;
|
|
||||||
data[6] = key[6] & 0xff;
|
|
||||||
data[7] = key[7] & 0x0f;
|
|
||||||
data[8] = key[8] & 0xfc;
|
|
||||||
data[9] = key[9] & 0xff;
|
|
||||||
data[10] = key[10] & 0xff;
|
|
||||||
data[11] = key[11] & 0x0f;
|
|
||||||
data[12] = key[12] & 0xfc;
|
|
||||||
data[13] = key[13] & 0xff;
|
|
||||||
data[14] = key[14] & 0xff;
|
|
||||||
data[15] = key[15] & 0x0f;
|
|
||||||
data[16] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Put(const uint8_t * d, uint8_t last=0)
|
|
||||||
{
|
|
||||||
memcpy(data, d, 17);
|
|
||||||
data[16] = last;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Buffer
|
|
||||||
{
|
|
||||||
uint8_t data[POLY1305_BLOCK_BYTES];
|
|
||||||
|
|
||||||
operator uint8_t * ()
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Poly1305
|
|
||||||
{
|
|
||||||
#if (__GNUC__ == 4) && (__GNUC_MINOR__ < 8) // older than gcc 4.8
|
|
||||||
Poly1305(const uint8_t * key) : m_Leftover(0), m_Final(0)
|
|
||||||
{
|
|
||||||
memset (&m_H, 0, sizeof (m_H));
|
|
||||||
#else
|
|
||||||
Poly1305(const uint8_t * key) : m_Leftover(0), m_H{0}, m_Final(0)
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
m_R.PutKey(key);
|
|
||||||
m_Pad.Put(key + 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update(const uint8_t * buf, size_t sz)
|
|
||||||
{
|
|
||||||
// process leftover
|
|
||||||
if(m_Leftover)
|
|
||||||
{
|
|
||||||
size_t want = POLY1305_BLOCK_BYTES - m_Leftover;
|
|
||||||
if(want > sz) want = sz;
|
|
||||||
memcpy(m_Buffer + m_Leftover, buf, want);
|
|
||||||
sz -= want;
|
|
||||||
buf += want;
|
|
||||||
m_Leftover += want;
|
|
||||||
if(m_Leftover < POLY1305_BLOCK_BYTES) return;
|
|
||||||
Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
|
|
||||||
m_Leftover = 0;
|
|
||||||
}
|
|
||||||
// process blocks
|
|
||||||
if(sz >= POLY1305_BLOCK_BYTES)
|
|
||||||
{
|
|
||||||
size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1));
|
|
||||||
Blocks(buf, want);
|
|
||||||
buf += want;
|
|
||||||
sz -= want;
|
|
||||||
}
|
|
||||||
// leftover
|
|
||||||
if(sz)
|
|
||||||
{
|
|
||||||
memcpy(m_Buffer+m_Leftover, buf, sz);
|
|
||||||
m_Leftover += sz;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Blocks(const uint8_t * buf, size_t sz)
|
|
||||||
{
|
|
||||||
const unsigned char hi = m_Final ^ 1;
|
|
||||||
while (sz >= POLY1305_BLOCK_BYTES) {
|
|
||||||
|
|
||||||
unsigned long u;
|
|
||||||
|
|
||||||
unsigned int i, j;
|
|
||||||
m_Msg.Put(buf, hi);
|
|
||||||
/* h += m */
|
|
||||||
m_H += m_Msg;
|
|
||||||
|
|
||||||
/* h *= r */
|
|
||||||
for (i = 0; i < 17; i++) {
|
|
||||||
u = 0;
|
|
||||||
for (j = 0; j <= i ; j++) {
|
|
||||||
u += (unsigned short)m_H.data[j] * m_R.data[i - j];
|
|
||||||
}
|
|
||||||
for (j = i + 1; j < 17; j++) {
|
|
||||||
unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j];
|
|
||||||
v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */
|
|
||||||
u += v;
|
|
||||||
}
|
|
||||||
m_HR[i] = u;
|
|
||||||
}
|
|
||||||
/* (partial) h %= p */
|
|
||||||
m_H %= m_HR;
|
|
||||||
buf += POLY1305_BLOCK_BYTES;
|
|
||||||
sz -= POLY1305_BLOCK_BYTES;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Finish(uint32_t *& out)
|
|
||||||
{
|
|
||||||
// process leftovers
|
|
||||||
if(m_Leftover)
|
|
||||||
{
|
|
||||||
size_t idx = m_Leftover;
|
|
||||||
m_Buffer[idx++] = 1;
|
|
||||||
for(; idx < POLY1305_BLOCK_BYTES; idx++)
|
|
||||||
m_Buffer[idx] = 0;
|
|
||||||
m_Final = 1;
|
|
||||||
Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
|
|
||||||
}
|
|
||||||
|
|
||||||
// freeze H
|
|
||||||
~m_H;
|
|
||||||
// add pad
|
|
||||||
m_H += m_Pad;
|
|
||||||
// copy digest
|
|
||||||
memcpy(out, m_H, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t m_Leftover;
|
|
||||||
poly1305::Buffer m_Buffer;
|
|
||||||
poly1305::Block m_H;
|
|
||||||
poly1305::Block m_R;
|
|
||||||
poly1305::Block m_Pad;
|
|
||||||
poly1305::Block m_Msg;
|
|
||||||
poly1305::LongBlock m_HR;
|
|
||||||
uint8_t m_Final;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz)
|
|
||||||
{
|
|
||||||
const uint8_t * k = (const uint8_t *) key;
|
|
||||||
Poly1305 p(k);
|
|
||||||
p.Update(buf, sz);
|
p.Update(buf, sz);
|
||||||
p.Finish(out);
|
p.Finish(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -9,20 +9,253 @@
|
||||||
#define LIBI2PD_POLY1305_H
|
#define LIBI2PD_POLY1305_H
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include "Crypto.h"
|
||||||
|
|
||||||
|
#if LEGACY_OPENSSL
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
const std::size_t POLY1305_DIGEST_BYTES = 16;
|
const std::size_t POLY1305_DIGEST_BYTES = 16;
|
||||||
const std::size_t POLY1305_DIGEST_DWORDS = 4;
|
const std::size_t POLY1305_DIGEST_DWORDS = 4;
|
||||||
const std::size_t POLY1305_KEY_BYTES = 32;
|
const std::size_t POLY1305_KEY_BYTES = 32;
|
||||||
const std::size_t POLY1305_KEY_DWORDS = 8;
|
const std::size_t POLY1305_KEY_DWORDS = 8;
|
||||||
const std::size_t POLY1305_BLOCK_BYTES = 16;
|
const std::size_t POLY1305_BLOCK_BYTES = 16;
|
||||||
|
|
||||||
|
namespace poly1305
|
||||||
|
{
|
||||||
|
|
||||||
|
struct LongBlock
|
||||||
|
{
|
||||||
|
unsigned long data[17];
|
||||||
|
operator unsigned long * ()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Block
|
||||||
|
{
|
||||||
|
unsigned char data[17];
|
||||||
|
|
||||||
|
void Zero()
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
operator uint8_t * ()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block & operator += (const Block & other)
|
||||||
|
{
|
||||||
|
unsigned short u;
|
||||||
|
unsigned int i;
|
||||||
|
for(u = 0, i = 0; i < 17; i++)
|
||||||
|
{
|
||||||
|
u += (unsigned short) data[i] + (unsigned short) other.data[i];
|
||||||
|
data[i] = (unsigned char) u & 0xff;
|
||||||
|
u >>= 8;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block & operator %=(const LongBlock & other)
|
||||||
|
{
|
||||||
|
unsigned long u;
|
||||||
|
unsigned int i;
|
||||||
|
u = 0;
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
u += other.data[i];
|
||||||
|
data[i] = (unsigned char)u & 0xff;
|
||||||
|
u >>= 8;
|
||||||
|
}
|
||||||
|
u += other.data[16];
|
||||||
|
data[16] = (unsigned char)u & 0x03;
|
||||||
|
u >>= 2;
|
||||||
|
u += (u << 2);
|
||||||
|
for (i = 0; i < 16; i++) {
|
||||||
|
u += data[i];
|
||||||
|
data[i] = (unsigned char)u & 0xff;
|
||||||
|
u >>= 8;
|
||||||
|
}
|
||||||
|
data[16] += (unsigned char)u;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block & operator = (const Block & other)
|
||||||
|
{
|
||||||
|
memcpy(data, other.data, sizeof(data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block & operator ~ ()
|
||||||
|
{
|
||||||
|
static const Block minusp = {
|
||||||
|
0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0xfc
|
||||||
|
};
|
||||||
|
Block orig;
|
||||||
|
unsigned char neg;
|
||||||
|
unsigned int i;
|
||||||
|
orig = *this;
|
||||||
|
*this += minusp;
|
||||||
|
neg = -(data[16] >> 7);
|
||||||
|
for(i = 0; i < 17; i++)
|
||||||
|
data[i] ^= neg & (orig.data[i] ^ data[i]);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PutKey(const uint64_t * key_l)
|
||||||
|
{
|
||||||
|
const uint8_t * key = (const uint8_t*) key_l;
|
||||||
|
data[0] = key[0] & 0xff;
|
||||||
|
data[1] = key[1] & 0xff;
|
||||||
|
data[2] = key[2] & 0xff;
|
||||||
|
data[3] = key[3] & 0x0f;
|
||||||
|
data[4] = key[4] & 0xfc;
|
||||||
|
data[5] = key[5] & 0xff;
|
||||||
|
data[6] = key[6] & 0xff;
|
||||||
|
data[7] = key[7] & 0x0f;
|
||||||
|
data[8] = key[8] & 0xfc;
|
||||||
|
data[9] = key[9] & 0xff;
|
||||||
|
data[10] = key[10] & 0xff;
|
||||||
|
data[11] = key[11] & 0x0f;
|
||||||
|
data[12] = key[12] & 0xfc;
|
||||||
|
data[13] = key[13] & 0xff;
|
||||||
|
data[14] = key[14] & 0xff;
|
||||||
|
data[15] = key[15] & 0x0f;
|
||||||
|
data[16] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Int_t>
|
||||||
|
void Put(const Int_t * d, uint8_t last=0)
|
||||||
|
{
|
||||||
|
memcpy(data, d, 16);
|
||||||
|
data[16] = last;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Buffer
|
||||||
|
{
|
||||||
|
uint8_t data[POLY1305_BLOCK_BYTES];
|
||||||
|
|
||||||
|
operator uint8_t * ()
|
||||||
|
{
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Poly1305
|
||||||
|
{
|
||||||
|
Poly1305(const uint64_t * key)
|
||||||
|
{
|
||||||
|
m_Leftover = 0;
|
||||||
|
m_H.Zero();
|
||||||
|
m_Final = 0;
|
||||||
|
m_R.PutKey(key);
|
||||||
|
m_Pad.Put(key + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update(const uint8_t * buf, size_t sz)
|
||||||
|
{
|
||||||
|
// process leftover
|
||||||
|
if(m_Leftover)
|
||||||
|
{
|
||||||
|
size_t want = POLY1305_BLOCK_BYTES - m_Leftover;
|
||||||
|
if(want > sz) want = sz;
|
||||||
|
memcpy(m_Buffer + m_Leftover, buf, want);
|
||||||
|
sz -= want;
|
||||||
|
buf += want;
|
||||||
|
m_Leftover += want;
|
||||||
|
if(m_Leftover < POLY1305_BLOCK_BYTES) return;
|
||||||
|
Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
|
||||||
|
m_Leftover = 0;
|
||||||
|
}
|
||||||
|
// process blocks
|
||||||
|
if(sz >= POLY1305_BLOCK_BYTES)
|
||||||
|
{
|
||||||
|
size_t want = (sz & ~(POLY1305_BLOCK_BYTES - 1));
|
||||||
|
Blocks(buf, want);
|
||||||
|
buf += want;
|
||||||
|
sz -= want;
|
||||||
|
}
|
||||||
|
// leftover
|
||||||
|
if(sz)
|
||||||
|
{
|
||||||
|
memcpy(m_Buffer+m_Leftover, buf, sz);
|
||||||
|
m_Leftover += sz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blocks(const uint8_t * buf, size_t sz)
|
||||||
|
{
|
||||||
|
const unsigned char hi = m_Final ^ 1;
|
||||||
|
while (sz >= POLY1305_BLOCK_BYTES) {
|
||||||
|
unsigned long u;
|
||||||
|
unsigned int i, j;
|
||||||
|
m_Msg.Put(buf, hi);
|
||||||
|
/* h += m */
|
||||||
|
m_H += m_Msg;
|
||||||
|
|
||||||
|
/* h *= r */
|
||||||
|
for (i = 0; i < 17; i++) {
|
||||||
|
u = 0;
|
||||||
|
for (j = 0; j <= i ; j++) {
|
||||||
|
u += (unsigned short)m_H.data[j] * m_R.data[i - j];
|
||||||
|
}
|
||||||
|
for (j = i + 1; j < 17; j++) {
|
||||||
|
unsigned long v = (unsigned short)m_H.data[j] * m_R.data[i + 17 - j];
|
||||||
|
v = ((v << 8) + (v << 6)); /* v *= (5 << 6); */
|
||||||
|
u += v;
|
||||||
|
}
|
||||||
|
m_HR[i] = u;
|
||||||
|
}
|
||||||
|
/* (partial) h %= p */
|
||||||
|
m_H %= m_HR;
|
||||||
|
buf += POLY1305_BLOCK_BYTES;
|
||||||
|
sz -= POLY1305_BLOCK_BYTES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finish(uint64_t * out)
|
||||||
|
{
|
||||||
|
// process leftovers
|
||||||
|
if(m_Leftover)
|
||||||
|
{
|
||||||
|
size_t idx = m_Leftover;
|
||||||
|
m_Buffer[idx++] = 1;
|
||||||
|
for(; idx < POLY1305_BLOCK_BYTES; idx++)
|
||||||
|
m_Buffer[idx] = 0;
|
||||||
|
m_Final = 1;
|
||||||
|
Blocks(m_Buffer, POLY1305_BLOCK_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// freeze H
|
||||||
|
~m_H;
|
||||||
|
// add pad
|
||||||
|
m_H += m_Pad;
|
||||||
|
// copy digest
|
||||||
|
memcpy(out, m_H, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t m_Leftover;
|
||||||
|
poly1305::Buffer m_Buffer;
|
||||||
|
poly1305::Block m_H;
|
||||||
|
poly1305::Block m_R;
|
||||||
|
poly1305::Block m_Pad;
|
||||||
|
poly1305::Block m_Msg;
|
||||||
|
poly1305::LongBlock m_HR;
|
||||||
|
uint8_t m_Final;
|
||||||
|
};
|
||||||
|
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
|
||||||
|
|
||||||
void Poly1305HMAC(uint32_t * out, const uint32_t * key, const uint8_t * buf, std::size_t sz);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#define SIPHASH_H
|
#define SIPHASH_H
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include "Crypto.h"
|
||||||
|
|
||||||
|
#if !OPENSSL_SIPHASH
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
|
@ -148,5 +150,6 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <chrono>
|
||||||
|
#include <future>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include "Config.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
|
@ -15,10 +19,30 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
|
static uint64_t GetLocalMillisecondsSinceEpoch ()
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch()).count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t GetLocalHoursSinceEpoch ()
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<std::chrono::hours>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch()).count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t GetLocalSecondsSinceEpoch ()
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
std::chrono::system_clock::now().time_since_epoch()).count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int64_t g_TimeOffset = 0; // in seconds
|
static int64_t g_TimeOffset = 0; // in seconds
|
||||||
|
|
||||||
void SyncTimeWithNTP (const std::string& address)
|
static void SyncTimeWithNTP (const std::string& address)
|
||||||
{
|
{
|
||||||
|
LogPrint (eLogInfo, "Timestamp: NTP request to ", address);
|
||||||
boost::asio::io_service service;
|
boost::asio::io_service service;
|
||||||
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
|
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
@ -48,18 +72,111 @@ namespace util
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTP error: ", e.what ());
|
LogPrint (eLogError, "Timestamp: NTP error: ", e.what ());
|
||||||
}
|
}
|
||||||
if (len >= 8)
|
if (len >= 8)
|
||||||
{
|
{
|
||||||
auto ourTs = GetSecondsSinceEpoch ();
|
auto ourTs = GetLocalSecondsSinceEpoch ();
|
||||||
uint32_t ts = bufbe32toh (buf + 32);
|
uint32_t ts = bufbe32toh (buf + 32);
|
||||||
if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900
|
if (ts > 2208988800U) ts -= 2208988800U; // 1/1/1970 from 1/1/1900
|
||||||
g_TimeOffset = ts - ourTs;
|
g_TimeOffset = ts - ourTs;
|
||||||
LogPrint (eLogInfo, address, " time offset from system time is ", g_TimeOffset, " seconds");
|
LogPrint (eLogInfo, "Timestamp: ", address, " time offset from system time is ", g_TimeOffset, " seconds");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Timestamp: Couldn't open UDP socket");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Timestamp: Couldn't resove address ", address);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTPTimeSync::NTPTimeSync (): m_IsRunning (false), m_Timer (m_Service)
|
||||||
|
{
|
||||||
|
i2p::config::GetOption("nettime.ntpsyncinterval", m_SyncInterval);
|
||||||
|
std::string ntpservers; i2p::config::GetOption("nettime.ntpservers", ntpservers);
|
||||||
|
boost::split (m_NTPServersList, ntpservers, boost::is_any_of(","), boost::token_compress_on);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTPTimeSync::~NTPTimeSync ()
|
||||||
|
{
|
||||||
|
Stop ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NTPTimeSync::Start()
|
||||||
|
{
|
||||||
|
if (m_NTPServersList.size () > 0)
|
||||||
|
{
|
||||||
|
m_IsRunning = true;
|
||||||
|
LogPrint(eLogInfo, "Timestamp: NTP time sync starting");
|
||||||
|
m_Service.post (std::bind (&NTPTimeSync::Sync, this));
|
||||||
|
m_Thread.reset (new std::thread (std::bind (&NTPTimeSync::Run, this)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Timestamp: No NTP server found");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NTPTimeSync::Stop ()
|
||||||
|
{
|
||||||
|
if (m_IsRunning)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "Timestamp: NTP time sync stopping");
|
||||||
|
m_IsRunning = false;
|
||||||
|
m_Timer.cancel ();
|
||||||
|
m_Service.stop ();
|
||||||
|
if (m_Thread)
|
||||||
|
{
|
||||||
|
m_Thread->join ();
|
||||||
|
m_Thread.reset (nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NTPTimeSync::Run ()
|
||||||
|
{
|
||||||
|
while (m_IsRunning)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Service.run ();
|
||||||
|
}
|
||||||
|
catch (std::exception& ex)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Timestamp: NTP time sync exception: ", ex.what ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NTPTimeSync::Sync ()
|
||||||
|
{
|
||||||
|
if (m_NTPServersList.size () > 0)
|
||||||
|
SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]);
|
||||||
|
else
|
||||||
|
m_IsRunning = false;
|
||||||
|
|
||||||
|
if (m_IsRunning)
|
||||||
|
{
|
||||||
|
m_Timer.expires_from_now (boost::posix_time::hours (m_SyncInterval));
|
||||||
|
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
Sync ();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GetMillisecondsSinceEpoch ()
|
||||||
|
{
|
||||||
|
return GetLocalMillisecondsSinceEpoch () + g_TimeOffset*1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetHoursSinceEpoch ()
|
||||||
|
{
|
||||||
|
return GetLocalHoursSinceEpoch () + g_TimeOffset/3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t GetSecondsSinceEpoch ()
|
||||||
|
{
|
||||||
|
return GetLocalSecondsSinceEpoch () + g_TimeOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,29 +2,43 @@
|
||||||
#define TIMESTAMP_H__
|
#define TIMESTAMP_H__
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <chrono>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace util
|
namespace util
|
||||||
{
|
{
|
||||||
inline uint64_t GetMillisecondsSinceEpoch ()
|
uint64_t GetMillisecondsSinceEpoch ();
|
||||||
{
|
uint32_t GetHoursSinceEpoch ();
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
uint64_t GetSecondsSinceEpoch ();
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint32_t GetHoursSinceEpoch ()
|
class NTPTimeSync
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::hours>(
|
public:
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint64_t GetSecondsSinceEpoch ()
|
NTPTimeSync ();
|
||||||
{
|
~NTPTimeSync ();
|
||||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
void Start ();
|
||||||
}
|
void Stop ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void Run ();
|
||||||
|
void Sync ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool m_IsRunning;
|
||||||
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
|
boost::asio::io_service m_Service;
|
||||||
|
boost::asio::deadline_timer m_Timer;
|
||||||
|
int m_SyncInterval;
|
||||||
|
std::vector<std::string> m_NTPServersList;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,11 @@ namespace transport
|
||||||
|
|
||||||
void DHKeysPairSupplier::Stop ()
|
void DHKeysPairSupplier::Stop ()
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
{
|
||||||
m_Acquired.notify_one ();
|
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||||
|
m_IsRunning = false;
|
||||||
|
m_Acquired.notify_one ();
|
||||||
|
}
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
{
|
{
|
||||||
m_Thread->join ();
|
m_Thread->join ();
|
||||||
|
@ -50,19 +53,20 @@ namespace transport
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
int num, total = 0;
|
int num, total = 0;
|
||||||
while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 20)
|
while ((num = m_QueueSize - (int)m_Queue.size ()) > 0 && total < 10)
|
||||||
{
|
{
|
||||||
CreateDHKeysPairs (num);
|
CreateDHKeysPairs (num);
|
||||||
total += num;
|
total += num;
|
||||||
}
|
}
|
||||||
if (total >= 20)
|
if (total >= 10)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time");
|
LogPrint (eLogWarning, "Transports: ", total, " DH keys generated at the time");
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // take a break
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
std::unique_lock<std::mutex> l(m_AcquiredMutex);
|
||||||
|
if (!m_IsRunning) break;
|
||||||
m_Acquired.wait (l); // wait for element gets acquired
|
m_Acquired.wait (l); // wait for element gets acquired
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,7 +817,6 @@ namespace transport
|
||||||
if (profile)
|
if (profile)
|
||||||
{
|
{
|
||||||
profile->TunnelNonReplied();
|
profile->TunnelNonReplied();
|
||||||
profile->Save(it->first);
|
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
it = m_Peers.erase (it);
|
it = m_Peers.erase (it);
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
||||||
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
||||||
|
|
||||||
|
/* // No more needed. Exists in MinGW.
|
||||||
int inet_pton(int af, const char *src, void *dst)
|
int inet_pton(int af, const char *src, void *dst)
|
||||||
{ /* This function was written by Petar Korponai?. See
|
{ // This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
|
||||||
http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */
|
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
int size = sizeof (ss);
|
int size = sizeof (ss);
|
||||||
char src_copy[INET6_ADDRSTRLEN + 1];
|
char src_copy[INET6_ADDRSTRLEN + 1];
|
||||||
|
@ -45,7 +45,7 @@ http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}*/
|
||||||
#else /* !WIN32 => UNIX */
|
#else /* !WIN32 => UNIX */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
|
|
@ -390,6 +390,10 @@ namespace proxy {
|
||||||
std::string origURI = m_ClientRequest.uri; // TODO: what do we need to change uri for?
|
std::string origURI = m_ClientRequest.uri; // TODO: what do we need to change uri for?
|
||||||
m_ClientRequest.uri = m_ClientRequestURL.to_string();
|
m_ClientRequest.uri = m_ClientRequestURL.to_string();
|
||||||
|
|
||||||
|
// update User-Agent to ESR version of Firefox, same as Tor Browser below version 8, for non-HTTPS connections
|
||||||
|
if(m_ClientRequest.method != "CONNECT")
|
||||||
|
m_ClientRequest.UpdateHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0");
|
||||||
|
|
||||||
m_ClientRequest.write(m_ClientRequestBuffer);
|
m_ClientRequest.write(m_ClientRequestBuffer);
|
||||||
m_ClientRequestBuffer << m_recv_buf.substr(m_req_len);
|
m_ClientRequestBuffer << m_recv_buf.substr(m_req_len);
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<translation type="qt" />
|
<translation type="qt" />
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.22.0" date="2018-11-09" />
|
||||||
<release version="2.21.1" date="2018-10-22" />
|
<release version="2.21.1" date="2018-10-22" />
|
||||||
<release version="2.21.0" date="2018-10-04" />
|
<release version="2.21.0" date="2018-10-04" />
|
||||||
</releases>
|
</releases>
|
||||||
|
|
|
@ -51,4 +51,10 @@ int main ()
|
||||||
uint8_t buf1[114];
|
uint8_t buf1[114];
|
||||||
assert (i2p::crypto::AEADChaCha20Poly1305 (buf, 114, ad, 12, key, nonce, buf1, 114, false));
|
assert (i2p::crypto::AEADChaCha20Poly1305 (buf, 114, ad, 12, key, nonce, buf1, 114, false));
|
||||||
assert (memcmp (buf1, text, 114) == 0);
|
assert (memcmp (buf1, text, 114) == 0);
|
||||||
|
// test encryption of multiple buffers
|
||||||
|
memcpy (buf, text, 114);
|
||||||
|
std::vector<std::pair<void*, std::size_t> > bufs{ std::make_pair (buf, 50), std::make_pair (buf + 50, 50), std::make_pair (buf + 100, 14) };
|
||||||
|
i2p::crypto::AEADChaCha20Poly1305Encrypt (bufs, key, nonce, buf + 114);
|
||||||
|
i2p::crypto::AEADChaCha20Poly1305 (buf, 114, nullptr, 0, key, nonce, buf1, 114, false);
|
||||||
|
assert (memcmp (buf1, text, 114) == 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue