mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-05 20:43:48 +01:00
commit
d231f944c0
47 changed files with 1493 additions and 1016 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,6 +1,25 @@
|
||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [2.24.0] - 2019-03-21
|
||||||
|
### Added
|
||||||
|
- Support of transient keys for LeaseSet2
|
||||||
|
- Support of encrypted LeaseSet2
|
||||||
|
- Recognize signature type 11 (RedDSA)
|
||||||
|
- Support websocket connections over HTTP proxy
|
||||||
|
- Ability to disable full addressbook persist
|
||||||
|
### Changed
|
||||||
|
- Don't load peer profiles if non-persistant
|
||||||
|
- REUSE_ADDR for ipv6 acceptors
|
||||||
|
- Reset eTags if addressbook can't be loaded
|
||||||
|
### Fixed
|
||||||
|
- Build with boost 1.70
|
||||||
|
- Filter out unspecified addresses from RouterInfo
|
||||||
|
- Check floodfill status change
|
||||||
|
- Correct SAM response for invalid key
|
||||||
|
- SAM crash on termination for Windows
|
||||||
|
- Race condition for publishing
|
||||||
|
|
||||||
## [2.23.0] - 2019-01-21
|
## [2.23.0] - 2019-01-21
|
||||||
### Added
|
### Added
|
||||||
- Standard LeaseSet2 support
|
- Standard LeaseSet2 support
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#define I2Pd_AppName "i2pd"
|
#define I2Pd_AppName "i2pd"
|
||||||
#define I2Pd_ver "2.23.0"
|
#define I2Pd_ver "2.24.0"
|
||||||
#define I2Pd_Publisher "PurpleI2P"
|
#define I2Pd_Publisher "PurpleI2P"
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
|
|
4
android/.gitignore
vendored
4
android/.gitignore
vendored
|
@ -12,7 +12,5 @@ local.properties
|
||||||
build.sh
|
build.sh
|
||||||
android.iml
|
android.iml
|
||||||
build
|
build
|
||||||
gradle
|
|
||||||
gradlew
|
|
||||||
gradlew.bat
|
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
android:installLocation="auto">
|
android:installLocation="auto">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" /> <!-- normal perm, per https://developer.android.com/guide/topics/permissions/normal-permissions.html -->
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- normal perm -->
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- required in API 26+ -->
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
@ -48,5 +48,4 @@
|
||||||
android:value="org.purplei2p.i2pd.I2PDPermsAskerActivity" />
|
android:value="org.purplei2p.i2pd.I2PDPermsAskerActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,9 +2,10 @@ buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,18 +19,18 @@ repositories {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:support-compat:28.0.0'
|
implementation 'com.android.support:support-compat:28.0.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
buildToolsVersion "28.0.1"
|
buildToolsVersion "28.0.3"
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.purplei2p.i2pd"
|
applicationId "org.purplei2p.i2pd"
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
versionCode 2230
|
versionCode 2240
|
||||||
versionName "2.23.0"
|
versionName "2.24.0"
|
||||||
ndk {
|
ndk {
|
||||||
abiFilters 'armeabi-v7a'
|
abiFilters 'armeabi-v7a'
|
||||||
abiFilters 'x86'
|
abiFilters 'x86'
|
||||||
|
|
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#Thu Mar 14 18:21:08 MSK 2019
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
172
android/gradlew
vendored
Executable file
172
android/gradlew
vendored
Executable file
|
@ -0,0 +1,172 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
84
android/gradlew.bat
vendored
Normal file
84
android/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
|
@ -16,4 +16,5 @@
|
||||||
<string name="stopped">Приложение было остановлено</string>
|
<string name="stopped">Приложение было остановлено</string>
|
||||||
<string name="remaining">осталось</string>
|
<string name="remaining">осталось</string>
|
||||||
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
|
<string name="title_activity_i2_pdperms_asker_prompt">Запрос</string>
|
||||||
|
<string name="permDenied">Права для записи на SD карту отклонены, вам необходимо предоставить их для продолжения</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -16,4 +16,5 @@
|
||||||
<string name="stopped">Application stopped</string>
|
<string name="stopped">Application stopped</string>
|
||||||
<string name="remaining">remaining</string>
|
<string name="remaining">remaining</string>
|
||||||
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
<string name="title_activity_i2_pdperms_asker_prompt">Prompt</string>
|
||||||
|
<string name="permDenied">SD card write permission denied, you need to allow this to continue</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -6,14 +6,12 @@ import android.util.Log;
|
||||||
import org.purplei2p.i2pd.R;
|
import org.purplei2p.i2pd.R;
|
||||||
|
|
||||||
public class DaemonSingleton {
|
public class DaemonSingleton {
|
||||||
private static final String TAG="i2pd";
|
private static final String TAG = "i2pd";
|
||||||
private static final DaemonSingleton instance = new DaemonSingleton();
|
private static final DaemonSingleton instance = new DaemonSingleton();
|
||||||
public interface StateUpdateListener { void daemonStateUpdate(); }
|
public interface StateUpdateListener { void daemonStateUpdate(); }
|
||||||
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
private final Set<StateUpdateListener> stateUpdateListeners = new HashSet<>();
|
||||||
|
|
||||||
public static DaemonSingleton getInstance() {
|
public static DaemonSingleton getInstance() { return instance; }
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
|
public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); }
|
||||||
public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
|
public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); }
|
||||||
|
@ -91,7 +89,6 @@ public class DaemonSingleton {
|
||||||
} catch (Throwable tr) {
|
} catch (Throwable tr) {
|
||||||
lastThrowable=tr;
|
lastThrowable=tr;
|
||||||
setState(State.startFailed);
|
setState(State.startFailed);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.purplei2p.i2pd;
|
package org.purplei2p.i2pd;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
|
|
@ -119,11 +119,10 @@ public class I2PDPermsAskerActivity extends Activity {
|
||||||
|
|
||||||
// permission denied, boo! Disable the
|
// permission denied, boo! Disable the
|
||||||
// functionality that depends on this permission.
|
// functionality that depends on this permission.
|
||||||
textview_retry.setText("SD card write permission denied, you need to allow this to continue");
|
textview_retry.setText(R.string.permDenied);
|
||||||
textview_retry.setVisibility(TextView.VISIBLE);
|
textview_retry.setVisibility(TextView.VISIBLE);
|
||||||
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
|
button_request_write_ext_storage_perms.setVisibility(Button.VISIBLE);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// other 'case' lines to check for other
|
// other 'case' lines to check for other
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: 2.23.0.{build}
|
version: 2.24.0.{build}
|
||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
branches:
|
branches:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||||
|
|
||||||
Name: i2pd-git
|
Name: i2pd-git
|
||||||
Version: 2.23.0
|
Version: 2.24.0
|
||||||
Release: git%{git_hash}%{?dist}
|
Release: git%{git_hash}%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd
|
Conflicts: i2pd
|
||||||
|
@ -110,6 +110,9 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 21 2019 orignal <i2porignal@yandex.ru> - 2.24.0
|
||||||
|
- update to 2.24.0
|
||||||
|
|
||||||
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
|
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
|
||||||
- update to 2.23.0
|
- update to 2.23.0
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Name: i2pd
|
Name: i2pd
|
||||||
Version: 2.23.0
|
Version: 2.24.0
|
||||||
Release: 1%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd-git
|
Conflicts: i2pd-git
|
||||||
|
@ -108,6 +108,9 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 21 2019 orignal <i2porignal@yandex.ru> - 2.24.0
|
||||||
|
- update to 2.24.0
|
||||||
|
|
||||||
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
|
* Mon Jan 21 2019 orignal <i2porignal@yandex.ru> - 2.23.0
|
||||||
- update to 2.23.0
|
- update to 2.23.0
|
||||||
|
|
||||||
|
|
|
@ -798,8 +798,7 @@ namespace http {
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr<boost::asio::ip::tcp::socket> socket):
|
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),
|
m_Socket (socket), m_BufferLen (0), expected_host(hostname)
|
||||||
expected_host(hostname)
|
|
||||||
{
|
{
|
||||||
/* cache options */
|
/* cache options */
|
||||||
i2p::config::GetOption("http.auth", needAuth);
|
i2p::config::GetOption("http.auth", needAuth);
|
||||||
|
|
|
@ -39,7 +39,6 @@ namespace http
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
|
||||||
boost::asio::deadline_timer m_Timer;
|
|
||||||
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
|
char m_Buffer[HTTP_CONNECTION_BUFFER_SIZE + 1];
|
||||||
size_t m_BufferLen;
|
size_t m_BufferLen;
|
||||||
std::string m_SendBuffer;
|
std::string m_SendBuffer;
|
||||||
|
|
7
debian/changelog
vendored
7
debian/changelog
vendored
|
@ -1,3 +1,10 @@
|
||||||
|
i2pd (2.24.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.24.0/0.9.39
|
||||||
|
* update docs, dirs, install, links files
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Thu, 21 Mar 2019 16:00:00 +0000
|
||||||
|
|
||||||
i2pd (2.23.0-1) unstable; urgency=medium
|
i2pd (2.23.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* updated to version 2.23.0/0.9.38
|
* updated to version 2.23.0/0.9.38
|
||||||
|
|
|
@ -256,6 +256,7 @@ namespace config {
|
||||||
options_description persist("Network information persisting options");
|
options_description persist("Network information persisting options");
|
||||||
persist.add_options()
|
persist.add_options()
|
||||||
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
|
("persist.profiles", value<bool>()->default_value(true), "Persist peer profiles (default: true)")
|
||||||
|
("persist.addressbook", value<bool>()->default_value(true), "Persist full addreses (default: true)")
|
||||||
;
|
;
|
||||||
|
|
||||||
m_OptionsDesc
|
m_OptionsDesc
|
||||||
|
|
|
@ -8,11 +8,14 @@
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include "TunnelBase.h"
|
#include "TunnelBase.h"
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include "Crypto.h"
|
#if OPENSSL_HKDF
|
||||||
|
#include <openssl/kdf.h>
|
||||||
|
#endif
|
||||||
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
||||||
#include "ChaCha20.h"
|
#include "ChaCha20.h"
|
||||||
#include "Poly1305.h"
|
#include "Poly1305.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "Crypto.h"
|
||||||
#include "Ed25519.h"
|
#include "Ed25519.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
@ -1228,6 +1231,47 @@ namespace crypto
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
||||||
|
{
|
||||||
|
#if OPENSSL_AEAD_CHACHA20_POLY1305
|
||||||
|
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new ();
|
||||||
|
EVP_EncryptInit_ex(ctx, EVP_chacha20 (), 0, key, nonce);
|
||||||
|
int outlen = 0;
|
||||||
|
EVP_EncryptUpdate(ctx, out, &outlen, msg, msgLen);
|
||||||
|
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||||
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
|
#else
|
||||||
|
chacha::Chacha20State state;
|
||||||
|
chacha::Chacha20Init (state, nonce, key, 1);
|
||||||
|
if (out != msg) memcpy (out, msg, msgLen);
|
||||||
|
chacha::Chacha20Encrypt (state, out, msgLen);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out)
|
||||||
|
{
|
||||||
|
#if OPENSSL_HKDF
|
||||||
|
EVP_PKEY_CTX * pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_HKDF, NULL);
|
||||||
|
EVP_PKEY_derive_init (pctx);
|
||||||
|
EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
|
||||||
|
EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
|
||||||
|
EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
|
||||||
|
if (info.length () > 0)
|
||||||
|
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
|
||||||
|
size_t outlen = 64;
|
||||||
|
EVP_PKEY_derive (pctx, out, &outlen);
|
||||||
|
EVP_PKEY_CTX_free (pctx);
|
||||||
|
#else
|
||||||
|
uint8_t prk[32]; unsigned int len;
|
||||||
|
HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len);
|
||||||
|
auto l = info.length ();
|
||||||
|
memcpy (out, info.c_str (), l); out[l] = 0x01;
|
||||||
|
HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
|
||||||
|
memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
|
||||||
|
HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len);
|
||||||
|
#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;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
# define X509_getm_notAfter X509_get_notAfter
|
# define X509_getm_notAfter X509_get_notAfter
|
||||||
#else
|
#else
|
||||||
# define LEGACY_OPENSSL 0
|
# define LEGACY_OPENSSL 0
|
||||||
|
# define OPENSSL_HKDF 1
|
||||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||||
# define OPENSSL_EDDSA 1
|
# define OPENSSL_EDDSA 1
|
||||||
# define OPENSSL_X25519 1
|
# define OPENSSL_X25519 1
|
||||||
|
@ -290,6 +291,13 @@ namespace crypto
|
||||||
|
|
||||||
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
void AEADChaCha20Poly1305Encrypt (const std::vector<std::pair<uint8_t *, size_t> >& bufs, const uint8_t * key, const uint8_t * nonce, uint8_t * mac); // encrypt multiple buffers with zero ad
|
||||||
|
|
||||||
|
// ChaCha20
|
||||||
|
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out);
|
||||||
|
|
||||||
|
// HKDF
|
||||||
|
|
||||||
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out); // salt - 32, out - 64, info <= 32
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation);
|
void InitCrypto (bool precomputation);
|
||||||
void TerminateCrypto ();
|
void TerminateCrypto ();
|
||||||
|
|
|
@ -272,15 +272,20 @@ namespace client
|
||||||
if (!m_Pool) return nullptr;
|
if (!m_Pool) return nullptr;
|
||||||
if (!m_LeaseSet)
|
if (!m_LeaseSet)
|
||||||
UpdateLeaseSet ();
|
UpdateLeaseSet ();
|
||||||
|
return GetLeaseSetMt ();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<const i2p::data::LocalLeaseSet> LeaseSetDestination::GetLeaseSetMt ()
|
||||||
|
{
|
||||||
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
|
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
|
||||||
return m_LeaseSet;
|
return m_LeaseSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet)
|
void LeaseSetDestination::SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
|
std::lock_guard<std::mutex> l(m_LeaseSetMutex);
|
||||||
m_LeaseSet.reset (newLeaseSet);
|
m_LeaseSet = newLeaseSet;
|
||||||
}
|
}
|
||||||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||||
if (m_IsPublic)
|
if (m_IsPublic)
|
||||||
|
@ -361,55 +366,75 @@ namespace client
|
||||||
}
|
}
|
||||||
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
|
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
|
||||||
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
|
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
|
||||||
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET || // 1
|
switch (buf[DATABASE_STORE_TYPE_OFFSET])
|
||||||
buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2) // 3
|
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
|
case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
|
||||||
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
case i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2: // 3
|
||||||
auto it = m_RemoteLeaseSets.find (key);
|
|
||||||
if (it != m_RemoteLeaseSets.end ())
|
|
||||||
{
|
{
|
||||||
leaseSet = it->second;
|
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
|
||||||
if (leaseSet->IsNewer (buf + offset, len - offset))
|
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
||||||
|
auto it = m_RemoteLeaseSets.find (key);
|
||||||
|
if (it != m_RemoteLeaseSets.end ())
|
||||||
{
|
{
|
||||||
leaseSet->Update (buf + offset, len - offset);
|
leaseSet = it->second;
|
||||||
|
if (leaseSet->IsNewer (buf + offset, len - offset))
|
||||||
|
{
|
||||||
|
leaseSet->Update (buf + offset, len - offset);
|
||||||
|
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
|
||||||
|
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed");
|
||||||
|
m_RemoteLeaseSets.erase (it);
|
||||||
|
leaseSet = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
|
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
|
||||||
|
else
|
||||||
|
leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset); // LeaseSet2
|
||||||
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
|
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
|
||||||
LogPrint (eLogDebug, "Destination: Remote LeaseSet updated");
|
{
|
||||||
|
if (leaseSet->GetIdentHash () != GetIdentHash ())
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
|
||||||
|
m_RemoteLeaseSets[key] = leaseSet;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Destination: Remote LeaseSet update failed");
|
LogPrint (eLogError, "Destination: New remote LeaseSet failed");
|
||||||
m_RemoteLeaseSets.erase (it);
|
|
||||||
leaseSet = nullptr;
|
leaseSet = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
break;
|
||||||
LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated");
|
|
||||||
}
|
}
|
||||||
else
|
case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
|
||||||
{
|
{
|
||||||
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
auto it2 = m_LeaseSetRequests.find (key);
|
||||||
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
|
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedIdentity)
|
||||||
else
|
|
||||||
leaseSet = std::make_shared<i2p::data::LeaseSet2> (buf[DATABASE_STORE_TYPE_OFFSET], buf + offset, len - offset); // LeaseSet2
|
|
||||||
if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key)
|
|
||||||
{
|
{
|
||||||
if (leaseSet->GetIdentHash () != GetIdentHash ())
|
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, it2->second->requestedIdentity);
|
||||||
|
if (ls2->IsValid ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Destination: New remote LeaseSet added");
|
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
|
||||||
m_RemoteLeaseSets[key] = leaseSet;
|
leaseSet = ls2;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
LogPrint (eLogDebug, "Destination: Own remote LeaseSet dropped");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
|
||||||
LogPrint (eLogError, "Destination: New remote LeaseSet failed");
|
break;
|
||||||
leaseSet = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
|
||||||
}
|
}
|
||||||
else
|
|
||||||
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
|
|
||||||
|
|
||||||
auto it1 = m_LeaseSetRequests.find (key);
|
auto it1 = m_LeaseSetRequests.find (key);
|
||||||
if (it1 != m_LeaseSetRequests.end ())
|
if (it1 != m_LeaseSetRequests.end ())
|
||||||
|
@ -485,7 +510,8 @@ namespace client
|
||||||
|
|
||||||
void LeaseSetDestination::Publish ()
|
void LeaseSetDestination::Publish ()
|
||||||
{
|
{
|
||||||
if (!m_LeaseSet || !m_Pool)
|
auto leaseSet = GetLeaseSetMt ();
|
||||||
|
if (!leaseSet || !m_Pool)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet");
|
LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet");
|
||||||
return;
|
return;
|
||||||
|
@ -517,7 +543,7 @@ namespace client
|
||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
||||||
if (!floodfill)
|
if (!floodfill)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
|
||||||
|
@ -527,7 +553,7 @@ namespace client
|
||||||
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||||
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
||||||
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
||||||
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound));
|
auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound));
|
||||||
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
||||||
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
|
@ -572,7 +598,8 @@ namespace client
|
||||||
{
|
{
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet)
|
auto ls = s->GetLeaseSetMt ();
|
||||||
|
if (ls && *ls == *leaseSet)
|
||||||
{
|
{
|
||||||
// we got latest LeasetSet
|
// we got latest LeasetSet
|
||||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
|
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32());
|
||||||
|
@ -605,7 +632,21 @@ namespace client
|
||||||
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
|
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete));
|
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete, nullptr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LeaseSetDestination::RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::IdentityEx> dest, RequestComplete requestComplete)
|
||||||
|
{
|
||||||
|
if (!m_Pool || !IsReady ())
|
||||||
|
{
|
||||||
|
if (requestComplete)
|
||||||
|
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i2p::data::IdentHash ident;
|
||||||
|
i2p::data::LeaseSet2::CalculateStoreHash (dest, i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519, ident); // always assume type 11
|
||||||
|
m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), ident, requestComplete, dest));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,13 +665,21 @@ namespace client
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete)
|
void LeaseSetDestination::CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::IdentityEx> dest, bool notify)
|
||||||
|
{
|
||||||
|
i2p::data::IdentHash ident;
|
||||||
|
i2p::data::LeaseSet2::CalculateStoreHash (dest, i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519, ident); // always assume type 11
|
||||||
|
CancelDestinationRequest (ident, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::IdentityEx> requestedIdentity)
|
||||||
{
|
{
|
||||||
std::set<i2p::data::IdentHash> excluded;
|
std::set<i2p::data::IdentHash> excluded;
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
{
|
{
|
||||||
auto request = std::make_shared<LeaseSetRequest> (m_Service);
|
auto request = std::make_shared<LeaseSetRequest> (m_Service);
|
||||||
|
request->requestedIdentity = requestedIdentity; // for encrypted LeaseSet2
|
||||||
if (requestComplete)
|
if (requestComplete)
|
||||||
request->requestComplete.push_back (requestComplete);
|
request->requestComplete.push_back (requestComplete);
|
||||||
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
auto ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
@ -1039,10 +1088,10 @@ namespace client
|
||||||
|
|
||||||
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
void ClientDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||||
{
|
{
|
||||||
i2p::data::LocalLeaseSet * leaseSet = nullptr;
|
std::shared_ptr<i2p::data::LocalLeaseSet> leaseSet;
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
{
|
{
|
||||||
leaseSet = new i2p::data::LocalLeaseSet (GetIdentity (), m_EncryptionPublicKey, tunnels);
|
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_EncryptionPublicKey, tunnels);
|
||||||
// sign
|
// sign
|
||||||
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
||||||
}
|
}
|
||||||
|
@ -1050,7 +1099,7 @@ namespace client
|
||||||
{
|
{
|
||||||
// standard LS2 (type 3) assumed for now. TODO: implement others
|
// standard LS2 (type 3) assumed for now. TODO: implement others
|
||||||
auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256;
|
auto keyLen = m_Decryptor ? m_Decryptor->GetPublicKeyLen () : 256;
|
||||||
leaseSet = new i2p::data::LocalLeaseSet2 (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
leaseSet = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
||||||
m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels);
|
m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels);
|
||||||
}
|
}
|
||||||
SetLeaseSet (leaseSet);
|
SetLeaseSet (leaseSet);
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace client
|
||||||
std::list<RequestComplete> requestComplete;
|
std::list<RequestComplete> requestComplete;
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> outboundTunnel;
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> replyTunnel;
|
std::shared_ptr<i2p::tunnel::InboundTunnel> replyTunnel;
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> requestedIdentity; // for encrypted LeaseSet2 only
|
||||||
|
|
||||||
void Complete (std::shared_ptr<i2p::data::LeaseSet> ls)
|
void Complete (std::shared_ptr<i2p::data::LeaseSet> ls)
|
||||||
{
|
{
|
||||||
|
@ -109,7 +110,9 @@ namespace client
|
||||||
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
|
bool IsReady () const { return m_LeaseSet && !m_LeaseSet->IsExpired () && m_Pool->GetOutboundTunnels ().size () > 0; };
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
std::shared_ptr<const i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
||||||
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
bool RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete = nullptr);
|
||||||
|
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::IdentityEx> dest, RequestComplete requestComplete = nullptr);
|
||||||
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
|
void CancelDestinationRequest (const i2p::data::IdentHash& dest, bool notify = true);
|
||||||
|
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::IdentityEx> dest, bool notify = true);
|
||||||
|
|
||||||
// implements GarlicDestination
|
// implements GarlicDestination
|
||||||
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSet ();
|
||||||
|
@ -124,7 +127,7 @@ namespace client
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet);
|
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
|
||||||
int GetLeaseSetType () const { return m_LeaseSetType; };
|
int GetLeaseSetType () const { return m_LeaseSetType; };
|
||||||
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
|
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
|
||||||
virtual void CleanupDestination () {}; // additional clean up in derived classes
|
virtual void CleanupDestination () {}; // additional clean up in derived classes
|
||||||
|
@ -136,6 +139,7 @@ namespace client
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
void UpdateLeaseSet ();
|
void UpdateLeaseSet ();
|
||||||
|
std::shared_ptr<const i2p::data::LocalLeaseSet> GetLeaseSetMt ();
|
||||||
void Publish ();
|
void Publish ();
|
||||||
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
void HandlePublishConfirmationTimer (const boost::system::error_code& ecode);
|
||||||
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
|
void HandlePublishVerificationTimer (const boost::system::error_code& ecode);
|
||||||
|
@ -144,7 +148,7 @@ namespace client
|
||||||
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len);
|
||||||
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void HandleDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete);
|
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::IdentityEx> requestedIdentity = nullptr);
|
||||||
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
|
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
|
||||||
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
|
||||||
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
void HandleCleanupTimer (const boost::system::error_code& ecode);
|
||||||
|
@ -161,7 +165,7 @@ namespace client
|
||||||
|
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
|
||||||
std::mutex m_LeaseSetMutex;
|
std::mutex m_LeaseSetMutex;
|
||||||
std::shared_ptr<i2p::data::LocalLeaseSet> m_LeaseSet;
|
std::shared_ptr<const i2p::data::LocalLeaseSet> m_LeaseSet;
|
||||||
bool m_IsPublic;
|
bool m_IsPublic;
|
||||||
uint32_t m_PublishReplyToken;
|
uint32_t m_PublishReplyToken;
|
||||||
uint64_t m_LastSubmissionTime; // in seconds
|
uint64_t m_LastSubmissionTime; // in seconds
|
||||||
|
|
|
@ -491,6 +491,21 @@ namespace crypto
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void Ed25519::BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded)
|
||||||
|
{
|
||||||
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
|
// calculate alpha = seed mod l
|
||||||
|
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
|
||||||
|
BN_mod (alpha, alpha, l, ctx); // % l
|
||||||
|
uint8_t priv[32];
|
||||||
|
EncodeBN (alpha, priv, 32); // back to Little Endian
|
||||||
|
BN_free (alpha);
|
||||||
|
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
|
||||||
|
auto A1 = Sum (DecodePublicKey (pub, ctx), MulB (priv, ctx), ctx); // pub + B*alpha
|
||||||
|
EncodePublicKey (A1, blinded, ctx);
|
||||||
|
BN_CTX_free (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
|
void Ed25519::ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey)
|
||||||
{
|
{
|
||||||
SHA512 (key, EDDSA25519_PRIVATE_KEY_LENGTH, expandedKey);
|
SHA512 (key, EDDSA25519_PRIVATE_KEY_LENGTH, expandedKey);
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace crypto
|
||||||
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
|
#endif
|
||||||
|
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#include <time.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Timestamp.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -77,6 +76,7 @@ namespace data
|
||||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)type, " is not supported");
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
{
|
{
|
||||||
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
|
||||||
RAND_bytes (m_StandardIdentity.signingKey, padding);
|
RAND_bytes (m_StandardIdentity.signingKey, padding);
|
||||||
|
@ -275,6 +275,13 @@ namespace data
|
||||||
return 128;
|
return 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint8_t * IdentityEx::GetSigningPublicKeyBuffer () const
|
||||||
|
{
|
||||||
|
auto keyLen = GetSigningPublicKeyLen ();
|
||||||
|
if (keyLen > 128) return nullptr; // P521
|
||||||
|
return m_StandardIdentity.signingKey + 128 - keyLen;
|
||||||
|
}
|
||||||
|
|
||||||
size_t IdentityEx::GetSigningPrivateKeyLen () const
|
size_t IdentityEx::GetSigningPrivateKeyLen () const
|
||||||
{
|
{
|
||||||
if (!m_Verifier) CreateVerifier ();
|
if (!m_Verifier) CreateVerifier ();
|
||||||
|
@ -331,6 +338,7 @@ namespace data
|
||||||
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
|
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
|
||||||
return new i2p::crypto::ECDSAP521Verifier ();
|
return new i2p::crypto::ECDSAP521Verifier ();
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
return new i2p::crypto::EDDSA25519Verifier ();
|
return new i2p::crypto::EDDSA25519Verifier ();
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA);
|
return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA);
|
||||||
|
@ -603,6 +611,7 @@ namespace data
|
||||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, IsOfflineSignature () ? nullptr: m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
|
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, IsOfflineSignature () ? nullptr: m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
|
@ -695,6 +704,7 @@ namespace data
|
||||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
||||||
// no break here
|
// no break here
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
|
@ -763,15 +773,7 @@ namespace data
|
||||||
{
|
{
|
||||||
uint8_t buf[41]; // ident + yyyymmdd
|
uint8_t buf[41]; // ident + yyyymmdd
|
||||||
memcpy (buf, (const uint8_t *)ident, 32);
|
memcpy (buf, (const uint8_t *)ident, 32);
|
||||||
time_t t = time (nullptr);
|
i2p::util::GetCurrentDate ((char *)(buf + 32));
|
||||||
struct tm tm;
|
|
||||||
#ifdef _WIN32
|
|
||||||
gmtime_s(&tm, &t);
|
|
||||||
sprintf_s((char *)(buf + 32), 9, "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
|
||||||
#else
|
|
||||||
gmtime_r(&t, &tm);
|
|
||||||
sprintf((char *)(buf + 32), "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
|
||||||
#endif
|
|
||||||
IdentHash key;
|
IdentHash key;
|
||||||
SHA256(buf, 40, key);
|
SHA256(buf, 40, key);
|
||||||
return key;
|
return key;
|
||||||
|
|
|
@ -67,9 +67,9 @@ namespace data
|
||||||
const uint16_t SIGNING_KEY_TYPE_RSA_SHA512_4096 = 6;
|
const uint16_t SIGNING_KEY_TYPE_RSA_SHA512_4096 = 6;
|
||||||
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 = 7;
|
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 = 7;
|
||||||
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519ph = 8; // not implemented
|
const uint16_t SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519ph = 8; // not implemented
|
||||||
// following signature type should never appear in netid=2
|
|
||||||
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9;
|
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256 = 9;
|
||||||
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB
|
const uint16_t SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512 = 10; // approved by FSB
|
||||||
|
const uint16_t SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 = 11; // for LeaseSet2 only
|
||||||
|
|
||||||
typedef uint16_t SigningKeyType;
|
typedef uint16_t SigningKeyType;
|
||||||
typedef uint16_t CryptoKeyType;
|
typedef uint16_t CryptoKeyType;
|
||||||
|
@ -100,6 +100,7 @@ namespace data
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (const uint8_t * key) const;
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (const uint8_t * key) const;
|
||||||
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
|
size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; };
|
||||||
size_t GetSigningPublicKeyLen () const;
|
size_t GetSigningPublicKeyLen () const;
|
||||||
|
const uint8_t * GetSigningPublicKeyBuffer () const; // returns NULL for P521
|
||||||
size_t GetSigningPrivateKeyLen () const;
|
size_t GetSigningPrivateKeyLen () const;
|
||||||
size_t GetSignatureLen () const;
|
size_t GetSignatureLen () const;
|
||||||
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
|
bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/hmac.h>
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
#include "Ed25519.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
|
@ -255,11 +258,17 @@ namespace data
|
||||||
{
|
{
|
||||||
SetBuffer (buf, len);
|
SetBuffer (buf, len);
|
||||||
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
ReadFromBufferEncrypted (buf, len);
|
ReadFromBufferEncrypted (buf, len, nullptr);
|
||||||
else
|
else
|
||||||
ReadFromBuffer (buf, len);
|
ReadFromBuffer (buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity):
|
||||||
|
LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
|
{
|
||||||
|
ReadFromBufferEncrypted (buf, len, identity);
|
||||||
|
}
|
||||||
|
|
||||||
void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature)
|
void LeaseSet2::Update (const uint8_t * buf, size_t len, bool verifySignature)
|
||||||
{
|
{
|
||||||
SetBuffer (buf, len);
|
SetBuffer (buf, len);
|
||||||
|
@ -281,9 +290,9 @@ namespace data
|
||||||
identity = GetIdentity ();
|
identity = GetIdentity ();
|
||||||
size_t offset = identity->GetFullLen ();
|
size_t offset = identity->GetFullLen ();
|
||||||
if (offset + 8 >= len) return;
|
if (offset + 8 >= len) return;
|
||||||
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
|
m_PublishedTimestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
|
||||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
||||||
SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds
|
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
|
||||||
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
||||||
if (flags & LEASESET2_FLAG_OFFLINE_KEYS)
|
if (flags & LEASESET2_FLAG_OFFLINE_KEYS)
|
||||||
{
|
{
|
||||||
|
@ -414,22 +423,25 @@ namespace data
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len)
|
void LeaseSet2::ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity)
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// blinded key
|
// blinded key
|
||||||
if (len < 2) return;
|
if (len < 2) return;
|
||||||
uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2;
|
const uint8_t * stA1 = buf + offset; // stA1 = blinded signature type, 2 bytes big endian
|
||||||
|
uint16_t blindedKeyType = bufbe16toh (stA1); offset += 2;
|
||||||
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType));
|
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (blindedKeyType));
|
||||||
if (!blindedVerifier) return;
|
if (!blindedVerifier) return;
|
||||||
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
||||||
if (offset + blindedKeyLen >= len) return;
|
if (offset + blindedKeyLen >= len) return;
|
||||||
blindedVerifier->SetPublicKey (buf + offset); offset += blindedKeyLen;
|
const uint8_t * blindedPublicKey = buf + offset;
|
||||||
|
blindedVerifier->SetPublicKey (blindedPublicKey); offset += blindedKeyLen;
|
||||||
// expiration
|
// expiration
|
||||||
if (offset + 8 >= len) return;
|
if (offset + 8 >= len) return;
|
||||||
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
|
const uint8_t * publishedTimestamp = buf + offset;
|
||||||
|
m_PublishedTimestamp = bufbe32toh (publishedTimestamp); offset += 4; // published timestamp (seconds)
|
||||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
|
||||||
SetExpirationTime ((timestamp + expires)*1000LL); // in milliseconds
|
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
|
||||||
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
uint16_t flags = bufbe16toh (buf + offset); offset += 2; // flags
|
||||||
if (flags & LEASESET2_FLAG_OFFLINE_KEYS)
|
if (flags & LEASESET2_FLAG_OFFLINE_KEYS)
|
||||||
{
|
{
|
||||||
|
@ -443,11 +455,114 @@ namespace data
|
||||||
}
|
}
|
||||||
// outer ciphertext
|
// outer ciphertext
|
||||||
if (offset + 2 > len) return;
|
if (offset + 2 > len) return;
|
||||||
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2 + lenOuterCiphertext;
|
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2;
|
||||||
|
const uint8_t * outerCiphertext = buf + offset;
|
||||||
|
offset += lenOuterCiphertext;
|
||||||
// verify signature
|
// verify signature
|
||||||
bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) :
|
bool verified = m_TransientVerifier ? VerifySignature (m_TransientVerifier, buf, len, offset) :
|
||||||
VerifySignature (blindedVerifier, buf, len, offset);
|
VerifySignature (blindedVerifier, buf, len, offset);
|
||||||
SetIsValid (verified);
|
SetIsValid (verified);
|
||||||
|
// handle ciphertext
|
||||||
|
if (verified && identity && lenOuterCiphertext >= 32)
|
||||||
|
{
|
||||||
|
SetIsValid (false); // we must verify it again in Layer 2
|
||||||
|
if (blindedKeyType == i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519)
|
||||||
|
{
|
||||||
|
// verify blinding
|
||||||
|
char date[9];
|
||||||
|
i2p::util::GetCurrentDate (date);
|
||||||
|
uint8_t blinded[32];
|
||||||
|
BlindPublicKey (identity, date, blindedKeyType, blinded);
|
||||||
|
if (memcmp (blindedPublicKey, blinded, 32))
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// credentials
|
||||||
|
uint8_t credential[32], subcredential[36];
|
||||||
|
// A = destination's signing public key
|
||||||
|
// stA = signature type of A, 2 bytes big endian
|
||||||
|
uint16_t stA = htobe16 (identity->GetSigningKeyType ());
|
||||||
|
// credential = H("credential", A || stA || stA1)
|
||||||
|
H ("credential", { {identity->GetSigningPublicKeyBuffer (), identity->GetSigningPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {stA1, 2} }, credential);
|
||||||
|
// subcredential = H("subcredential", credential || blindedPublicKey)
|
||||||
|
H ("subcredential", { {credential, 32}, {blindedPublicKey, blindedKeyLen} }, subcredential);
|
||||||
|
// outer key
|
||||||
|
// outerInput = subcredential || publishedTimestamp
|
||||||
|
memcpy (subcredential + 32, publishedTimestamp, 4);
|
||||||
|
// outerSalt = outerCiphertext[0:32]
|
||||||
|
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
||||||
|
uint8_t keys[64]; // 44 bytes actual data
|
||||||
|
i2p::crypto::HKDF (outerCiphertext, subcredential, 36, "ELS2_L1K", keys);
|
||||||
|
// decrypt Layer 1
|
||||||
|
// outerKey = keys[0:31]
|
||||||
|
// outerIV = keys[32:43]
|
||||||
|
size_t lenOuterPlaintext = lenOuterCiphertext - 32;
|
||||||
|
std::vector<uint8_t> outerPlainText (lenOuterPlaintext);
|
||||||
|
i2p::crypto::ChaCha20 (outerCiphertext + 32, lenOuterPlaintext, keys, keys + 32, outerPlainText.data ());
|
||||||
|
// inner key
|
||||||
|
// innerSalt = innerCiphertext[0:32]
|
||||||
|
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
||||||
|
// skip 1 byte flags
|
||||||
|
i2p::crypto::HKDF (outerPlainText.data () + 1, subcredential, 36, "ELS2_L2K", keys); // no authCookie
|
||||||
|
// decrypt Layer 2
|
||||||
|
// innerKey = keys[0:31]
|
||||||
|
// innerIV = keys[32:43]
|
||||||
|
size_t lenInnerPlaintext = lenOuterPlaintext - 32 - 1;
|
||||||
|
std::vector<uint8_t> innerPlainText (lenInnerPlaintext);
|
||||||
|
i2p::crypto::ChaCha20 (outerPlainText.data () + 32 + 1, lenInnerPlaintext, keys, keys + 32, innerPlainText.data ());
|
||||||
|
if (innerPlainText[0] == NETDB_STORE_TYPE_STANDARD_LEASESET2 || innerPlainText[0] == NETDB_STORE_TYPE_META_LEASESET2)
|
||||||
|
{
|
||||||
|
// override store type and buffer
|
||||||
|
m_StoreType = innerPlainText[0];
|
||||||
|
SetBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
||||||
|
// parse and verify Layer 2
|
||||||
|
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "LeaseSet2: unxpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSet2::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash)
|
||||||
|
{
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, p.c_str (), p.length ());
|
||||||
|
for (const auto& it: bufs)
|
||||||
|
SHA256_Update (&ctx, it.first, it.second);
|
||||||
|
SHA256_Final (hash, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSet2::BlindPublicKey (std::shared_ptr<const IdentityEx> identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey)
|
||||||
|
{
|
||||||
|
uint16_t stA = htobe16 (identity->GetSigningKeyType ()), stA1 = htobe16 (blindedKeyType);
|
||||||
|
uint8_t salt[32], seed[64];
|
||||||
|
//seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64)
|
||||||
|
H ("I2PGenerateAlpha", { {identity->GetSigningPublicKeyBuffer (), identity->GetSigningPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt);
|
||||||
|
i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed);
|
||||||
|
i2p::crypto::GetEd25519 ()->BlindPublicKey (identity->GetSigningPublicKeyBuffer (), seed, blindedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeaseSet2::CalculateStoreHash (std::shared_ptr<const IdentityEx> identity, SigningKeyType blindedKeyType, i2p::data::IdentHash& hash)
|
||||||
|
{
|
||||||
|
if (blindedKeyType != i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519 &&
|
||||||
|
blindedKeyType != SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "LeaseSet2: blinded key type ", (int)blindedKeyType, " is not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char date[9];
|
||||||
|
i2p::util::GetCurrentDate (date);
|
||||||
|
uint8_t blinded[32];
|
||||||
|
BlindPublicKey (identity, date, blindedKeyType, blinded);
|
||||||
|
auto stA1 = htobe16 (blindedKeyType);
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, (const uint8_t *)&stA1, 2);
|
||||||
|
SHA256_Update (&ctx, blinded, 32);
|
||||||
|
SHA256_Final ((uint8_t *)hash, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
|
void LeaseSet2::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const
|
||||||
|
|
|
@ -78,6 +78,7 @@ namespace data
|
||||||
bool operator== (const LeaseSet& other) const
|
bool operator== (const LeaseSet& other) const
|
||||||
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
|
{ return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); };
|
||||||
virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; };
|
virtual uint8_t GetStoreType () const { return NETDB_STORE_TYPE_LEASESET; };
|
||||||
|
virtual uint32_t GetPublishedTimestamp () const { return 0; }; // should be set for LeaseSet2 only
|
||||||
virtual std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return nullptr; };
|
virtual std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return nullptr; };
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
|
@ -132,17 +133,21 @@ namespace data
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true);
|
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true);
|
||||||
|
LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity); // store type 5, called from local netdb only
|
||||||
uint8_t GetStoreType () const { return m_StoreType; };
|
uint8_t GetStoreType () const { return m_StoreType; };
|
||||||
|
uint32_t GetPublishedTimestamp () const { return m_PublishedTimestamp; };
|
||||||
std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return m_TransientVerifier; };
|
std::shared_ptr<const i2p::crypto::Verifier> GetTransientVerifier () const { return m_TransientVerifier; };
|
||||||
void Update (const uint8_t * buf, size_t len, bool verifySignature);
|
void Update (const uint8_t * buf, size_t len, bool verifySignature);
|
||||||
|
|
||||||
|
static void CalculateStoreHash (std::shared_ptr<const IdentityEx> identity, SigningKeyType blindedKeyType, i2p::data::IdentHash& hash);
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
|
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity = true, bool verifySignature = true);
|
void ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity = true, bool verifySignature = true);
|
||||||
void ReadFromBufferEncrypted (const uint8_t * buf, size_t len);
|
void ReadFromBufferEncrypted (const uint8_t * buf, size_t len, std::shared_ptr<const IdentityEx> identity);
|
||||||
size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
size_t ReadStandardLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
||||||
size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
size_t ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
|
@ -151,9 +156,14 @@ namespace data
|
||||||
|
|
||||||
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const;
|
uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
|
// for encrypted LS
|
||||||
|
static void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash);
|
||||||
|
static void BlindPublicKey (std::shared_ptr<const IdentityEx> identity, const char * date, SigningKeyType blindedKeyType, uint8_t * blindedKey); // blinded key 32 bytes, date is 8 chars "YYYYMMDD"
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_StoreType;
|
uint8_t m_StoreType;
|
||||||
|
uint32_t m_PublishedTimestamp = 0;
|
||||||
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
||||||
};
|
};
|
||||||
|
|
|
@ -935,7 +935,7 @@ namespace transport
|
||||||
htobe16buf (buf + 1, len); // size
|
htobe16buf (buf + 1, len); // size
|
||||||
len += 3;
|
len += 3;
|
||||||
totalLen += len;
|
totalLen += len;
|
||||||
encryptBufs.push_back (std::make_pair (buf, len));
|
encryptBufs.push_back ( {buf, len} );
|
||||||
if (&it == &msgs.front ()) // first message
|
if (&it == &msgs.front ()) // first message
|
||||||
{
|
{
|
||||||
// allocate two bytes for length
|
// allocate two bytes for length
|
||||||
|
@ -949,7 +949,7 @@ namespace transport
|
||||||
auto paddingLen = CreatePaddingBlock (totalLen, buf + len, it->maxLen - it->len - 16);
|
auto paddingLen = CreatePaddingBlock (totalLen, buf + len, it->maxLen - it->len - 16);
|
||||||
if (paddingLen)
|
if (paddingLen)
|
||||||
{
|
{
|
||||||
encryptBufs.push_back (std::make_pair (buf + len, paddingLen));
|
encryptBufs.push_back ( {buf + len, paddingLen} );
|
||||||
len += paddingLen;
|
len += paddingLen;
|
||||||
totalLen += paddingLen;
|
totalLen += paddingLen;
|
||||||
}
|
}
|
||||||
|
@ -969,7 +969,7 @@ namespace transport
|
||||||
auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16);
|
auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16);
|
||||||
// and padding block to encrypt and send
|
// and padding block to encrypt and send
|
||||||
if (paddingLen)
|
if (paddingLen)
|
||||||
encryptBufs.push_back (std::make_pair (m_NextSendBuffer, paddingLen));
|
encryptBufs.push_back ( {m_NextSendBuffer, paddingLen} );
|
||||||
bufs.push_back (boost::asio::buffer (m_NextSendBuffer, paddingLen + 16));
|
bufs.push_back (boost::asio::buffer (m_NextSendBuffer, paddingLen + 16));
|
||||||
macBuf = m_NextSendBuffer + paddingLen;
|
macBuf = m_NextSendBuffer + paddingLen;
|
||||||
totalLen += paddingLen;
|
totalLen += paddingLen;
|
||||||
|
@ -1001,7 +1001,7 @@ namespace transport
|
||||||
// encrypt
|
// encrypt
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
|
CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++;
|
||||||
i2p::crypto::AEADChaCha20Poly1305Encrypt ({std::make_pair (m_NextSendBuffer + 2, payloadLen)}, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2);
|
i2p::crypto::AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2);
|
||||||
SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer);
|
SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer);
|
||||||
// send
|
// send
|
||||||
m_IsSending = true;
|
m_IsSending = true;
|
||||||
|
@ -1180,6 +1180,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
|
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||||
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||||
|
m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||||
m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
m_NTCP2V6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||||
m_NTCP2V6Acceptor->listen ();
|
m_NTCP2V6Acceptor->listen ();
|
||||||
|
|
||||||
|
|
|
@ -843,6 +843,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
m_NTCPV6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||||
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
m_NTCPV6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||||
|
m_NTCPV6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||||
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
m_NTCPV6Acceptor->bind (boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port));
|
||||||
m_NTCPV6Acceptor->listen ();
|
m_NTCPV6Acceptor->listen ();
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace data
|
||||||
case eI2NPDummyMsg:
|
case eI2NPDummyMsg:
|
||||||
// plain RouterInfo from NTCP2 with flags for now
|
// plain RouterInfo from NTCP2 with flags for now
|
||||||
HandleNTCP2RouterInfoMsg (msg);
|
HandleNTCP2RouterInfoMsg (msg);
|
||||||
break;
|
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);
|
||||||
|
@ -138,7 +138,7 @@ namespace data
|
||||||
lastDestinationCleanup = ts;
|
lastDestinationCleanup = ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // update timestamp and publish
|
if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL) // update timestamp and publish
|
||||||
{
|
{
|
||||||
i2p::context.UpdateTimestamp (ts);
|
i2p::context.UpdateTimestamp (ts);
|
||||||
if (!m_HiddenMode) Publish ();
|
if (!m_HiddenMode) Publish ();
|
||||||
|
@ -148,7 +148,7 @@ namespace data
|
||||||
{
|
{
|
||||||
auto numRouters = m_RouterInfos.size ();
|
auto numRouters = m_RouterInfos.size ();
|
||||||
if (!numRouters)
|
if (!numRouters)
|
||||||
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
throw std::runtime_error("No known routers, reseed seems to be totally failed");
|
||||||
else // we have peers now
|
else // we have peers now
|
||||||
m_FloodfillBootstrap = nullptr;
|
m_FloodfillBootstrap = nullptr;
|
||||||
if (numRouters < 2500 || ts - lastExploratory >= 90)
|
if (numRouters < 2500 || ts - lastExploratory >= 90)
|
||||||
|
@ -170,17 +170,17 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::SetHidden(bool hide)
|
void NetDb::SetHidden(bool hide)
|
||||||
{
|
{
|
||||||
// TODO: remove reachable addresses from router info
|
// TODO: remove reachable addresses from router info
|
||||||
m_HiddenMode = hide;
|
m_HiddenMode = hide;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
|
||||||
{
|
{
|
||||||
bool updated;
|
bool updated;
|
||||||
AddRouterInfo (buf, len, updated);
|
AddRouterInfo (buf, len, updated);
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated)
|
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated)
|
||||||
|
@ -196,7 +196,7 @@ namespace data
|
||||||
{
|
{
|
||||||
bool updated;
|
bool updated;
|
||||||
AddRouterInfo (ident, buf, len, updated);
|
AddRouterInfo (ident, buf, len, updated);
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated)
|
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated)
|
||||||
|
@ -207,9 +207,18 @@ namespace data
|
||||||
{
|
{
|
||||||
if (r->IsNewer (buf, len))
|
if (r->IsNewer (buf, len))
|
||||||
{
|
{
|
||||||
|
bool wasFloodfill = r->IsFloodfill ();
|
||||||
r->Update (buf, len);
|
r->Update (buf, len);
|
||||||
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
|
||||||
// TODO: check if floodfill has been changed
|
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
|
||||||
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
|
if (wasFloodfill)
|
||||||
|
m_Floodfills.remove (r);
|
||||||
|
else
|
||||||
|
m_Floodfills.push_back (r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -220,7 +229,7 @@ namespace data
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = std::make_shared<RouterInfo> (buf, len);
|
r = std::make_shared<RouterInfo> (buf, len);
|
||||||
if (!r->IsUnreachable ())
|
if (!r->IsUnreachable () && r->HasValidAddresses ())
|
||||||
{
|
{
|
||||||
bool inserted = false;
|
bool inserted = false;
|
||||||
{
|
{
|
||||||
|
@ -291,10 +300,22 @@ namespace data
|
||||||
bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType)
|
bool NetDb::AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
|
std::unique_lock<std::mutex> lock(m_LeaseSetsMutex);
|
||||||
// always new LS2 for now. TODO: implement update
|
|
||||||
auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb
|
auto leaseSet = std::make_shared<LeaseSet2> (storeType, buf, len, false); // we don't need leases in netdb
|
||||||
m_LeaseSets[ident] = leaseSet;
|
if (leaseSet->IsValid ())
|
||||||
return true;
|
{
|
||||||
|
auto it = m_LeaseSets.find(ident);
|
||||||
|
if (it == m_LeaseSets.end () || it->second->GetStoreType () != storeType ||
|
||||||
|
leaseSet->GetPublishedTimestamp () > it->second->GetPublishedTimestamp ())
|
||||||
|
{
|
||||||
|
// TODO: implement actual update
|
||||||
|
LogPrint (eLogInfo, "NetDb: LeaseSet2 updated: ", ident.ToBase32());
|
||||||
|
m_LeaseSets[ident] = leaseSet;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "NetDb: new LeaseSet2 validation failed: ", ident.ToBase32());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
|
std::shared_ptr<RouterInfo> NetDb::FindRouter (const IdentHash& ident) const
|
||||||
|
@ -319,6 +340,9 @@ namespace data
|
||||||
|
|
||||||
std::shared_ptr<RouterProfile> NetDb::FindRouterProfile (const IdentHash& ident) const
|
std::shared_ptr<RouterProfile> NetDb::FindRouterProfile (const IdentHash& ident) const
|
||||||
{
|
{
|
||||||
|
if (!m_PersistProfiles)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
auto router = FindRouter (ident);
|
auto router = FindRouter (ident);
|
||||||
return router ? router->GetProfile () : nullptr;
|
return router ? router->GetProfile () : nullptr;
|
||||||
}
|
}
|
||||||
|
@ -418,8 +442,9 @@ namespace data
|
||||||
|
|
||||||
void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
|
void NetDb::VisitStoredRouterInfos(RouterInfoVisitor v)
|
||||||
{
|
{
|
||||||
m_Storage.Iterate([v] (const std::string & filename) {
|
m_Storage.Iterate([v] (const std::string & filename)
|
||||||
auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
|
{
|
||||||
|
auto ri = std::make_shared<i2p::data::RouterInfo>(filename);
|
||||||
v(ri);
|
v(ri);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -555,11 +580,11 @@ namespace data
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// clean up expired floodfiils
|
// clean up expired floodfills or not floodfills anymore
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
for (auto it = m_Floodfills.begin (); it != m_Floodfills.end ();)
|
for (auto it = m_Floodfills.begin (); it != m_Floodfills.end ();)
|
||||||
if ((*it)->IsUnreachable ())
|
if ((*it)->IsUnreachable () || !(*it)->IsFloodfill ())
|
||||||
it = m_Floodfills.erase (it);
|
it = m_Floodfills.erase (it);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
|
@ -651,22 +676,22 @@ namespace data
|
||||||
size_t payloadOffset = offset;
|
size_t payloadOffset = offset;
|
||||||
|
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
uint8_t storeType = buf[DATABASE_STORE_TYPE_OFFSET];
|
uint8_t storeType = buf[DATABASE_STORE_TYPE_OFFSET];
|
||||||
if (storeType) // LeaseSet or LeaseSet2
|
if (storeType) // LeaseSet or LeaseSet2
|
||||||
{
|
{
|
||||||
if (!m->from) // unsolicited LS must be received directly
|
if (!m->from) // unsolicited LS must be received directly
|
||||||
{
|
{
|
||||||
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32());
|
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32());
|
||||||
updated = AddLeaseSet (ident, buf + offset, len - offset);
|
updated = AddLeaseSet (ident, buf + offset, len - offset);
|
||||||
}
|
}
|
||||||
else // all others are considered as LeaseSet2
|
else // all others are considered as LeaseSet2
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
|
LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
|
||||||
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
|
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // RouterInfo
|
else // RouterInfo
|
||||||
{
|
{
|
||||||
|
@ -873,7 +898,7 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
|
if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP ||
|
||||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP))
|
||||||
{
|
{
|
||||||
auto leaseSet = FindLeaseSet (ident);
|
auto leaseSet = FindLeaseSet (ident);
|
||||||
if (!leaseSet)
|
if (!leaseSet)
|
||||||
|
@ -1180,13 +1205,13 @@ namespace data
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
|
||||||
return GetRandomRouter(
|
return GetRandomRouter(
|
||||||
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
||||||
{
|
{
|
||||||
return router->IsFamily(fam);
|
return router->IsFamily(fam);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetClosestNonFloodfill (const IdentHash& destination,
|
std::shared_ptr<const RouterInfo> NetDb::GetClosestNonFloodfill (const IdentHash& destination,
|
||||||
const std::set<IdentHash>& excluded) const
|
const std::set<IdentHash>& excluded) const
|
||||||
|
|
|
@ -208,26 +208,21 @@ namespace data
|
||||||
{
|
{
|
||||||
boost::system::error_code ecode;
|
boost::system::error_code ecode;
|
||||||
address->host = boost::asio::ip::address::from_string (value, ecode);
|
address->host = boost::asio::ip::address::from_string (value, ecode);
|
||||||
if (ecode)
|
if (!ecode)
|
||||||
{
|
{
|
||||||
if (address->transportStyle == eTransportNTCP)
|
#if BOOST_VERSION >= 104900
|
||||||
{
|
if (!address->host.is_unspecified ()) // check if address is valid
|
||||||
supportedTransports |= eNTCPV4; // TODO:
|
#else
|
||||||
address->addressString = value;
|
address->host.to_string (ecode);
|
||||||
}
|
if (!ecode)
|
||||||
else
|
#endif
|
||||||
{
|
{
|
||||||
supportedTransports |= eSSUV4; // TODO:
|
// add supported protocol
|
||||||
address->addressString = value;
|
if (address->host.is_v4 ())
|
||||||
}
|
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
|
||||||
}
|
else
|
||||||
else
|
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
|
||||||
{
|
}
|
||||||
// add supported protocol
|
|
||||||
if (address->host.is_v4 ())
|
|
||||||
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
|
|
||||||
else
|
|
||||||
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp (key, "port"))
|
else if (!strcmp (key, "port"))
|
||||||
|
|
|
@ -102,7 +102,6 @@ namespace data
|
||||||
{
|
{
|
||||||
TransportStyle transportStyle;
|
TransportStyle transportStyle;
|
||||||
boost::asio::ip::address host;
|
boost::asio::ip::address host;
|
||||||
std::string addressString;
|
|
||||||
int port;
|
int port;
|
||||||
uint64_t date;
|
uint64_t date;
|
||||||
uint8_t cost;
|
uint8_t cost;
|
||||||
|
@ -170,6 +169,7 @@ namespace data
|
||||||
void EnableV4 ();
|
void EnableV4 ();
|
||||||
void DisableV4 ();
|
void DisableV4 ();
|
||||||
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
bool IsCompatible (const RouterInfo& other) const { return m_SupportedTransports & other.m_SupportedTransports; };
|
||||||
|
bool HasValidAddresses () const { return m_SupportedTransports; };
|
||||||
bool UsesIntroducer () const;
|
bool UsesIntroducer () const;
|
||||||
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
|
bool IsIntroducer () const { return m_Caps & eSSUIntroducer; };
|
||||||
bool IsPeerTesting () const { return m_Caps & eSSUTesting; };
|
bool IsPeerTesting () const { return m_Caps & eSSUTesting; };
|
||||||
|
|
|
@ -97,7 +97,7 @@ namespace crypto
|
||||||
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
|
uint8_t publicKey[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
|
size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||||
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
|
EVP_PKEY_get_raw_public_key (m_Pkey, publicKey, &len);
|
||||||
if (memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
|
LogPrint (eLogWarning, "EdDSA public key mismatch. Fallback");
|
||||||
EVP_PKEY_free (m_Pkey);
|
EVP_PKEY_free (m_Pkey);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
@ -37,7 +39,6 @@ namespace util
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
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
|
||||||
|
|
||||||
static void SyncTimeWithNTP (const std::string& address)
|
static void SyncTimeWithNTP (const std::string& address)
|
||||||
|
@ -178,6 +179,19 @@ namespace util
|
||||||
{
|
{
|
||||||
return GetLocalSecondsSinceEpoch () + g_TimeOffset;
|
return GetLocalSecondsSinceEpoch () + g_TimeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetCurrentDate (char * date)
|
||||||
|
{
|
||||||
|
time_t t = time (nullptr);
|
||||||
|
struct tm tm;
|
||||||
|
#ifdef _WIN32
|
||||||
|
gmtime_s(&tm, &t);
|
||||||
|
sprintf_s(date, 9, "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
||||||
|
#else
|
||||||
|
gmtime_r(&t, &tm);
|
||||||
|
sprintf(date, "%04i%02i%02i", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ namespace util
|
||||||
uint32_t GetHoursSinceEpoch ();
|
uint32_t GetHoursSinceEpoch ();
|
||||||
uint64_t GetSecondsSinceEpoch ();
|
uint64_t GetSecondsSinceEpoch ();
|
||||||
|
|
||||||
|
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
|
||||||
|
|
||||||
class NTPTimeSync
|
class NTPTimeSync
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -426,37 +426,28 @@ namespace transport
|
||||||
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
auto address = peer.router->GetNTCPAddress (!context.SupportsV6 ());
|
||||||
if (address && m_NTCPServer)
|
if (address && m_NTCPServer)
|
||||||
{
|
{
|
||||||
#if BOOST_VERSION >= 104900
|
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
|
||||||
if (!address->host.is_unspecified ()) // we have address now
|
|
||||||
#else
|
|
||||||
boost::system::error_code ecode;
|
|
||||||
address->host.to_string (ecode);
|
|
||||||
if (!ecode)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
if (!peer.router->UsesIntroducer () && !peer.router->IsUnreachable ())
|
if(!m_NTCPServer->ShouldLimit())
|
||||||
{
|
{
|
||||||
if(!m_NTCPServer->ShouldLimit())
|
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
||||||
|
if(m_NTCPServer->UsingProxy())
|
||||||
{
|
{
|
||||||
auto s = std::make_shared<NTCPSession> (*m_NTCPServer, peer.router);
|
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
|
||||||
if(m_NTCPServer->UsingProxy())
|
std::string addr = address->host.to_string();
|
||||||
{
|
|
||||||
NTCPServer::RemoteAddressType remote = NTCPServer::eIP4Address;
|
|
||||||
std::string addr = address->host.to_string();
|
|
||||||
|
|
||||||
if(address->host.is_v6())
|
if(address->host.is_v6())
|
||||||
remote = NTCPServer::eIP6Address;
|
remote = NTCPServer::eIP6Address;
|
||||||
|
|
||||||
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
|
m_NTCPServer->ConnectWithProxy(addr, address->port, remote, s);
|
||||||
}
|
|
||||||
else
|
|
||||||
m_NTCPServer->Connect (address->host, address->port, s);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
m_NTCPServer->Connect (address->host, address->port, s);
|
||||||
LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogPrint(eLogWarning, "Transports: NTCP Limit hit falling back to SSU");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,17 +460,8 @@ namespace transport
|
||||||
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
if (m_SSUServer && peer.router->IsSSU (!context.SupportsV6 ()))
|
||||||
{
|
{
|
||||||
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
|
auto address = peer.router->GetSSUAddress (!context.SupportsV6 ());
|
||||||
#if BOOST_VERSION >= 104900
|
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
||||||
if (!address->host.is_unspecified ()) // we have address now
|
return true;
|
||||||
#else
|
|
||||||
boost::system::error_code ecode;
|
|
||||||
address->host.to_string (ecode);
|
|
||||||
if (!ecode)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
m_SSUServer->CreateSession (peer.router, address->host, address->port);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
|
LogPrint (eLogInfo, "Transports: No NTCP or SSU addresses available");
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
|
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
|
||||||
|
|
||||||
#define I2PD_VERSION_MAJOR 2
|
#define I2PD_VERSION_MAJOR 2
|
||||||
#define I2PD_VERSION_MINOR 23
|
#define I2PD_VERSION_MINOR 24
|
||||||
#define I2PD_VERSION_MICRO 0
|
#define I2PD_VERSION_MICRO 0
|
||||||
#define I2PD_VERSION_PATCH 0
|
#define I2PD_VERSION_PATCH 0
|
||||||
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
#define I2P_VERSION_MAJOR 0
|
#define I2P_VERSION_MAJOR 0
|
||||||
#define I2P_VERSION_MINOR 9
|
#define I2P_VERSION_MINOR 9
|
||||||
#define I2P_VERSION_MICRO 38
|
#define I2P_VERSION_MICRO 39
|
||||||
#define I2P_VERSION_PATCH 0
|
#define I2P_VERSION_PATCH 0
|
||||||
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
|
@ -30,7 +31,10 @@ namespace client
|
||||||
std::string etagsPath, indexPath, localPath;
|
std::string etagsPath, indexPath, localPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32") {};
|
AddressBookFilesystemStorage (): storage("addressbook", "b", "", "b32")
|
||||||
|
{
|
||||||
|
i2p::config::GetOption("persist.addressbook", m_IsPersist);
|
||||||
|
}
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const;
|
std::shared_ptr<const i2p::data::IdentityEx> GetAddress (const i2p::data::IdentHash& ident) const;
|
||||||
void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
|
void AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address);
|
||||||
void RemoveAddress (const i2p::data::IdentHash& ident);
|
void RemoveAddress (const i2p::data::IdentHash& ident);
|
||||||
|
@ -42,11 +46,15 @@ namespace client
|
||||||
|
|
||||||
void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified);
|
void SaveEtag (const i2p::data::IdentHash& subsciption, const std::string& etag, const std::string& lastModified);
|
||||||
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
|
bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified);
|
||||||
|
void ResetEtags ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses); // returns -1 if can't open file, otherwise number of records
|
int LoadFromFile (const std::string& filename, std::map<std::string, i2p::data::IdentHash>& addresses); // returns -1 if can't open file, otherwise number of records
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
bool m_IsPersist;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool AddressBookFilesystemStorage::Init()
|
bool AddressBookFilesystemStorage::Init()
|
||||||
|
@ -69,6 +77,11 @@ namespace client
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const
|
std::shared_ptr<const i2p::data::IdentityEx> AddressBookFilesystemStorage::GetAddress (const i2p::data::IdentHash& ident) const
|
||||||
{
|
{
|
||||||
|
if (!m_IsPersist)
|
||||||
|
{
|
||||||
|
LogPrint(eLogDebug, "Addressbook: Persistance is disabled");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
std::string filename = storage.Path(ident.ToBase32());
|
std::string filename = storage.Path(ident.ToBase32());
|
||||||
std::ifstream f(filename, std::ifstream::binary);
|
std::ifstream f(filename, std::ifstream::binary);
|
||||||
if (!f.is_open ()) {
|
if (!f.is_open ()) {
|
||||||
|
@ -92,6 +105,7 @@ namespace client
|
||||||
|
|
||||||
void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
|
void AddressBookFilesystemStorage::AddAddress (std::shared_ptr<const i2p::data::IdentityEx> address)
|
||||||
{
|
{
|
||||||
|
if (!m_IsPersist) return;
|
||||||
std::string path = storage.Path( address->GetIdentHash().ToBase32() );
|
std::string path = storage.Path( address->GetIdentHash().ToBase32() );
|
||||||
std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
|
std::ofstream f (path, std::ofstream::binary | std::ofstream::out);
|
||||||
if (!f.is_open ()) {
|
if (!f.is_open ()) {
|
||||||
|
@ -107,6 +121,7 @@ namespace client
|
||||||
|
|
||||||
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
|
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
|
if (!m_IsPersist) return;
|
||||||
storage.Remove( ident.ToBase32() );
|
storage.Remove( ident.ToBase32() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +220,17 @@ namespace client
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddressBookFilesystemStorage::ResetEtags ()
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Addressbook: resetting eTags");
|
||||||
|
for (boost::filesystem::directory_iterator it (etagsPath); it != boost::filesystem::directory_iterator (); ++it)
|
||||||
|
{
|
||||||
|
if (!boost::filesystem::is_regular_file (it->status ()))
|
||||||
|
continue;
|
||||||
|
boost::filesystem::remove (it->path ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
|
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
|
||||||
m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
|
m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr)
|
||||||
|
@ -343,6 +369,9 @@ namespace client
|
||||||
LoadHostsFromStream (f, false);
|
LoadHostsFromStream (f, false);
|
||||||
m_IsLoaded = true;
|
m_IsLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset eTags, because we don’t know how old hosts.txt is or can't load addressbook
|
||||||
|
m_Storage->ResetEtags ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AddressBook::LoadHostsFromStream (std::istream& f, bool is_update)
|
bool AddressBook::LoadHostsFromStream (std::istream& f, bool is_update)
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace client
|
||||||
|
|
||||||
virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
|
virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0;
|
||||||
virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
|
virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0;
|
||||||
|
virtual void ResetEtags () = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AddressBookSubscription;
|
class AddressBookSubscription;
|
||||||
|
|
|
@ -63,14 +63,14 @@ namespace client
|
||||||
|
|
||||||
void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len)
|
void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len);
|
auto ls = std::make_shared<i2p::data::LocalLeaseSet> (m_Identity, buf, len);
|
||||||
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
||||||
SetLeaseSet (ls);
|
SetLeaseSet (ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len)
|
void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
auto ls = new i2p::data::LocalLeaseSet2 (storeType, m_Identity, buf, len);
|
auto ls = std::make_shared<i2p::data::LocalLeaseSet2> (storeType, m_Identity, buf, len);
|
||||||
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
||||||
SetLeaseSet (ls);
|
SetLeaseSet (ls);
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,6 +359,24 @@ namespace client
|
||||||
}
|
}
|
||||||
forward = std::make_shared<boost::asio::ip::udp::endpoint>(addr, port);
|
forward = std::make_shared<boost::asio::ip::udp::endpoint>(addr, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ensure we actually received a destination
|
||||||
|
if (destination.empty())
|
||||||
|
{
|
||||||
|
SendMessageReply (SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination != SAM_VALUE_TRANSIENT)
|
||||||
|
{
|
||||||
|
//ensure it's a base64 string
|
||||||
|
i2p::data::PrivateKeys keys;
|
||||||
|
if (!keys.FromBase64(destination))
|
||||||
|
{
|
||||||
|
SendMessageReply(SAM_SESSION_STATUS_INVALID_KEY, strlen(SAM_SESSION_STATUS_INVALID_KEY), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create destination
|
// create destination
|
||||||
auto session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms);
|
auto session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
<translation type="qt" />
|
<translation type="qt" />
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.24.0" date="2019-03-21" />
|
||||||
<release version="2.23.0" date="2019-01-21" />
|
<release version="2.23.0" date="2019-01-21" />
|
||||||
<release version="2.22.0" date="2018-11-09" />
|
<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" />
|
||||||
|
|
Loading…
Add table
Reference in a new issue