mirror of
https://github.com/PurpleI2P/i2pd
synced 2024-11-10 08:00:38 +03:00
commit
73b6338f62
11
ChangeLog
11
ChangeLog
@ -1,6 +1,17 @@
|
||||
# for this file format description,
|
||||
# see https://github.com/olivierlacan/keep-a-changelog
|
||||
|
||||
## [2.20.0] - 2018-08-23
|
||||
### Added
|
||||
- Full implementation of NTCP2
|
||||
- Assets for android
|
||||
### Changed
|
||||
- armeabi-v7a and x86 in one apk for android
|
||||
- NTCP2 is enabled by default
|
||||
- Show lease's expiration time in readable format in the web console
|
||||
### Fixed
|
||||
- Correct names for transports in the web console
|
||||
|
||||
## [2.19.0] - 2018-06-26
|
||||
### Added
|
||||
- ECIES support for RouterInfo
|
||||
|
14
Makefile.osx
14
Makefile.osx
@ -31,6 +31,14 @@ endif
|
||||
|
||||
# Disabled, since it will be the default make rule. I think its better
|
||||
# to define the default rule in Makefile and not Makefile.<ostype> - torkel
|
||||
#install: all
|
||||
# test -d ${PREFIX} || mkdir -p ${PREFIX}/
|
||||
# cp -r i2p ${PREFIX}/
|
||||
install-brew: all
|
||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
|
||||
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||
@gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
|
||||
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||
|
@ -1,5 +1,5 @@
|
||||
#define I2Pd_AppName "i2pd"
|
||||
#define I2Pd_ver "2.19.0"
|
||||
#define I2Pd_ver "2.20.0"
|
||||
#define I2Pd_Publisher "PurpleI2P"
|
||||
|
||||
[Setup]
|
||||
|
@ -3,7 +3,7 @@
|
||||
package="org.purplei2p.i2pd"
|
||||
android:installLocation="auto"
|
||||
android:versionCode="1"
|
||||
android:versionName="2.19.0">
|
||||
android:versionName="2.20.0">
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="14"
|
||||
|
@ -15,12 +15,15 @@ ipv6 = false
|
||||
# ntcpproxy = http://127.0.0.1:8118
|
||||
# ssu = true
|
||||
|
||||
bandwidth = O
|
||||
bandwidth = L
|
||||
# share = 100
|
||||
|
||||
# notransit = true
|
||||
# floodfill = true
|
||||
|
||||
[ntcp2]
|
||||
enabled = true
|
||||
|
||||
[http]
|
||||
enabled = true
|
||||
address = 127.0.0.1
|
||||
|
@ -25,7 +25,7 @@ android {
|
||||
targetSdkVersion 28
|
||||
minSdkVersion 14
|
||||
versionCode 1
|
||||
versionName "2.19.0"
|
||||
versionName "2.20.0"
|
||||
ndk {
|
||||
abiFilters 'armeabi-v7a'
|
||||
abiFilters 'x86'
|
||||
|
@ -68,6 +68,6 @@ include $(PREBUILT_STATIC_LIBRARY)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
@ -1,8 +1,8 @@
|
||||
#APP_ABI := all
|
||||
#APP_ABI := armeabi-v7a x86
|
||||
APP_ABI := armeabi-v7a x86
|
||||
#APP_ABI := x86
|
||||
#APP_ABI := x86_64
|
||||
APP_ABI := armeabi-v7a
|
||||
#APP_ABI := armeabi-v7a
|
||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
||||
APP_PLATFORM := android-14
|
||||
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <exception>
|
||||
#include <boost/exception/diagnostic_information.hpp>
|
||||
#include <boost/exception_ptr.hpp>
|
||||
#include <exception>
|
||||
//#include "mainwindow.h"
|
||||
#include "FS.h"
|
||||
#include "DaemonAndroid.h"
|
||||
#include "Daemon.h"
|
||||
|
||||
namespace i2p
|
||||
{
|
||||
@ -80,6 +83,17 @@ namespace android
|
||||
//mutex=new QMutex(QMutex::Recursive);
|
||||
//setRunningCallback(0);
|
||||
//m_IsRunning=false;
|
||||
|
||||
// make sure assets are ready before proceed
|
||||
i2p::fs::DetectDataDir("", false);
|
||||
int numAttempts = 0;
|
||||
do
|
||||
{
|
||||
if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready
|
||||
numAttempts++;
|
||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second
|
||||
}
|
||||
while (numAttempts <= 10); // 10 seconds max
|
||||
return Daemon.init(argc,argv);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.purplei2p.i2pd;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@ -25,21 +28,27 @@ import android.view.MenuItem;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
// For future package update checking
|
||||
import org.purplei2p.i2pd.BuildConfig;
|
||||
|
||||
public class I2PDActivity extends Activity {
|
||||
private static final String TAG = "i2pdActvt";
|
||||
public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000;
|
||||
|
||||
|
||||
private TextView textView;
|
||||
|
||||
private boolean assetsCopied;
|
||||
private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/";
|
||||
|
||||
private static final DaemonSingleton daemon = DaemonSingleton.getInstance();
|
||||
|
||||
|
||||
private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener =
|
||||
new DaemonSingleton.StateUpdateListener() {
|
||||
|
||||
@Override
|
||||
public void daemonStateUpdate() {
|
||||
public void daemonStateUpdate()
|
||||
{
|
||||
processAssets();
|
||||
runOnUiThread(new Runnable(){
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
@ -55,7 +64,7 @@ public class I2PDActivity extends Activity {
|
||||
(DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+
|
||||
(DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"")
|
||||
);
|
||||
} catch (Throwable tr) {
|
||||
} catch (Throwable tr) {
|
||||
Log.e(TAG,"error ignored",tr);
|
||||
}
|
||||
}
|
||||
@ -64,7 +73,7 @@ public class I2PDActivity extends Activity {
|
||||
};
|
||||
private static volatile long graceStartedMillis;
|
||||
private static final Object graceStartedMillis_LOCK=new Object();
|
||||
|
||||
|
||||
private static String formatGraceTimeRemaining() {
|
||||
long remainingSeconds;
|
||||
synchronized (graceStartedMillis_LOCK){
|
||||
@ -74,25 +83,19 @@ public class I2PDActivity extends Activity {
|
||||
long remSec=remainingSeconds-remainingMinutes*60;
|
||||
return remainingMinutes+":"+(remSec/10)+remSec%10;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// copy assets
|
||||
copyAsset("certificates");
|
||||
copyAsset("i2pd.conf");
|
||||
copyAsset("subsciptions.txt");
|
||||
copyAsset("tunnels.conf");
|
||||
|
||||
|
||||
textView = new TextView(this);
|
||||
setContentView(textView);
|
||||
daemon.addStateChangeListener(daemonStateUpdatedListener);
|
||||
daemonStateUpdatedListener.daemonStateUpdate();
|
||||
|
||||
|
||||
// set the app be foreground
|
||||
doBindService();
|
||||
|
||||
|
||||
final Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null){
|
||||
long gracefulStopAtMillis;
|
||||
@ -102,7 +105,7 @@ public class I2PDActivity extends Activity {
|
||||
rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
@ -115,7 +118,7 @@ public class I2PDActivity extends Activity {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void cancelGracefulStop() {
|
||||
Timer gracefulQuitTimer = getGracefulQuitTimer();
|
||||
if(gracefulQuitTimer!=null) {
|
||||
@ -123,7 +126,7 @@ public class I2PDActivity extends Activity {
|
||||
setGracefulQuitTimer(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private CharSequence throwableToString(Throwable tr) {
|
||||
StringWriter sw = new StringWriter(8192);
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
@ -131,9 +134,9 @@ public class I2PDActivity extends Activity {
|
||||
pw.close();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
|
||||
// private LocalService mBoundService;
|
||||
|
||||
|
||||
private ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// This is called when the connection with the service has been
|
||||
@ -142,12 +145,12 @@ public class I2PDActivity extends Activity {
|
||||
// service that we know is running in our own process, we can
|
||||
// cast its IBinder to a concrete class and directly access it.
|
||||
// mBoundService = ((LocalService.LocalBinder)service).getService();
|
||||
|
||||
|
||||
// Tell the user about this for our demo.
|
||||
// Toast.makeText(Binding.this, R.string.local_service_connected,
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
// This is called when the connection with the service has been
|
||||
// unexpectedly disconnected -- that is, its process crashed.
|
||||
@ -158,10 +161,9 @@ public class I2PDActivity extends Activity {
|
||||
// Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
private static volatile boolean mIsBound;
|
||||
|
||||
|
||||
private void doBindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) return;
|
||||
@ -173,7 +175,7 @@ public class I2PDActivity extends Activity {
|
||||
mIsBound = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void doUnbindService() {
|
||||
synchronized (I2PDActivity.class) {
|
||||
if (mIsBound) {
|
||||
@ -183,21 +185,21 @@ public class I2PDActivity extends Activity {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
getMenuInflater().inflate(R.menu.options_main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
// Handle action bar item clicks here. The action bar will
|
||||
// automatically handle clicks on the Home/Up button, so long
|
||||
// as you specify a parent activity in AndroidManifest.xml.
|
||||
int id = item.getItemId();
|
||||
|
||||
|
||||
switch(id){
|
||||
case R.id.action_stop:
|
||||
i2pdStop();
|
||||
@ -206,14 +208,14 @@ public class I2PDActivity extends Activity {
|
||||
i2pdGracefulStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
|
||||
private void i2pdStop() {
|
||||
cancelGracefulStop();
|
||||
new Thread(new Runnable(){
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d(TAG, "stopping");
|
||||
@ -223,12 +225,12 @@ public class I2PDActivity extends Activity {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},"stop").start();
|
||||
}
|
||||
|
||||
|
||||
private static volatile Timer gracefulQuitTimer;
|
||||
|
||||
|
||||
private void i2pdGracefulStop() {
|
||||
if(daemon.getState()==DaemonSingleton.State.stopped){
|
||||
Toast.makeText(this, R.string.already_stopped,
|
||||
@ -243,7 +245,7 @@ public class I2PDActivity extends Activity {
|
||||
Toast.makeText(this, R.string.graceful_stop_is_in_progress,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
new Thread(new Runnable(){
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try{
|
||||
@ -263,21 +265,21 @@ public class I2PDActivity extends Activity {
|
||||
Log.e(TAG,"",tr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},"gracInit").start();
|
||||
}
|
||||
|
||||
|
||||
private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) {
|
||||
if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel();
|
||||
final Timer gracefulQuitTimer = new Timer(true);
|
||||
setGracefulQuitTimer(gracefulQuitTimer);
|
||||
gracefulQuitTimer.schedule(new TimerTask(){
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
i2pdStop();
|
||||
}
|
||||
|
||||
|
||||
}, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis()));
|
||||
final TimerTask tickerTask = new TimerTask() {
|
||||
@Override
|
||||
@ -287,30 +289,30 @@ public class I2PDActivity extends Activity {
|
||||
};
|
||||
gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/);
|
||||
}
|
||||
|
||||
|
||||
private static Timer getGracefulQuitTimer() {
|
||||
return gracefulQuitTimer;
|
||||
}
|
||||
|
||||
|
||||
private static void setGracefulQuitTimer(Timer gracefulQuitTimer) {
|
||||
I2PDActivity.gracefulQuitTimer = gracefulQuitTimer;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the asset at the specified path to this app's data directory. If the
|
||||
* asset is a directory, its contents are also copied.
|
||||
*
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyAsset(String path) {
|
||||
AssetManager manager = getAssets();
|
||||
|
||||
|
||||
// If we have a directory, we make it and recurse. If a file, we copy its
|
||||
// contents.
|
||||
try {
|
||||
String[] contents = manager.list(path);
|
||||
|
||||
|
||||
// The documentation suggests that list throws an IOException, but doesn't
|
||||
// say under what conditions. It'd be nice if it did so when the path was
|
||||
// to a file. That doesn't appear to be the case. If the returned array is
|
||||
@ -318,30 +320,30 @@ public class I2PDActivity extends Activity {
|
||||
// directories will get turned into files.
|
||||
if (contents == null || contents.length == 0)
|
||||
throw new IOException();
|
||||
|
||||
|
||||
// Make the directory.
|
||||
File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path);
|
||||
File dir = new File(i2pdpath, path);
|
||||
dir.mkdirs();
|
||||
|
||||
|
||||
// Recurse on the contents.
|
||||
for (String entry : contents) {
|
||||
copyAsset(path + "/" + entry);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
copyFileAsset(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the asset file specified by path to app's data directory. Assumes
|
||||
* parent directories have already been created.
|
||||
*
|
||||
*
|
||||
* @param path
|
||||
* Path to asset, relative to app's assets directory.
|
||||
*/
|
||||
private void copyFileAsset(String path) {
|
||||
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path);
|
||||
try {
|
||||
File file = new File(i2pdpath, path);
|
||||
if(!file.exists()) try {
|
||||
InputStream in = getAssets().open(path);
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[1024];
|
||||
@ -352,8 +354,66 @@ public class I2PDActivity extends Activity {
|
||||
}
|
||||
out.close();
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteRecursive(File fileOrDirectory) {
|
||||
if (fileOrDirectory.isDirectory()) {
|
||||
for (File child : fileOrDirectory.listFiles()) {
|
||||
deleteRecursive(child);
|
||||
}
|
||||
}
|
||||
fileOrDirectory.delete();
|
||||
}
|
||||
|
||||
private void processAssets() {
|
||||
if (!assetsCopied) try {
|
||||
assetsCopied = true; // prevent from running on every state update
|
||||
|
||||
File holderfile = new File(i2pdpath, "assets.ready");
|
||||
String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX
|
||||
StringBuilder text = new StringBuilder();
|
||||
|
||||
if (holderfile.exists()) try { // if holder file exists, read assets version string
|
||||
BufferedReader br = new BufferedReader(new FileReader(holderfile));
|
||||
String line;
|
||||
|
||||
while ((line = br.readLine()) != null) {
|
||||
text.append(line);
|
||||
}
|
||||
br.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
|
||||
// if version differs from current app version or null, try to delete certificates folder
|
||||
if (!text.toString().contains(versionName)) try {
|
||||
holderfile.delete();
|
||||
File certpath = new File(i2pdpath, "certificates");
|
||||
deleteRecursive(certpath);
|
||||
}
|
||||
catch (Throwable tr) {
|
||||
Log.e(TAG, "", tr);
|
||||
}
|
||||
|
||||
// copy assets. If processed file exists, it won't be overwrited
|
||||
copyAsset("certificates");
|
||||
copyAsset("i2pd.conf");
|
||||
copyAsset("subscriptions.txt");
|
||||
copyAsset("tunnels.conf");
|
||||
|
||||
// update holder file about successful copying
|
||||
FileWriter writer = new FileWriter(holderfile);
|
||||
writer.append(versionName);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (Throwable tr)
|
||||
{
|
||||
Log.e(TAG,"copy assets",tr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,6 @@ include $(PREBUILT_STATIC_LIBRARY)
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := miniupnpc
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include
|
||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
||||
include $(PREBUILT_STATIC_LIBRARY)
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 2.19.{build}
|
||||
version: 2.20.{build}
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
branches:
|
||||
|
@ -2,7 +2,7 @@ FROM alpine:latest
|
||||
LABEL authors "Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
|
||||
|
||||
# Expose git branch, tag and URL variables as arguments
|
||||
ARG GIT_BRANCH="master"
|
||||
ARG GIT_BRANCH="openssl"
|
||||
ENV GIT_BRANCH=${GIT_BRANCH}
|
||||
ARG GIT_TAG=""
|
||||
ENV GIT_TAG=${GIT_TAG}
|
||||
|
@ -1,7 +1,7 @@
|
||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||
|
||||
Name: i2pd-git
|
||||
Version: 2.19.0
|
||||
Version: 2.20.0
|
||||
Release: git%{git_hash}%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd
|
||||
|
@ -1,5 +1,5 @@
|
||||
Name: i2pd
|
||||
Version: 2.19.0
|
||||
Version: 2.20.0
|
||||
Release: 1%{?dist}
|
||||
Summary: I2P router written in C++
|
||||
Conflicts: i2pd-git
|
||||
@ -96,6 +96,9 @@ getent passwd i2pd >/dev/null || \
|
||||
|
||||
|
||||
%changelog
|
||||
* Thu Aug 23 2018 orignal <i2porignal@yandex.ru> - 2.20.0
|
||||
- update to 2.20.0
|
||||
|
||||
* Tue Jun 26 2018 orignal <i2porignal@yandex.ru> - 2.19.0
|
||||
- update to 2.19.0
|
||||
|
||||
|
@ -92,6 +92,8 @@ namespace http {
|
||||
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
|
||||
const char HTTP_PARAM_ADDRESS[] = "address";
|
||||
|
||||
static std::string ConvertTime (uint64_t time);
|
||||
|
||||
static void ShowUptime (std::stringstream& s, int seconds)
|
||||
{
|
||||
int num;
|
||||
@ -262,7 +264,9 @@ namespace http {
|
||||
{
|
||||
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
|
||||
{
|
||||
s << "NTCP2 supported <br>\r\n";
|
||||
s << "NTCP2";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << " supported <br>\r\n";
|
||||
continue;
|
||||
}
|
||||
switch (address->transportStyle)
|
||||
@ -271,13 +275,13 @@ namespace http {
|
||||
{
|
||||
s << "NTCP";
|
||||
if (address->IsPublishedNTCP2 ()) s << "2";
|
||||
if (address->host.is_v6 ()) s << "6";
|
||||
if (address->host.is_v6 ()) s << "v6";
|
||||
s << " ";
|
||||
break;
|
||||
}
|
||||
case i2p::data::RouterInfo::eTransportSSU:
|
||||
if (address->host.is_v6 ())
|
||||
s << "SSU6 ";
|
||||
s << "SSUv6 ";
|
||||
else
|
||||
s << "SSU ";
|
||||
break;
|
||||
@ -462,14 +466,14 @@ namespace http {
|
||||
s << "<div class='invalid'>!! Invalid !! </div>\r\n";
|
||||
s << "<div class='slide'><label for='slide" << counter << "'>" << dest.ToBase32() << "</label>\r\n";
|
||||
s << "<input type='checkbox' id='slide" << (counter++) << "'/>\r\n<p class='content'>\r\n";
|
||||
s << "<b>Expires:</b> " << ls.GetExpirationTime() << "<br>\r\n";
|
||||
s << "<b>Expires:</b> " << ConvertTime(ls.GetExpirationTime()) << "<br>\r\n";
|
||||
auto leases = ls.GetNonExpiredLeases();
|
||||
s << "<b>Non Expired Leases: " << leases.size() << "</b><br>\r\n";
|
||||
for ( auto & l : leases )
|
||||
{
|
||||
s << "<b>Gateway:</b> " << l->tunnelGateway.ToBase64() << "<br>\r\n";
|
||||
s << "<b>TunnelID:</b> " << l->tunnelID << "<br>\r\n";
|
||||
s << "<b>EndDate:</b> " << l->endDate << "<br>\r\n";
|
||||
s << "<b>EndDate:</b> " << ConvertTime(l->endDate) << "<br>\r\n";
|
||||
}
|
||||
s << "</p>\r\n</div>\r\n</div>\r\n";
|
||||
}
|
||||
@ -583,7 +587,7 @@ namespace http {
|
||||
}
|
||||
if (!tmp_s6.str ().empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ntcp6'><b>" << name << "6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_ntcp6'/>\r\n<p class='content'>";
|
||||
s << "<div class='slide'><label for='slide_" << boost::algorithm::to_lower_copy(name) << "v6'><b>" << name << "v6</b> ( " << cnt6 << " )</label>\r\n<input type='checkbox' id='slide_" << boost::algorithm::to_lower_copy(name) << "v6'/>\r\n<p class='content'>";
|
||||
s << tmp_s6.str () << "</p>\r\n</div>\r\n";
|
||||
}
|
||||
}
|
||||
@ -628,7 +632,7 @@ namespace http {
|
||||
auto sessions6 = ssuServer->GetSessionsV6 ();
|
||||
if (!sessions6.empty ())
|
||||
{
|
||||
s << "<div class='slide'><label for='slide_ssu6'><b>SSU6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssu6'/>\r\n<p class='content'>";
|
||||
s << "<div class='slide'><label for='slide_ssuv6'><b>SSUv6</b> ( " << (int) sessions6.size() << " )</label>\r\n<input type='checkbox' id='slide_ssuv6'/>\r\n<p class='content'>";
|
||||
for (const auto& it: sessions6)
|
||||
{
|
||||
auto endpoint = it.second->GetRemoteEndpoint ();
|
||||
@ -763,6 +767,16 @@ namespace http {
|
||||
}
|
||||
}
|
||||
|
||||
std::string ConvertTime (uint64_t time)
|
||||
{
|
||||
ldiv_t divTime = ldiv(time,1000);
|
||||
time_t t = divTime.quot;
|
||||
struct tm *tm = localtime(&t);
|
||||
char date[128];
|
||||
snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem);
|
||||
return date;
|
||||
}
|
||||
|
||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
||||
m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0),
|
||||
expected_host(hostname)
|
||||
|
@ -131,8 +131,8 @@ namespace transport
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
TryPortMapping (address);
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
TryPortMapping (address);
|
||||
}
|
||||
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
|
||||
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
|
||||
@ -148,7 +148,7 @@ namespace transport
|
||||
const auto& a = context.GetRouterInfo().GetAddresses();
|
||||
for (const auto& address : a)
|
||||
{
|
||||
if (!address->host.is_v6 ())
|
||||
if (!address->host.is_v6 () && address->port)
|
||||
CloseMapping (address);
|
||||
}
|
||||
}
|
||||
|
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
||||
i2pd (2.20.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.20.0/0.9.36
|
||||
|
||||
-- orignal <orignal@i2pmail.org> Thu, 23 Aug 2018 16:00:00 +0000
|
||||
|
||||
i2pd (2.19.0-1) unstable; urgency=medium
|
||||
|
||||
* updated to version 2.19.0/0.9.35
|
||||
|
@ -233,7 +233,7 @@ namespace config {
|
||||
|
||||
options_description ntcp2("NTCP2 Options");
|
||||
ntcp2.add_options()
|
||||
("ntcp2.enabled", value<bool>()->default_value(false), "Enable NTCP2 (default: disabled)")
|
||||
("ntcp2.enabled", value<bool>()->default_value(true), "Enable NTCP2 (default: enabled)")
|
||||
("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)")
|
||||
;
|
||||
|
@ -1,3 +1,14 @@
|
||||
/*
|
||||
* 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 <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/hmac.h>
|
||||
@ -244,6 +255,140 @@ namespace transport
|
||||
SHA256_Final (m_H, &ctx); //h = SHA256(h || ciphertext)
|
||||
}
|
||||
|
||||
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen)
|
||||
{
|
||||
// decrypt X
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (i2p::context.GetIdentHash ());
|
||||
decryption.SetIV (i2p::context.GetNTCP2IV ());
|
||||
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
|
||||
decryption.GetIV (m_IV); // save IV for SessionCreated
|
||||
// decryption key for next block
|
||||
KDF1Bob ();
|
||||
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
||||
uint8_t nonce[12], options[16];
|
||||
memset (nonce, 0, 12); // set nonce to zero
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, m_H, 32, m_K, nonce, options, 16, false)) // decrypt
|
||||
{
|
||||
// options
|
||||
if (options[1] == 2) // ver is always 2
|
||||
{
|
||||
paddingLen = bufbe16toh (options + 2);
|
||||
m_SessionRequestBufferLen = paddingLen + 64;
|
||||
m3p2Len = bufbe16toh (options + 4);
|
||||
if (m3p2Len < 16)
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest m3p2len=", m3p2Len, " is too short");
|
||||
return false;
|
||||
}
|
||||
// check timestamp
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
uint32_t tsA = bufbe32toh (options + 8);
|
||||
if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NTCP2Establisher::ProcessSessionCreatedMessage (uint16_t& paddingLen)
|
||||
{
|
||||
m_SessionCreatedBufferLen = 64;
|
||||
// decrypt Y
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (m_RemoteIdentHash);
|
||||
decryption.SetIV (m_IV);
|
||||
decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ());
|
||||
// decryption key for next block (m_K)
|
||||
KDF2Alice ();
|
||||
// decrypt and verify MAC
|
||||
uint8_t payload[16];
|
||||
uint8_t nonce[12];
|
||||
memset (nonce, 0, 12); // set nonce to zero
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, m_H, 32, m_K, nonce, payload, 16, false)) // decrypt
|
||||
{
|
||||
// options
|
||||
paddingLen = bufbe16toh(payload + 2);
|
||||
// check timestamp
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
uint32_t tsB = bufbe32toh (payload + 8);
|
||||
if (tsB < ts - NTCP2_CLOCK_SKEW || tsB > ts + NTCP2_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", (int)(ts - tsB), " exceeds clock skew");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
||||
{
|
||||
// update AD
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, m_H, 32);
|
||||
SHA256_Update (&ctx, m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
||||
SHA256_Final (m_H, &ctx);
|
||||
|
||||
int paddingLength = m_SessionCreatedBufferLen - 64;
|
||||
if (paddingLength > 0)
|
||||
{
|
||||
SHA256_CTX ctx1;
|
||||
SHA256_Init (&ctx1);
|
||||
SHA256_Update (&ctx1, m_H, 32);
|
||||
SHA256_Update (&ctx1, m_SessionCreatedBuffer + 64, paddingLength);
|
||||
SHA256_Final (m_H, &ctx1);
|
||||
}
|
||||
if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, m_H, 32, m_K, nonce, m_RemoteStaticKey, 32, false)) // decrypt S
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf)
|
||||
{
|
||||
// update AD again
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, m_H, 32);
|
||||
SHA256_Update (&ctx, m_SessionConfirmedBuffer, 48);
|
||||
SHA256_Final (m_H, &ctx);
|
||||
|
||||
KDF3Bob ();
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, m_H, 32, m_K, nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
||||
{
|
||||
// caclulate new h again for KDF data
|
||||
memcpy (m_SessionConfirmedBuffer + 16, m_H, 32); // h || ciphertext
|
||||
SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_H); //h = SHA256(h || ciphertext);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed ");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
||||
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
|
||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||
@ -368,52 +513,28 @@ namespace transport
|
||||
}
|
||||
else
|
||||
{
|
||||
// decrypt X
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (i2p::context.GetIdentHash ());
|
||||
decryption.SetIV (i2p::context.GetNTCP2IV ());
|
||||
decryption.Decrypt (m_Establisher->m_SessionRequestBuffer, 32, m_Establisher->GetRemotePub ());
|
||||
decryption.GetIV (m_Establisher->m_IV); // save IV for SessionCreated
|
||||
// decryption key for next block
|
||||
m_Establisher->KDF1Bob ();
|
||||
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
||||
uint8_t nonce[12], options[16];
|
||||
memset (nonce, 0, 12); // set nonce to zero
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionRequestBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, options, 16, false)) // decrypt
|
||||
LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred);
|
||||
uint16_t paddingLen = 0;
|
||||
if (m_Establisher->ProcessSessionRequestMessage (paddingLen))
|
||||
{
|
||||
if (options[1] == 2)
|
||||
if (paddingLen > 0)
|
||||
{
|
||||
uint16_t paddingLen = bufbe16toh (options + 2);
|
||||
m_Establisher->m_SessionRequestBufferLen = paddingLen + 64;
|
||||
m_Establisher->m3p2Len = bufbe16toh (options + 4);
|
||||
// TODO: check tsA
|
||||
if (paddingLen > 0)
|
||||
if (paddingLen <= 287 - 64) // session request is 287 bytes max
|
||||
{
|
||||
if (paddingLen <= 287 - 64) // session request is 287 bytes max
|
||||
{
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
|
||||
std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||
Terminate ();
|
||||
}
|
||||
boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (),
|
||||
std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
else
|
||||
SendSessionCreated ();
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]);
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed ");
|
||||
Terminate ();
|
||||
SendSessionCreated ();
|
||||
}
|
||||
else
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -446,23 +567,9 @@ namespace transport
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred);
|
||||
m_Establisher->m_SessionCreatedBufferLen = 64;
|
||||
// decrypt Y
|
||||
i2p::crypto::CBCDecryption decryption;
|
||||
decryption.SetKey (GetRemoteIdentity ()->GetIdentHash ());
|
||||
decryption.SetIV (m_Establisher->m_IV);
|
||||
decryption.Decrypt (m_Establisher->m_SessionCreatedBuffer, 32, m_Establisher->GetRemotePub ());
|
||||
// decryption key for next block (m_K)
|
||||
m_Establisher->KDF2Alice ();
|
||||
// decrypt and verify MAC
|
||||
uint8_t payload[16];
|
||||
uint8_t nonce[12];
|
||||
memset (nonce, 0, 12); // set nonce to zero
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionCreatedBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, payload, 16, false)) // decrypt
|
||||
{
|
||||
uint16_t paddingLen = bufbe16toh(payload + 2);
|
||||
LogPrint (eLogDebug, "NTCP2: padding length ", paddingLen);
|
||||
// TODO: check tsB
|
||||
uint16_t paddingLen = 0;
|
||||
if (m_Establisher->ProcessSessionCreatedMessage (paddingLen))
|
||||
{
|
||||
if (paddingLen > 0)
|
||||
{
|
||||
if (paddingLen <= 287 - 64) // session created is 287 bytes max
|
||||
@ -480,10 +587,7 @@ namespace transport
|
||||
SendSessionConfirmed ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed ");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,38 +663,16 @@ namespace transport
|
||||
else
|
||||
{
|
||||
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
||||
// update AD
|
||||
uint8_t h[80];
|
||||
memcpy (h, m_Establisher->GetH (), 32);
|
||||
memcpy (h + 32, m_Establisher->m_SessionCreatedBuffer + 32, 32); // encrypted payload
|
||||
SHA256 (h, 64, h);
|
||||
int paddingLength = m_Establisher->m_SessionCreatedBufferLen - 64;
|
||||
if (paddingLength > 0)
|
||||
{
|
||||
SHA256_CTX ctx;
|
||||
SHA256_Init (&ctx);
|
||||
SHA256_Update (&ctx, h, 32);
|
||||
SHA256_Update (&ctx, m_Establisher->m_SessionCreatedBuffer + 64, paddingLength);
|
||||
SHA256_Final (h, &ctx);
|
||||
}
|
||||
// part 1
|
||||
uint8_t nonce[12];
|
||||
CreateNonce (1, nonce);
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer, 32, h, 32, m_Establisher->GetK (), nonce, m_Establisher->m_RemoteStaticKey, 32, false)) // decrypt S
|
||||
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
|
||||
{
|
||||
// part 2
|
||||
// update AD again
|
||||
memcpy (h + 32, m_Establisher->m_SessionConfirmedBuffer, 48);
|
||||
SHA256 (h, 80, m_Establisher->m_H);
|
||||
|
||||
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
|
||||
m_Establisher->KDF3Bob ();
|
||||
memset (nonce, 0, 12); // set nonce to 0 again
|
||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer + 48, m_Establisher->m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, buf.data (), m_Establisher->m3p2Len - 16, false)) // decrypt
|
||||
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ()))
|
||||
{
|
||||
// caclulate new h again for KDF data
|
||||
memcpy (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext
|
||||
SHA256 (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext);
|
||||
KeyDerivationFunctionDataPhase ();
|
||||
// Bob data phase keys
|
||||
m_SendKey = m_Kba;
|
||||
@ -599,7 +681,7 @@ namespace transport
|
||||
m_ReceiveSipKey = m_Sipkeysab;
|
||||
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
|
||||
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
|
||||
|
||||
// payload
|
||||
// process RI
|
||||
if (buf[0] != eNTCP2BlkRouterInfo)
|
||||
{
|
||||
@ -644,19 +726,13 @@ namespace transport
|
||||
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
||||
m_Server.AddNTCP2Session (shared_from_this ());
|
||||
Established ();
|
||||
ReceiveLength ();
|
||||
}
|
||||
ReceiveLength ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed ");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed ");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -691,12 +767,20 @@ namespace transport
|
||||
else
|
||||
{
|
||||
i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey);
|
||||
// m_NextRecivedLen comes from the network in BigEndian
|
||||
// m_NextReceivedLen comes from the network in BigEndian
|
||||
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
|
||||
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
|
||||
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
|
||||
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
|
||||
Receive ();
|
||||
if (m_NextReceivedLen >= 16)
|
||||
{
|
||||
if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer;
|
||||
m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen];
|
||||
Receive ();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short");
|
||||
Terminate ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,7 +949,7 @@ namespace transport
|
||||
payload[s] = eNTCP2BlkPadding; // blk
|
||||
htobe16buf (payload + s + 1, paddingSize); // size
|
||||
s += 3;
|
||||
RAND_bytes (payload + s, paddingSize);
|
||||
memset (payload + s, 0, paddingSize);
|
||||
s += paddingSize;
|
||||
// send
|
||||
SendNextFrame (payload, s);
|
||||
@ -875,6 +959,7 @@ namespace transport
|
||||
|
||||
void NTCP2Session::SendRouterInfo ()
|
||||
{
|
||||
if (!IsEstablished ()) return;
|
||||
auto riLen = i2p::context.GetRouterInfo ().GetBufferLen ();
|
||||
int paddingSize = (riLen*NTCP2_MAX_PADDING_RATIO)/100;
|
||||
size_t payloadLen = riLen + paddingSize + 7; // 7 = 2*3 bytes header + 1 byte RI flag
|
||||
@ -892,6 +977,7 @@ namespace transport
|
||||
|
||||
void NTCP2Session::SendTermination (NTCP2TerminationReason reason)
|
||||
{
|
||||
if (!IsEstablished ()) return;
|
||||
uint8_t payload[12] = { eNTCP2BlkTermination, 0, 9 };
|
||||
htobe64buf (payload + 3, m_ReceiveSequenceNumber);
|
||||
payload[11] = (uint8_t)reason;
|
||||
@ -921,7 +1007,7 @@ namespace transport
|
||||
void NTCP2Session::SendLocalRouterInfo ()
|
||||
{
|
||||
if (!IsOutgoing ()) // we send it in SessionConfirmed
|
||||
SendRouterInfo ();
|
||||
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
|
||||
}
|
||||
|
||||
NTCP2Server::NTCP2Server ():
|
||||
|
@ -1,3 +1,13 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
#ifndef NTCP2_H__
|
||||
#define NTCP2_H__
|
||||
|
||||
@ -26,6 +36,8 @@ namespace transport
|
||||
const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes
|
||||
const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
|
||||
|
||||
const int NTCP2_CLOCK_SKEW = 60; // in seconds
|
||||
|
||||
enum NTCP2BlockType
|
||||
{
|
||||
eNTCP2BlkDateTime = 0,
|
||||
@ -91,6 +103,11 @@ namespace transport
|
||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||
|
||||
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
|
||||
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
||||
|
||||
BN_CTX * m_Ctx;
|
||||
uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519
|
||||
uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/;
|
||||
|
@ -402,7 +402,7 @@ namespace transport
|
||||
uint32_t tsA1 = be32toh (tsA);
|
||||
if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew");
|
||||
LogPrint (eLogError, "NTCP: Phase3 time difference ", (int)(ts - tsA1), " exceeds clock skew");
|
||||
Terminate ();
|
||||
return;
|
||||
}
|
||||
@ -485,7 +485,7 @@ namespace transport
|
||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||
if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW)
|
||||
{
|
||||
LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew");
|
||||
LogPrint (eLogError, "NTCP: Phase4 time difference ", (int)(ts - tsB), " exceeds clock skew");
|
||||
Terminate ();
|
||||
return;
|
||||
}
|
||||
|
@ -164,6 +164,7 @@ namespace i2p
|
||||
|
||||
void RouterContext::PublishNTCP2Address (int port, bool publish)
|
||||
{
|
||||
if (!m_NTCP2Keys) return;
|
||||
if (!port)
|
||||
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
|
||||
bool updated = false;
|
||||
@ -173,6 +174,7 @@ namespace i2p
|
||||
{
|
||||
address->port = port;
|
||||
address->ntcp2->isPublished = publish;
|
||||
address->ntcp2->iv = m_NTCP2Keys->iv;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
@ -668,7 +668,7 @@ namespace data
|
||||
addr->host = boost::asio::ip::address::from_string (host);
|
||||
addr->port = port;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 2;
|
||||
addr->cost = 6;
|
||||
addr->date = 0;
|
||||
for (const auto& it: *m_Addresses) // don't insert same address twice
|
||||
if (*it == *addr) return;
|
||||
@ -703,7 +703,7 @@ namespace data
|
||||
auto addr = std::make_shared<Address>();
|
||||
addr->port = 0;
|
||||
addr->transportStyle = eTransportNTCP;
|
||||
addr->cost = 14;
|
||||
addr->cost = 3;
|
||||
addr->date = 0;
|
||||
addr->ntcp2.reset (new NTCP2Ext ());
|
||||
addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
|
||||
|
||||
#define I2PD_VERSION_MAJOR 2
|
||||
#define I2PD_VERSION_MINOR 19
|
||||
#define I2PD_VERSION_MINOR 20
|
||||
#define I2PD_VERSION_MICRO 0
|
||||
#define I2PD_VERSION_PATCH 0
|
||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
#define I2P_VERSION_MAJOR 0
|
||||
#define I2P_VERSION_MINOR 9
|
||||
#define I2P_VERSION_MICRO 35
|
||||
#define I2P_VERSION_MICRO 36
|
||||
#define I2P_VERSION_PATCH 0
|
||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.19.0" android:versionCode="2" android:installLocation="auto">
|
||||
<manifest package="org.purplei2p.i2pd" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="2.20.0" android:versionCode="1" android:installLocation="auto">
|
||||
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23"/>
|
||||
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||
<!-- <application android:hardwareAccelerated="true" -->
|
||||
|
Loading…
Reference in New Issue
Block a user