diff --git a/.travis.yml b/.travis.yml index 819c75f4..7dd14872 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,34 +2,53 @@ language: cpp cache: apt: true os: - - linux -sudo: required +- linux +- osx dist: trusty +sudo: required +compiler: +- g++ +- clang++ +env: + global: + - MAKEFLAGS="-j 2" + matrix: + - BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes + - BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no + - BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes + - BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no +matrix: + exclude: + - os: osx + env: BUILD_TYPE=cmake UPNP=ON MAKE_UPNP=yes + - os: osx + env: BUILD_TYPE=cmake UPNP=OFF MAKE_UPNP=no + - os: linux + compiler: clang++ + env: BUILD_TYPE=make UPNP=ON MAKE_UPNP=yes + - os: linux + compiler: clang++ + env: BUILD_TYPE=make UPNP=OFF MAKE_UPNP=no addons: apt: packages: - - build-essential - - cmake - - g++ - - clang - - libboost-chrono-dev - - libboost-date-time-dev - - libboost-filesystem-dev - - libboost-program-options-dev - - libboost-system-dev - - libboost-thread-dev - - libminiupnpc-dev - - libssl-dev -compiler: - - gcc - - clang + - build-essential + - cmake + - g++ + - clang + - libboost-chrono-dev + - libboost-date-time-dev + - libboost-filesystem-dev + - libboost-program-options-dev + - libboost-system-dev + - libboost-thread-dev + - libminiupnpc-dev + - libssl-dev before_install: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install openssl miniupnpc ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew unlink boost openssl && brew link boost openssl -f ; fi -env: - matrix: - - BUILD_TYPE=Release UPNP=ON - - BUILD_TYPE=Release UPNP=OFF +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install libressl miniupnpc ; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew outdated boost || brew upgrade boost ; fi script: - - cd build && cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DWITH_UPNP=${UPNP} && make +- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "cmake" ]]; then cd build && cmake -DCMAKE_BUILD_TYPE=Release -DWITH_UPNP=${UPNP} && make ; fi +- if [[ "$TRAVIS_OS_NAME" == "linux" && "$BUILD_TYPE" == "make" ]]; then make USE_UPNP=${MAKE_UPNP} ; fi +- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make HOMEBREW=1 USE_UPNP=${MAKE_UPNP} ; fi diff --git a/ChangeLog b/ChangeLog index 29d3ced3..b7bb8924 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,23 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.16.0] - 2017-11-13 +### Added +- https and "Connect" method for HTTP proxy +- outproxy for HTTP proxy +- initial support of ECIES crypto +- NTCP soft and hard descriptors limits +- Support full timestamps in logs +### Changed +- Faster implmentation of GOST R 34.11 hash +- Reject routers with RSA signtures +- Reload config and shudown from Windows GUI +- Update tunnels address(destination) without restart +### Fixed +- BOB crashes if destination is not set +- Correct SAM tunnel name +- QT GUI issues + ## [2.15.0] - 2017-08-17 ### Added - QT GUI diff --git a/Makefile.homebrew b/Makefile.homebrew index 4f69ae36..287dea05 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -3,27 +3,30 @@ BREWROOT = /usr/local BOOSTROOT = ${BREWROOT}/opt/boost SSLROOT = ${BREWROOT}/opt/libressl UPNPROOT = ${BREWROOT}/opt/miniupnpc -CXX = clang++ CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include +ifndef TRAVIS + CXX = clang++ +endif + ifeq ($(USE_STATIC),yes) -LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread + LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread else -LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib -LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + LDFLAGS = -L${SSLROOT}/lib -L${BOOSTROOT}/lib + LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread endif ifeq ($(USE_UPNP),yes) LDFLAGS += -ldl CXXFLAGS += -DUSE_UPNP - INCFLAGS += -I${UPNPROOT}/include - ifeq ($(USE_STATIC),yes) - LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a - else - LDFLAGS += -L${UPNPROOT}/lib - LDLIBS += -lminiupnpc - endif + INCFLAGS += -I${UPNPROOT}/include + ifeq ($(USE_STATIC),yes) + LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a + else + LDFLAGS += -L${UPNPROOT}/lib + LDLIBS += -lminiupnpc + endif endif # OSX Notes diff --git a/Makefile.osx b/Makefile.osx index 8d6a1c65..f6a0847d 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -5,29 +5,29 @@ INCFLAGS = -I/usr/local/include LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib ifeq ($(USE_STATIC),yes) -LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread + LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread else -LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread endif ifeq ($(USE_UPNP),yes) - LDFLAGS += -ldl - CXXFLAGS += -DUSE_UPNP -ifeq ($(USE_STATIC),yes) - LDLIBS += /usr/local/lib/libminiupnpc.a -else - LDLIBS += -lminiupnpc -endif + LDFLAGS += -ldl + CXXFLAGS += -DUSE_UPNP + ifeq ($(USE_STATIC),yes) + LDLIBS += /usr/local/lib/libminiupnpc.a + else + LDLIBS += -lminiupnpc + endif endif ifeq ($(USE_AESNI),1) - CXXFLAGS += -maes -DAESNI + CXXFLAGS += -maes -DAESNI else - CXXFLAGS += -msse + CXXFLAGS += -msse endif ifeq ($(USE_AVX),1) - CXXFLAGS += -mavx + CXXFLAGS += -mavx endif # Disabled, since it will be the default make rule. I think its better diff --git a/README.md b/README.md index c941eb3b..d5d7ceb9 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,9 @@ Build instructions: **Supported systems:** -* GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) -* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) -* Mac OS X +* GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) +* Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) +* Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * FreeBSD * Android * iOS diff --git a/Win32/installer.iss b/Win32/installer.iss index 55f89a32..86edf220 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.15.0" +#define I2Pd_ver "2.16.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index e4023db5..e542b42e 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ diff --git a/appveyor.yml b/appveyor.yml index 59011e77..b1892b80 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.15.{build} +version: 2.16.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 1f18beb7..db0fd33f 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -150,7 +150,7 @@ else() if (MSYS OR MINGW) add_definitions( -DWIN32_LEAN_AND_MEAN ) endif () - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter" ) set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic" ) # TODO: The following is incompatible with static build and enabled hardening for OpenWRT. # Multiple definitions of __stack_chk_fail (libssp & libc) @@ -180,7 +180,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # more tweaks if (NOT (MSVC OR MSYS OR APPLE)) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++" ) + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-const-variable -Wno-overloaded-virtual -Wno-c99-extensions" ) endif() endif () diff --git a/contrib/certificates/reseed/r4sas_at_mail.i2p.crt b/contrib/certificates/reseed/r4sas_at_mail.i2p.crt deleted file mode 100644 index b0c8d749..00000000 --- a/contrib/certificates/reseed/r4sas_at_mail.i2p.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFezCCA2OgAwIBAgIEb8xTzzANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxHjAcBgNVBAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEL -MAkGA1UEChMCWFgxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOcjRzYXNAbWFpbC5p -MnAwHhcNMTYwODExMjIyNDM2WhcNMjYwODExMjIyNDM2WjBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxHjAcBgNVBAcTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEL -MAkGA1UEChMCWFgxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOcjRzYXNAbWFpbC5p -MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDjUMy/aYd0i6Oc3rdc -24V/fM2vhviH+cNhAOXsMSrwDSVbFQkuDPIfq4fo1A25rsyULR57vy7XKA51OstX -GvREPDhth4cMZjthq0f8AVzPq2vIk8Po65uvKR190yupPQ4FhvGeRkHkqp+SqoIJ -lClD8xZEHrUHSYZotm5TLWIgSwa4DuO1q3bMRI8oIWzqhv99FtlmHlC8fjVUN4mR -2czhABr0u6RMPOtJwTVxWgT1PKXiLWfmeHb63TcPYGgpJ39iMDOjtgY9jYueoO8J -uGJJtkGRIRjOuhDFE9NUlNnljUxUDWvMU7zCO4ozaKMZgoxr1WoIO6ubI/003I53 -sZ0Q5h8yfz+QreEw3wzjxnQSkejG5c3NIvJSiu0ylOqDWmnj0v1Jv/P0qAMU4bt/ -ZWj0GOrYfPn9STg0VxMOQwQ2o15GAcbr6PFI56U2IJhZAeER3hIe2kOl6591jQ67 -zvOjPRRh2q05Ss8yo7nEpYUiB/FrE6RssJ5tVwX6e6Tq4Z1frINanIkUkToTkypP -Fn2T/KV2lak9rLuxzvhiDobu5iGCR323zFcFEpGq4Wsopx1uRT9+71G/ejw8pKTf -kQ7XiGaaxFyZuMuOz3bFkTuoTmAkUQTlRjGw2DmKZi/apcN+VQgpq9tQpS10pEUy -DCVdtw1AdlOnwb+Hf3X0Uz6OjwIDAQABoyEwHzAdBgNVHQ4EFgQUqLBlSlnqCo25 -sIduMPm4iROMqkAwDQYJKoZIhvcNAQENBQADggIBAGWv8rDTzqhHkjqDOT+Ba2bs -gVddpCNa94RQoOn2DUSu4c+yuWJLSctjpX7gswB6qvWk5Ojfafop8jJW8zuozJrO -76b9345S/VnnbHVSoVfIpF9Fve1Xc8nvU4ylRcAMwhf8N3Md5Yc1kb+P7NtTTwMZ -TBR3xY3fVxv3qTpKApWQKkUiqM7yJKOfS8xcK/pjO/3oRUwfA9DHugCUpgSidlN+ -JkZmgwAcA3/WMlDdNKmKnWLGB2Ea+W6kIx5TDFfjf11rbjuwXhDLyaOK88qlN0W2 -hYa31UDSEYYQd3gMG1gjVc+9vZA/Vr0+SF5ULN9QLjB18CVIdPv92mBjJQRmJSVW -b1qwZI0jf/V+1fu9H9r7sE4CId3+WGOek3UNRNZLOVZCSiFq/b9cswcQZGjw6aE+ -1FNjw1HW9CLoNcg74Kr98QouOoeRSofQYZiYqaM9Sz/MsinYMIRGRGw3Uq1uNRo0 -WgoOngmZSKGaW5PFR19uuuNIVB4fCShqBVyrguW4xIskta1JVFoggFeOeTwk6/kH -S5roMzyB/kzv83A2IB0VxqbiDj8khgdm1Us6HCCmU+iTRVyG28gFklCJ8dQfxgGH -W2gpIwvxYLyNP14/7E1oF7/NfHmyjAVzYnR5Xw2wE4tvSHuIrHhj6Q26VB3vze6j -E/w1AJEepnw/KfHqS3bw ------END CERTIFICATE----- diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index 4dd21897..d9fe951b 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -23,7 +23,8 @@ # log = file ## Path to logfile (default - autodetect) # logfile = /var/log/i2pd.log -## Log messages above this level (debug, *info, warn, error) +## Log messages above this level (debug, *info, warn, error, none) +## If you set it to none, logging will be disabled # loglevel = info ## Path to storage of i2pd data (RI, keys, peer profiles, ...) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index d898249b..2e3d2efb 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,7 +1,7 @@ %define build_timestamp %(date +"%Y%m%d") Name: i2pd -Version: 2.15.0 +Version: 2.16.0 Release: %{build_timestamp}git%{?dist} Summary: I2P router written in C++ @@ -103,6 +103,20 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Nov 13 2017 orignal - 2.16.0 +- Added https and "Connect" method for HTTP proxy +- Added outproxy for HTTP proxy +- Added initial support of ECIES crypto +- Added NTCP soft and hard descriptors limits +- Added support full timestamps in logs +- Changed faster implmentation of GOST R 34.11 hash +- Changed reject routers with RSA signtures +- Changed reload config and shudown from Windows GUI +- Changed update tunnels address(destination) without restart +- Fixed BOB crashes if destination is not set +- Fixed correct SAM tunnel name +- Fixed QT GUI issues + * Thu Aug 17 2017 orignal - 2.15.0 - Added QT GUI - Added ability add and remove I2P tunnels without restart diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 0577ac15..5fa65679 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -60,12 +60,14 @@ namespace http { " .tunnel.established { color: #56B734; }\r\n" " .tunnel.expiring { color: #D3AE3F; }\r\n" " .tunnel.failed { color: #D33F3F; }\r\n" - " .tunnel.another { color: #434343; }\r\n" + " .tunnel.building { color: #434343; }\r\n" " caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n" " table { width: 100%; border-collapse: collapse; text-align: center; }\r\n" - " .private { background: black; color: black; } .private:hover { background: black; color: white } \r\n" - " .slide p, .slide [type='checkbox']{ display:none; } \r\n" - " .slide [type='checkbox']:checked ~ p { display:block; } \r\n" + " .slide label { color: #894C84 }\r\n" + " .slide p, .slide [type='checkbox']{ display:none; }\r\n" + " .slide [type='checkbox']:checked ~ p { display:block; margin-top: 0; padding: 0; }\r\n" + " .disabled:after { color: #D33F3F; content: \"Disabled\" }\r\n" + " .enabled:after { color: #56B734; content: \"Enabled\" }\r\n" "\r\n"; const char HTTP_PAGE_TUNNELS[] = "tunnels"; @@ -270,7 +272,17 @@ namespace http { size_t transitTunnelCount = i2p::tunnel::tunnels.CountTransitTunnels(); s << "Client Tunnels: " << std::to_string(clientTunnelCount) << " "; - s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n"; + s << "Transit Tunnels: " << std::to_string(transitTunnelCount) << "
\r\n
\r\n"; + + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + s << "\r\n"; + bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol); + s << "\r\n"; + s << "
Services
ServiceState
" << "HTTP Proxy" << "
" << "SOCKS Proxy" << "
" << "BOB" << "
" << "SAM" << "
" << "I2CP" << "
" << "I2PControl" << "
\r\n"; } void ShowLocalDestinations (std::stringstream& s) @@ -284,7 +296,7 @@ namespace http { } auto i2cpServer = i2p::client::context.GetI2CPServer (); - if (i2cpServer) + if (i2cpServer && !(i2cpServer->GetSessions ().empty ())) { s << "
I2CP Local Destinations:
\r\n
\r\n"; for (auto& it: i2cpServer->GetSessions ()) @@ -304,14 +316,14 @@ namespace http { { s << "Base64:
\r\n
\r\n
\r\n"; - s << "LeaseSets: " << dest->GetNumRemoteLeaseSets () << "
\r\n"; if(dest->GetNumRemoteLeaseSets()) { - s << "
\r\n\r\n

\r\n"; + s << "

\r\n\r\n

\r\n"; for(auto& it: dest->GetLeaseSets ()) s << it.second->GetIdentHash ().ToBase32 () << "
\r\n"; s << "

\r\n
\r\n"; - } + } else + s << "LeaseSets: 0
\r\n"; auto pool = dest->GetTunnelPool (); if (pool) { @@ -401,7 +413,7 @@ namespace http { void ShowLeasesSets(std::stringstream& s) { - s << "
LeaseSets (click on to show info):

\r\n"; + s << "LeaseSets:
\r\n
\r\n"; int counter = 1; // for each lease set i2p::data::netdb.VisitLeaseSets( @@ -434,6 +446,7 @@ namespace http { void ShowTunnels (std::stringstream& s) { + s << "Tunnels:
\r\n
\r\n"; s << "Queue size: " << i2p::tunnel::tunnels.GetQueueSize () << "
\r\n"; s << "Inbound tunnels:
\r\n"; @@ -457,7 +470,7 @@ namespace http { static void ShowCommands (std::stringstream& s, uint32_t token) { /* commands */ - s << "Router Commands
\r\n"; + s << "Router Commands
\r\n
\r\n"; s << " Run peer test
\r\n"; //s << " Reload config
\r\n"; if (i2p::context.AcceptsTunnels ()) @@ -529,13 +542,13 @@ namespace http { } if (!tmp_s.str ().empty ()) { - s << "NTCP ( " << cnt << " )
\r\n"; - s << tmp_s.str () << "
\r\n"; + s << "
\r\n\r\n

"; + s << tmp_s.str () << "

\r\n
\r\n"; } if (!tmp_s6.str ().empty ()) { - s << "NTCP6 ( " << cnt6 << " )
\r\n"; - s << tmp_s6.str () << "
\r\n"; + s << "
\r\n\r\n

"; + s << tmp_s6.str () << "

\r\n
\r\n"; } } } @@ -545,7 +558,7 @@ namespace http { auto sessions = ssuServer->GetSessions (); if (!sessions.empty ()) { - s << "SSU ( " << (int) sessions.size() << " )
\r\n"; + s << "
\r\n\r\n

"; for (const auto& it: sessions) { auto endpoint = it.second->GetRemoteEndpoint (); @@ -557,12 +570,12 @@ namespace http { s << " [itag:" << it.second->GetRelayTag () << "]"; s << "
\r\n" << std::endl; } - s << "
\r\n"; + s << "

\r\n
\r\n"; } auto sessions6 = ssuServer->GetSessionsV6 (); if (!sessions6.empty ()) { - s << "SSU6 ( " << (int) sessions6.size() << " )
\r\n"; + s << "
\r\n\r\n

"; for (const auto& it: sessions6) { auto endpoint = it.second->GetRemoteEndpoint (); @@ -574,7 +587,7 @@ namespace http { s << " [itag:" << it.second->GetRelayTag () << "]"; s << "
\r\n" << std::endl; } - s << "
\r\n"; + s << "

\r\n
\r\n"; } } } diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index d1a190d6..ba7b408c 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -79,11 +79,14 @@ namespace transport void UPnP::Discover () { - int nerror = 0; #if MINIUPNPC_API_VERSION >= 14 + int nerror = 0; m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror); -#else +#elif ( MINIUPNPC_API_VERSION >= 8 || defined(UPNPDISCOVER_SUCCESS) ) + int nerror = 0; m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror); +#else + m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0); #endif { // notify satrting thread @@ -155,7 +158,11 @@ namespace transport std::string strType (GetProto (address)), strPort (std::to_string (address->port)); int r; std::string strDesc; i2p::config::GetOption("upnp.name", strDesc); +#ifdef UPNPDISCOVER_SUCCESS r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0"); +#else + r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0); +#endif if (r!=UPNPCOMMAND_SUCCESS) { LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r); diff --git a/debian/changelog b/debian/changelog index 62d8908b..80ccd0f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.16.0-1) unstable; urgency=low + + * updated to version 2.16.0/0.9.32 + + -- orignal Mon, 13 Nov 2017 18:00:00 +0000 + i2pd (2.15.0-1) unstable; urgency=low * updated to version 2.15.0/0.9.31 diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 4997852a..636e4986 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -179,6 +179,7 @@ namespace config { ("reseed.floodfill", value()->default_value(""), "Path to router info of floodfill to reseed from") ("reseed.file", value()->default_value(""), "Path to local .su3 file or HTTPS URL to reseed from") ("reseed.zipfile", value()->default_value(""), "Path to local .zip file to reseed from") + ("reseed.proxy", value()->default_value(""), "url for reseed proxy, supports http/socks") ("reseed.urls", value()->default_value( "https://reseed.i2p-projekt.de/," "https://i2p.mooo.com/netDb/," diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index ddd42f0d..fd0ef4bd 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -14,20 +14,20 @@ namespace i2p { namespace crypto -{ +{ const uint8_t elgp_[256]= { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, - 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, @@ -36,7 +36,7 @@ namespace crypto }; const int elgg_ = 2; - + const uint8_t dsap_[128]= { 0x9c, 0x05, 0xb2, 0xaa, 0x96, 0x0d, 0x9b, 0x97, 0xb8, 0x93, 0x19, 0x63, 0xc9, 0xcc, 0x9e, 0x8c, @@ -45,7 +45,7 @@ namespace crypto 0x76, 0x55, 0xc4, 0x96, 0x4a, 0xfa, 0xa2, 0xb3, 0x37, 0xe9, 0x6a, 0xd3, 0x16, 0xb9, 0xfb, 0x1c, 0xc5, 0x64, 0xb5, 0xae, 0xc5, 0xb6, 0x9a, 0x9f, 0xf6, 0xc3, 0xe4, 0x54, 0x87, 0x07, 0xfe, 0xf8, 0x50, 0x3d, 0x91, 0xdd, 0x86, 0x02, 0xe8, 0x67, 0xe6, 0xd3, 0x5d, 0x22, 0x35, 0xc1, 0x86, 0x9c, - 0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11, + 0xe2, 0x47, 0x9c, 0x3b, 0x9d, 0x54, 0x01, 0xde, 0x04, 0xe0, 0x72, 0x7f, 0xb3, 0x3d, 0x65, 0x11, 0x28, 0x5d, 0x4c, 0xf2, 0x95, 0x38, 0xd9, 0xe3, 0xb6, 0x05, 0x1f, 0x5b, 0x22, 0xcc, 0x1c, 0x93 }; @@ -63,27 +63,27 @@ namespace crypto 0x3c, 0x43, 0x1f, 0x46, 0x98, 0x59, 0x9d, 0xda, 0x02, 0x45, 0x18, 0x24, 0xff, 0x36, 0x97, 0x52, 0x59, 0x36, 0x47, 0xcc, 0x3d, 0xdc, 0x19, 0x7d, 0xe9, 0x85, 0xe4, 0x3d, 0x13, 0x6c, 0xdc, 0xfc, 0x6b, 0xd5, 0x40, 0x9c, 0xd2, 0xf4, 0x50, 0x82, 0x11, 0x42, 0xa5, 0xe6, 0xf8, 0xeb, 0x1c, 0x3a, - 0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c, - 0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82 + 0xb5, 0xd0, 0x48, 0x4b, 0x81, 0x29, 0xfc, 0xf1, 0x7b, 0xce, 0x4f, 0x7f, 0x33, 0x32, 0x1c, 0x3c, + 0xb3, 0xdb, 0xb1, 0x4a, 0x90, 0x5e, 0x7b, 0x2b, 0x3e, 0x93, 0xbe, 0x47, 0x08, 0xcb, 0xcc, 0x82 }; - const int rsae_ = 65537; - + const int rsae_ = 65537; + struct CryptoConstants { // DH/ElGamal BIGNUM * elgp; - BIGNUM * elgg; + BIGNUM * elgg; // DSA - BIGNUM * dsap; + BIGNUM * dsap; BIGNUM * dsaq; BIGNUM * dsag; // RSA BIGNUM * rsae; - - CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_, + + CryptoConstants (const uint8_t * elgp_, int elgg_, const uint8_t * dsap_, const uint8_t * dsaq_, const uint8_t * dsag_, int rsae_) { elgp = BN_new (); @@ -99,18 +99,18 @@ namespace crypto rsae = BN_new (); BN_set_word (rsae, rsae_); } - + ~CryptoConstants () { BN_free (elgp); BN_free (elgg); BN_free (dsap); BN_free (dsaq); BN_free (dsag); BN_free (rsae); - } - }; + } + }; static const CryptoConstants& GetCryptoConstants () { - static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_); + static CryptoConstants cryptoConstants (elgp_, elgg_, dsap_, dsaq_, dsag_, rsae_); return cryptoConstants; - } + } bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len) { @@ -119,34 +119,34 @@ namespace crypto BN_bn2bin (bn, buf + offset); memset (buf, 0, offset); return true; - } + } // RSA - #define rsae GetCryptoConstants ().rsae + #define rsae GetCryptoConstants ().rsae const BIGNUM * GetRSAE () { return rsae; - } + } // DSA - #define dsap GetCryptoConstants ().dsap + #define dsap GetCryptoConstants ().dsap #define dsaq GetCryptoConstants ().dsaq - #define dsag GetCryptoConstants ().dsag + #define dsag GetCryptoConstants ().dsag DSA * CreateDSA () { DSA * dsa = DSA_new (); - DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag)); + DSA_set0_pqg (dsa, BN_dup (dsap), BN_dup (dsaq), BN_dup (dsag)); DSA_set0_key (dsa, NULL, NULL); return dsa; } -// DH/ElGamal +// DH/ElGamal const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048; const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8; - + #define elgp GetCryptoConstants ().elgp #define elgg GetCryptoConstants ().elgg @@ -156,14 +156,14 @@ namespace crypto if (len <= 0) return; BN_CTX * ctx = BN_CTX_new (); g_MontCtx = BN_MONT_CTX_new (); - BN_MONT_CTX_set (g_MontCtx, elgp, ctx); + BN_MONT_CTX_set (g_MontCtx, elgp, ctx); auto montCtx = BN_MONT_CTX_new (); BN_MONT_CTX_copy (montCtx, g_MontCtx); for (int i = 0; i < len; i++) { table[i][0] = BN_new (); - if (!i) - BN_to_montgomery (table[0][0], elgg, montCtx, ctx); + if (!i) + BN_to_montgomery (table[0][0], elgg, montCtx, ctx); else BN_mod_mul_montgomery (table[i][0], table[i-1][254], table[i-1][0], montCtx, ctx); for (int j = 1; j < 255; j++) @@ -174,7 +174,7 @@ namespace crypto } BN_MONT_CTX_free (montCtx); BN_CTX_free (ctx); - } + } static void DestroyElggTable (BIGNUM * table[][255], int len) { @@ -186,9 +186,9 @@ namespace crypto } BN_MONT_CTX_free (g_MontCtx); } - + static BIGNUM * ElggPow (const uint8_t * exp, int len, BIGNUM * table[][255], BN_CTX * ctx) - // exp is in Big Endian + // exp is in Big Endian { if (len <= 0) return nullptr; auto montCtx = BN_MONT_CTX_new (); @@ -200,15 +200,15 @@ namespace crypto { if (exp[i]) BN_mod_mul_montgomery (res, res, table[len-1-i][exp[i]-1], montCtx, ctx); - } - else if (exp[i]) + } + else if (exp[i]) res = BN_dup (table[len-i-1][exp[i]-1]); - } + } if (res) BN_from_montgomery (res, res, montCtx, ctx); BN_MONT_CTX_free (montCtx); return res; - } + } static BIGNUM * ElggPow (const BIGNUM * exp, BIGNUM * table[][255], BN_CTX * ctx) { @@ -218,64 +218,64 @@ namespace crypto auto ret = ElggPow (buf, len, table, ctx); delete[] buf; return ret; - } + } + + static BIGNUM * (* g_ElggTable)[255] = nullptr; - static BIGNUM * (* g_ElggTable)[255] = nullptr; - // DH - + DHKeys::DHKeys () { m_DH = DH_new (); DH_set0_pqg (m_DH, BN_dup (elgp), NULL, BN_dup (elgg)); DH_set0_key (m_DH, NULL, NULL); } - + DHKeys::~DHKeys () { DH_free (m_DH); - } + } void DHKeys::GenerateKeys () { - BIGNUM * priv_key = NULL, * pub_key = NULL; -#if !defined(__x86_64__) // use short exponent for non x64 + BIGNUM * priv_key = NULL, * pub_key = NULL; +#if !defined(__x86_64__) // use short exponent for non x64 priv_key = BN_new (); BN_rand (priv_key, ELGAMAL_SHORT_EXPONENT_NUM_BITS, 0, 1); -#endif +#endif if (g_ElggTable) - { + { #if defined(__x86_64__) priv_key = BN_new (); BN_rand (priv_key, ELGAMAL_FULL_EXPONENT_NUM_BITS, 0, 1); -#endif +#endif auto ctx = BN_CTX_new (); pub_key = ElggPow (priv_key, g_ElggTable, ctx); DH_set0_key (m_DH, pub_key, priv_key); BN_CTX_free (ctx); - } + } else { DH_set0_key (m_DH, NULL, priv_key); DH_generate_key (m_DH); DH_get0_key (m_DH, (const BIGNUM **)&pub_key, (const BIGNUM **)&priv_key); - } + } bn2buf (pub_key, m_PublicKey, 256); - } - + } + void DHKeys::Agree (const uint8_t * pub, uint8_t * shared) { BIGNUM * pk = BN_bin2bn (pub, 256, NULL); DH_compute_key (shared, pk, m_DH); BN_free (pk); - } - + } + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) { BN_CTX_start (ctx); - // everything, but a, because a might come from table + // everything, but a, because a might come from table BIGNUM * k = BN_CTX_get (ctx); BIGNUM * y = BN_CTX_get (ctx); BIGNUM * b1 = BN_CTX_get (ctx); @@ -285,13 +285,13 @@ namespace crypto BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64 #else BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits -#endif +#endif // calculate a - BIGNUM * a; + BIGNUM * a; if (g_ElggTable) a = ElggPow (k, g_ElggTable, ctx); else - { + { a = BN_new (); BN_mod_exp (a, elgg, k, elgp, ctx); } @@ -315,17 +315,17 @@ namespace crypto bn2buf (a, encrypted + 1, 256); encrypted[257] = 0; bn2buf (b, encrypted + 258, 256); - } + } else { bn2buf (a, encrypted, 256); bn2buf (b, encrypted + 256, 256); - } + } BN_free (a); BN_CTX_end (ctx); } - bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, + bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) { BN_CTX_start (ctx); @@ -334,11 +334,11 @@ namespace crypto BN_sub (x, elgp, x); BN_sub_word (x, 1); // x = elgp - x- 1 BN_bin2bn (zeroPadding ? encrypted + 1 : encrypted, 256, a); BN_bin2bn (zeroPadding ? encrypted + 258 : encrypted + 256, 256, b); - // m = b*(a^x mod p) mod p + // m = b*(a^x mod p) mod p BN_mod_exp (x, a, x, elgp, ctx); - BN_mod_mul (b, b, x, elgp, ctx); + BN_mod_mul (b, b, x, elgp, ctx); uint8_t m[255]; - bn2buf (b, m, 255); + bn2buf (b, m, 255); BN_CTX_end (ctx); uint8_t hash[32]; SHA256 (m + 33, 222, hash); @@ -346,14 +346,14 @@ namespace crypto { LogPrint (eLogError, "ElGamal decrypt hash doesn't match"); return false; - } + } memcpy (data, m + 33, 222); return true; - } + } void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub) { -#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) +#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER) RAND_bytes (priv, 256); #else // lower 226 bits (28 bytes and 2 bits) only. short exponent @@ -364,10 +364,10 @@ namespace crypto priv[numZeroBytes] &= 0x03; #endif BN_CTX * ctx = BN_CTX_new (); - BIGNUM * p = BN_new (); + BIGNUM * p = BN_new (); BN_bin2bn (priv, 256, p); BN_mod_exp (p, elgg, p, elgp, ctx); - bn2buf (p, pub, 256); + bn2buf (p, pub, 256); BN_free (p); BN_CTX_free (ctx); } @@ -385,15 +385,15 @@ namespace crypto auto p = EC_POINT_new (curve); EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx); BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx); - EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr); + EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr); encrypted[0] = 0; bn2buf (x, encrypted + 1, len); bn2buf (y, encrypted + 1 + len, len); RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len); // ecryption key and iv - EC_POINT_mul (curve, p, nullptr, key, k, ctx); + EC_POINT_mul (curve, p, nullptr, key, k, ctx); EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr); - uint8_t keyBuf[64], iv[64], shared[32]; + uint8_t keyBuf[64], iv[64], shared[32]; bn2buf (x, keyBuf, len); bn2buf (y, iv, len); SHA256 (keyBuf, len, shared); @@ -421,16 +421,16 @@ namespace crypto int len = BN_num_bytes (q); // point for shared secret BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx); - BN_bin2bn (encrypted + 1, len, x); - BN_bin2bn (encrypted + 1 + len, len, y); + BN_bin2bn (encrypted + 1, len, x); + BN_bin2bn (encrypted + 1 + len, len, y); auto p = EC_POINT_new (curve); if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr)) { auto s = EC_POINT_new (curve); - EC_POINT_mul (curve, s, nullptr, p, key, ctx); + EC_POINT_mul (curve, s, nullptr, p, key, ctx); EC_POINT_get_affine_coordinates_GFp (curve, s, x, y, nullptr); EC_POINT_free (s); - uint8_t keyBuf[64], iv[64], shared[32]; + uint8_t keyBuf[64], iv[64], shared[32]; bn2buf (x, keyBuf, len); bn2buf (y, iv, len); SHA256 (keyBuf, len, shared); @@ -442,21 +442,21 @@ namespace crypto decryption.Decrypt (encrypted + 258, 256, m); // verify and copy uint8_t hash[32]; - SHA256 (m + 33, 222, hash); + SHA256 (m + 33, 222, hash); if (!memcmp (m + 1, hash, 32)) - memcpy (data, m + 33, 222); + memcpy (data, m + 33, 222); else { - LogPrint (eLogError, "ECICS decrypt hash doesn't match"); + LogPrint (eLogError, "ECIES decrypt hash doesn't match"); ret = false; - } + } } else { - LogPrint (eLogError, "ECICS decrypt point is invalid"); + LogPrint (eLogError, "ECIES decrypt point is invalid"); ret = false; } - + EC_POINT_free (p); BN_CTX_end (ctx); return ret; @@ -468,7 +468,7 @@ namespace crypto BIGNUM * q = BN_new (); EC_GROUP_get_order(curve, q, ctx); priv = BN_new (); - BN_rand_range (priv, q); + BN_rand_range (priv, q); pub = EC_POINT_new (curve); EC_POINT_mul (curve, pub, priv, nullptr, nullptr, ctx); BN_free (q); @@ -477,17 +477,17 @@ namespace crypto // HMAC const uint64_t IPAD = 0x3636363636363636; - const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; + const uint64_t OPAD = 0x5C5C5C5C5C5C5C5C; -#if defined(__AVX__) +#if defined(__AVX__) static const uint64_t ipads[] = { IPAD, IPAD, IPAD, IPAD }; static const uint64_t opads[] = { OPAD, OPAD, OPAD, OPAD }; #endif - + void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest) // key is 32 bytes // digest is 16 bytes - // block size is 64 bytes + // block size is 64 bytes { uint64_t buf[256]; uint64_t hash[12]; // 96 bytes @@ -498,53 +498,53 @@ namespace crypto "vmovups %[ipad], %%ymm1 \n" "vmovups %%ymm1, 32(%[buf]) \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n" - "vmovups %%ymm1, (%[buf]) \n" + "vmovups %%ymm1, (%[buf]) \n" "vmovups %[opad], %%ymm1 \n" - "vmovups %%ymm1, 32(%[hash]) \n" + "vmovups %%ymm1, 32(%[hash]) \n" "vxorps %%ymm0, %%ymm1, %%ymm1 \n" "vmovups %%ymm1, (%[hash]) \n" "vzeroall \n" // end of AVX - "movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes - : + "movups %%xmm0, 80(%[hash]) \n" // zero last 16 bytes + : : [key]"m"(*(const uint8_t *)key), [ipad]"m"(*ipads), [opad]"m"(*opads), - [buf]"r"(buf), [hash]"r"(hash) + [buf]"r"(buf), [hash]"r"(hash) : "memory", "%xmm0" // TODO: change to %ymm0 later ); #else // ikeypad - buf[0] = key.GetLL ()[0] ^ IPAD; - buf[1] = key.GetLL ()[1] ^ IPAD; - buf[2] = key.GetLL ()[2] ^ IPAD; - buf[3] = key.GetLL ()[3] ^ IPAD; + buf[0] = key.GetLL ()[0] ^ IPAD; + buf[1] = key.GetLL ()[1] ^ IPAD; + buf[2] = key.GetLL ()[2] ^ IPAD; + buf[3] = key.GetLL ()[3] ^ IPAD; buf[4] = IPAD; buf[5] = IPAD; buf[6] = IPAD; buf[7] = IPAD; - // okeypad - hash[0] = key.GetLL ()[0] ^ OPAD; - hash[1] = key.GetLL ()[1] ^ OPAD; - hash[2] = key.GetLL ()[2] ^ OPAD; - hash[3] = key.GetLL ()[3] ^ OPAD; + // okeypad + hash[0] = key.GetLL ()[0] ^ OPAD; + hash[1] = key.GetLL ()[1] ^ OPAD; + hash[2] = key.GetLL ()[2] ^ OPAD; + hash[3] = key.GetLL ()[3] ^ OPAD; hash[4] = OPAD; hash[5] = OPAD; hash[6] = OPAD; hash[7] = OPAD; // fill last 16 bytes with zeros (first hash size assumed 32 bytes in I2P) - memset (hash + 10, 0, 16); + memset (hash + 10, 0, 16); #endif // concatenate with msg memcpy (buf + 8, msg, len); // calculate first hash - MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes - + MD5((uint8_t *)buf, len + 64, (uint8_t *)(hash + 8)); // 16 bytes + // calculate digest MD5((uint8_t *)hash, 96, digest); } // AES #ifdef AESNI - + #define KeyExpansion256(round0,round1) \ "pshufd $0xff, %%xmm2, %%xmm2 \n" \ "movaps %%xmm1, %%xmm4 \n" \ @@ -566,7 +566,7 @@ namespace crypto "pslldq $4, %%xmm4 \n" \ "pxor %%xmm4, %%xmm3 \n" \ "pxor %%xmm2, %%xmm3 \n" \ - "movaps %%xmm3, "#round1"(%[sched]) \n" + "movaps %%xmm3, "#round1"(%[sched]) \n" void ECBCryptoAESNI::ExpandKey (const AESKey& key) { @@ -591,7 +591,7 @@ namespace crypto "aeskeygenassist $64, %%xmm3, %%xmm2 \n" // key expansion final "pshufd $0xff, %%xmm2, %%xmm2 \n" - "movaps %%xmm1, %%xmm4 \n" + "movaps %%xmm1, %%xmm4 \n" "pslldq $4, %%xmm4 \n" "pxor %%xmm4, %%xmm1 \n" "pslldq $4, %%xmm4 \n" @@ -622,17 +622,17 @@ namespace crypto "aesenc 192(%["#sched"]), %%xmm0 \n" \ "aesenc 208(%["#sched"]), %%xmm0 \n" \ "aesenclast 224(%["#sched"]), %%xmm0 \n" - + void ECBEncryptionAESNI::Encrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" EncryptAES256(sched) - "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[out]) \n" : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" ); - } + } #define DecryptAES256(sched) \ "pxor 224(%["#sched"]), %%xmm0 \n" \ @@ -650,22 +650,22 @@ namespace crypto "aesdec 32(%["#sched"]), %%xmm0 \n" \ "aesdec 16(%["#sched"]), %%xmm0 \n" \ "aesdeclast (%["#sched"]), %%xmm0 \n" - + void ECBDecryptionAESNI::Decrypt (const ChipherBlock * in, ChipherBlock * out) { __asm__ ( "movups (%[in]), %%xmm0 \n" DecryptAES256(sched) - "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[out]) \n" : : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory" - ); + ); } #define CallAESIMC(offset) \ "movaps "#offset"(%[shed]), %%xmm0 \n" \ "aesimc %%xmm0, %%xmm0 \n" \ - "movaps %%xmm0, "#offset"(%[shed]) \n" + "movaps %%xmm0, "#offset"(%[shed]) \n" void ECBDecryptionAESNI::SetKey (const AESKey& key) { @@ -690,7 +690,7 @@ namespace crypto ); } -#endif +#endif void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out) @@ -698,31 +698,31 @@ namespace crypto #ifdef AESNI __asm__ ( - "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + "movups (%[iv]), %%xmm1 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) : "%xmm0", "%xmm1", "cc", "memory" - ); -#else + ); +#else for (int i = 0; i < numBlocks; i++) { *m_LastBlock.GetChipherBlock () ^= in[i]; m_ECBEncryption.Encrypt (m_LastBlock.GetChipherBlock (), m_LastBlock.GetChipherBlock ()); out[i] = *m_LastBlock.GetChipherBlock (); } -#endif +#endif } void CBCEncryption::Encrypt (const uint8_t * in, std::size_t len, uint8_t * out) @@ -730,7 +730,7 @@ namespace crypto // len/16 int numBlocks = len >> 4; if (numBlocks > 0) - Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out); + Encrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out); } void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out) @@ -740,17 +740,17 @@ namespace crypto ( "movups (%[iv]), %%xmm1 \n" "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched) + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched) "movups %%xmm0, (%[out]) \n" "movups %%xmm0, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), + : + : [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory" - ); + ); #else - Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); + Encrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); #endif } @@ -760,23 +760,23 @@ namespace crypto __asm__ ( "movups (%[iv]), %%xmm1 \n" - "1: \n" - "movups (%[in]), %%xmm0 \n" + "1: \n" + "movups (%[in]), %%xmm0 \n" "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched) + DecryptAES256(sched) "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[out]) \n" "movaps %%xmm2, %%xmm1 \n" - "add $16, %[in] \n" - "add $16, %[out] \n" - "dec %[num] \n" - "jnz 1b \n" - "movups %%xmm1, (%[iv]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + "add $16, %[in] \n" + "add $16, %[out] \n" + "dec %[num] \n" + "jnz 1b \n" + "movups %%xmm1, (%[iv]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(numBlocks) : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" - ); + ); #else for (int i = 0; i < numBlocks; i++) { @@ -792,7 +792,7 @@ namespace crypto { int numBlocks = len >> 4; if (numBlocks > 0) - Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out); + Decrypt (numBlocks, (const ChipherBlock *)in, (ChipherBlock *)out); } void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out) @@ -801,18 +801,18 @@ namespace crypto __asm__ ( "movups (%[iv]), %%xmm1 \n" - "movups (%[in]), %%xmm0 \n" + "movups (%[in]), %%xmm0 \n" "movups %%xmm0, (%[iv]) \n" - DecryptAES256(sched) + DecryptAES256(sched) "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" - : - : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), + "movups %%xmm0, (%[out]) \n" + : + : [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "%xmm1", "memory" ); #else - Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); + Decrypt (1, (const ChipherBlock *)in, (ChipherBlock *)out); #endif } @@ -821,7 +821,7 @@ namespace crypto #ifdef AESNI __asm__ ( - // encrypt IV + // encrypt IV "movups (%[in]), %%xmm0 \n" EncryptAES256(sched_iv) "movaps %%xmm0, %%xmm1 \n" @@ -831,16 +831,16 @@ namespace crypto // encrypt data, IV is xmm1 "1: \n" "add $16, %[in] \n" - "add $16, %[out] \n" - "movups (%[in]), %%xmm0 \n" - "pxor %%xmm1, %%xmm0 \n" - EncryptAES256(sched_l) - "movaps %%xmm0, %%xmm1 \n" - "movups %%xmm0, (%[out]) \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()), + "add $16, %[out] \n" + "movups (%[in]), %%xmm0 \n" + "pxor %%xmm1, %%xmm0 \n" + EncryptAES256(sched_l) + "movaps %%xmm0, %%xmm1 \n" + "movups %%xmm0, (%[out]) \n" + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.GetKeySchedule ()), [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes : "%xmm0", "%xmm1", "cc", "memory" ); @@ -857,7 +857,7 @@ namespace crypto #ifdef AESNI __asm__ ( - // decrypt IV + // decrypt IV "movups (%[in]), %%xmm0 \n" DecryptAES256(sched_iv) "movaps %%xmm0, %%xmm1 \n" @@ -867,27 +867,27 @@ namespace crypto // decrypt data, IV is xmm1 "1: \n" "add $16, %[in] \n" - "add $16, %[out] \n" + "add $16, %[out] \n" "movups (%[in]), %%xmm0 \n" "movaps %%xmm0, %%xmm2 \n" - DecryptAES256(sched_l) + DecryptAES256(sched_l) "pxor %%xmm1, %%xmm0 \n" - "movups %%xmm0, (%[out]) \n" + "movups %%xmm0, (%[out]) \n" "movaps %%xmm2, %%xmm1 \n" - "dec %[num] \n" - "jnz 1b \n" - : - : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()), - [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes + "dec %[num] \n" + "jnz 1b \n" + : + : [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.GetKeySchedule ()), + [in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes : "%xmm0", "%xmm1", "%xmm2", "cc", "memory" ); #else m_IVDecryption.Decrypt ((const ChipherBlock *)in, (ChipherBlock *)out); // iv - m_LayerDecryption.SetIV (out); + m_LayerDecryption.SetIV (out); m_LayerDecryption.Decrypt (in + 16, i2p::tunnel::TUNNEL_DATA_ENCRYPTED_SIZE, out + 16); // data m_IVDecryption.Decrypt ((ChipherBlock *)out, (ChipherBlock *)out); // double iv #endif - } + } /* std::vector > m_OpenSSLMutexes; static void OpensslLockingCallback(int mode, int type, const char * file, int line) @@ -898,45 +898,44 @@ namespace crypto m_OpenSSLMutexes[type]->lock (); else m_OpenSSLMutexes[type]->unlock (); - } + } }*/ - + void InitCrypto (bool precomputation) { SSL_library_init (); /* auto numLocks = CRYPTO_num_locks(); for (int i = 0; i < numLocks; i++) - m_OpenSSLMutexes.emplace_back (new std::mutex); + m_OpenSSLMutexes.emplace_back (new std::mutex); CRYPTO_set_locking_callback (OpensslLockingCallback);*/ if (precomputation) - { + { #if defined(__x86_64__) g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES); -#else +#else g_ElggTable = new BIGNUM * [ELGAMAL_SHORT_EXPONENT_NUM_BYTES][255]; PrecalculateElggTable (g_ElggTable, ELGAMAL_SHORT_EXPONENT_NUM_BYTES); -#endif - } +#endif + } } - + void TerminateCrypto () { if (g_ElggTable) - { + { DestroyElggTable (g_ElggTable, -#if defined(__x86_64__) +#if defined(__x86_64__) ELGAMAL_FULL_EXPONENT_NUM_BYTES #else - ELGAMAL_SHORT_EXPONENT_NUM_BYTES -#endif - ); + ELGAMAL_SHORT_EXPONENT_NUM_BYTES +#endif + ); delete[] g_ElggTable; g_ElggTable = nullptr; - } + } /* CRYPTO_set_locking_callback (nullptr); m_OpenSSLMutexes.clear ();*/ - } + } } } - diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f57de0c3..4b6e8bc8 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -483,9 +483,22 @@ namespace client { if (m_PublishReplyToken) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); m_PublishReplyToken = 0; - Publish (); + if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) + { + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + Publish (); + } + else + { + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ()); + // Java floodfill never sends confirmantion back for unknown crypto type + // assume it successive and try to verify + m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); + m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, + shared_from_this (), std::placeholders::_1)); + + } } } } @@ -702,8 +715,8 @@ namespace client } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): - LeaseSetDestination (isPublic, params), - m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0), + LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), + m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { if (isPublic) @@ -714,6 +727,14 @@ namespace client m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); + + // extract streaming params + if (params) + { + auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY); + if (it != params->end ()) + m_StreamingAckDelay = std::stoi(it->second); + } } ClientDestination::~ClientDestination () diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 3b87d1d0..d11b10dd 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -58,6 +58,10 @@ namespace client const char I2CP_PARAM_MAX_TUNNEL_LATENCY[] = "latency.max"; const int DEFAULT_MAX_TUNNEL_LATENCY = 0; + // streaming + const char I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY[] = "i2p.streaming.initialAckDelay"; + const int DEFAULT_INITIAL_ACK_DELAY = 200; // milliseconds + typedef std::function stream)> StreamRequestComplete; class LeaseSetDestination: public i2p::garlic::GarlicDestination, @@ -199,6 +203,7 @@ namespace client void StopAcceptingStreams (); bool IsAcceptingStreams () const; void AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor); + int GetStreamingAckDelay () const { return m_StreamingAckDelay; } // datagram i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; }; @@ -230,6 +235,7 @@ namespace client uint8_t m_EncryptionPublicKey[256], m_EncryptionPrivateKey[256]; std::shared_ptr m_Decryptor; + int m_StreamingAckDelay; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; i2p::datagram::DatagramDestination * m_DatagramDestination; diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 6d207dd5..23f32bc8 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -324,6 +324,12 @@ namespace data return SIGNING_KEY_TYPE_DSA_SHA1; } + bool IdentityEx::IsRSA () const + { + auto sigType = GetSigningKeyType (); + return sigType <= SIGNING_KEY_TYPE_RSA_SHA512_4096 && sigType >= SIGNING_KEY_TYPE_RSA_SHA256_2048; + } + CryptoKeyType IdentityEx::GetCryptoKeyType () const { if (m_StandardIdentity.certificate[0] == CERTIFICATE_TYPE_KEY && m_ExtendedLen >= 4) @@ -451,6 +457,7 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: + case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: @@ -602,6 +609,7 @@ namespace data return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: + case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: return std::make_shared(key); break; case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: @@ -632,14 +640,10 @@ namespace data i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); break; case SIGNING_KEY_TYPE_RSA_SHA256_2048: - i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA2562048_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); - break; case SIGNING_KEY_TYPE_RSA_SHA384_3072: - i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA3843072_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); - break; case SIGNING_KEY_TYPE_RSA_SHA512_4096: - i2p::crypto::CreateRSARandomKeys (i2p::crypto::RSASHA5124096_KEY_LENGTH, keys.m_SigningPrivateKey, signingPublicKey); - break; + LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA"); + // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); break; @@ -650,7 +654,7 @@ namespace data i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, keys.m_SigningPrivateKey, signingPublicKey); break; default: - LogPrint (eLogError, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); + LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1"); return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1 } // encryption @@ -673,6 +677,7 @@ namespace data i2p::crypto::GenerateElGamalKeyPair(priv, pub); break; case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC: + case CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST: i2p::crypto::CreateECIESP256RandomKeys (priv, pub); break; case CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC: diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index b0c6f48a..53ab4a7c 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -53,7 +53,8 @@ namespace data const size_t DEFAULT_IDENTITY_SIZE = sizeof (Identity); // 387 bytes const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0; - const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 65280; // TODO: change to actual code + const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1; + const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later const uint16_t CRYPTO_KEY_TYPE_ECIES_GOSTR3410_CRYPTO_PRO_A_SHA256_AES256CBC = 65281; // TODO: use GOST R 34.11 instead SHA256 and GOST 28147-89 instead AES const uint16_t SIGNING_KEY_TYPE_DSA_SHA1 = 0; @@ -102,6 +103,7 @@ namespace data size_t GetSignatureLen () const; bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const; SigningKeyType GetSigningKeyType () const; + bool IsRSA () const; // signing key type CryptoKeyType GetCryptoKeyType () const; void DropVerifier () const; // to save memory diff --git a/libi2pd/Log.cpp b/libi2pd/Log.cpp index 8ae417c2..b664a5d9 100644 --- a/libi2pd/Log.cpp +++ b/libi2pd/Log.cpp @@ -16,10 +16,11 @@ namespace log { */ static const char * g_LogLevelStr[eNumLogLevels] = { + "none", // eLogNone "error", // eLogError "warn", // eLogWarn "info", // eLogInfo - "debug" // eLogDebug + "debug" // eLogDebug }; /** @@ -27,9 +28,10 @@ namespace log { * @note Using ISO 6429 (ANSI) color sequences */ #ifdef _WIN32 - static const char *LogMsgColors[] = { "", "", "", "", "" }; + static const char *LogMsgColors[] = { "", "", "", "", "", "" }; #else /* UNIX */ static const char *LogMsgColors[] = { + [eLogNone] = "\033[0m", /* reset */ [eLogError] = "\033[1;31m", /* red */ [eLogWarning] = "\033[1;33m", /* yellow */ [eLogInfo] = "\033[1;36m", /* cyan */ @@ -46,6 +48,7 @@ namespace log { static inline int GetSyslogPrio (enum LogLevel l) { int priority = LOG_DEBUG; switch (l) { + case eLogNone : priority = LOG_CRIT; break; case eLogError : priority = LOG_ERR; break; case eLogWarning : priority = LOG_WARNING; break; case eLogInfo : priority = LOG_INFO; break; @@ -71,15 +74,15 @@ namespace log { void Log::Start () { if (!m_IsRunning) - { - m_IsRunning = true; + { + m_IsRunning = true; m_Thread = new std::thread (std::bind (&Log::Run, this)); } } - void Log::Stop () + void Log::Stop () { - switch (m_Destination) + switch (m_Destination) { #ifndef _WIN32 case eLogSyslog : @@ -97,15 +100,16 @@ namespace log { m_IsRunning = false; m_Queue.WakeUp (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; - } + } } void Log::SetLogLevel (const std::string& level) { - if (level == "error") { m_MinLevel = eLogError; } + if (level == "none") { m_MinLevel = eLogNone; } + else if (level == "error") { m_MinLevel = eLogError; } else if (level == "warn") { m_MinLevel = eLogWarning; } else if (level == "info") { m_MinLevel = eLogInfo; } else if (level == "debug") { m_MinLevel = eLogDebug; } @@ -115,7 +119,7 @@ namespace log { } LogPrint(eLogInfo, "Log: min messages level set to ", level); } - + const char * Log::TimeAsString(std::time_t t) { if (t != m_LastTimestamp) { strftime(m_LastDateTime, sizeof(m_LastDateTime), m_TimeFormat.c_str(), localtime(&t)); @@ -129,7 +133,7 @@ namespace log { * Unfortunately, with current startup process with late fork() this * will give us nothing but pain. Maybe later. See in NetDb as example. */ - void Log::Process(std::shared_ptr msg) + void Log::Process(std::shared_ptr msg) { if (!msg) return; std::hash hasher; @@ -165,25 +169,26 @@ namespace log { while (m_IsRunning) { std::shared_ptr msg; - while (msg = m_Queue.Get ()) + while ((msg = m_Queue.Get ())) Process (msg); if (m_LogStream) m_LogStream->flush(); if (m_IsRunning) m_Queue.Wait (); } - } + } - void Log::Append(std::shared_ptr & msg) + void Log::Append(std::shared_ptr & msg) { m_Queue.Put(msg); } - void Log::SendTo (const std::string& path) + void Log::SendTo (const std::string& path) { - if (m_LogStream) m_LogStream = nullptr; // close previous + if (m_LogStream) m_LogStream = nullptr; // close previous + if (m_MinLevel == eLogNone) return; auto flags = std::ofstream::out | std::ofstream::app; auto os = std::make_shared (path, flags); - if (os->is_open ()) + if (os->is_open ()) { m_HasColors = false; m_Logfile = path; @@ -202,6 +207,7 @@ namespace log { #ifndef _WIN32 void Log::SendTo(const char *name, int facility) { + if (m_MinLevel == eLogNone) return; m_HasColors = false; m_Destination = eLogSyslog; m_LogStream = nullptr; diff --git a/libi2pd/Log.h b/libi2pd/Log.h index bec741a8..74b4dc01 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -25,10 +25,11 @@ enum LogLevel { - eLogError = 0, + eLogNone = 0, + eLogError, eLogWarning, eLogInfo, - eLogDebug, + eLogDebug, eNumLogLevels }; diff --git a/libi2pd/NTCPSession.cpp b/libi2pd/NTCPSession.cpp index 27f30600..a340089c 100644 --- a/libi2pd/NTCPSession.cpp +++ b/libi2pd/NTCPSession.cpp @@ -1247,7 +1247,7 @@ namespace transport return; } buff[4] = (uint8_t) addrsize; - memcpy(buff+4, host.c_str(), addrsize); + memcpy(buff+5, host.c_str(), addrsize); } htobe16buf(buff+sz, port); sz += 2; @@ -1259,7 +1259,7 @@ namespace transport } }); - boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, sz), [=](const boost::system::error_code & e, std::size_t transferred) { + boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff, 10), [=](const boost::system::error_code & e, std::size_t transferred) { if(e) { LogPrint(eLogError, "NTCP: socks proxy read error ", e.message()); diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index f35425da..21fa790e 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -489,6 +489,27 @@ namespace data std::string Reseeder::HttpsRequest (const std::string& address) { + i2p::http::URL proxyUrl; + std::string proxy; i2p::config::GetOption("reseed.proxy", proxy); + // check for proxy url + if(proxy.size()) { + // parse + if(proxyUrl.parse(proxy)) { + if (proxyUrl.schema == "http" && !proxyUrl.port) { + proxyUrl.port = 80; + } else if (proxyUrl.schema == "socks" && !proxyUrl.port) { + proxyUrl.port = 1080; + } + // check for valid proxy url schema + if (proxyUrl.schema != "http" && proxyUrl.schema != "socks") { + LogPrint(eLogError, "Reseed: bad proxy url: ", proxy); + return ""; + } + } else { + LogPrint(eLogError, "Reseed: bad proxy url: ", proxy); + return ""; + } + } i2p::http::URL url; if (!url.parse(address)) { LogPrint(eLogError, "Reseed: failed to parse url: ", address); @@ -500,68 +521,185 @@ namespace data boost::asio::io_service service; boost::system::error_code ecode; - auto it = boost::asio::ip::tcp::resolver(service).resolve ( - boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode); - if (!ecode) + + boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23); + ctx.set_verify_mode(boost::asio::ssl::context::verify_none); + boost::asio::ssl::stream s(service, ctx); + + if(proxyUrl.schema.size()) { - boost::asio::ssl::context ctx(service, boost::asio::ssl::context::sslv23); - ctx.set_verify_mode(boost::asio::ssl::context::verify_none); - boost::asio::ssl::stream s(service, ctx); - s.lowest_layer().connect (*it, ecode); - if (!ecode) + // proxy connection + auto it = boost::asio::ip::tcp::resolver(service).resolve ( + boost::asio::ip::tcp::resolver::query (proxyUrl.host, std::to_string(proxyUrl.port)), ecode); + if(!ecode) { - SSL_set_tlsext_host_name(s.native_handle(), url.host.c_str ()); - s.handshake (boost::asio::ssl::stream_base::client, ecode); - if (!ecode) + s.lowest_layer().connect(*it, ecode); + if(!ecode) { - LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port); - i2p::http::HTTPReq req; - req.uri = url.to_string(); - req.AddHeader("User-Agent", "Wget/1.11.4"); - req.AddHeader("Connection", "close"); - s.write_some (boost::asio::buffer (req.to_string())); - // read response - std::stringstream rs; - char recv_buf[1024]; size_t l = 0; - do { - l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode); - if (l) rs.write (recv_buf, l); - } while (!ecode && l); - // process response - std::string data = rs.str(); - i2p::http::HTTPRes res; - int len = res.parse(data); - if (len <= 0) { - LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host); - return ""; - } - if (res.code != 200) { - LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code); - return ""; + auto & sock = s.next_layer(); + if(proxyUrl.schema == "http") + { + i2p::http::HTTPReq proxyReq; + i2p::http::HTTPRes proxyRes; + proxyReq.method = "CONNECT"; + proxyReq.version = "HTTP/1.1"; + proxyReq.uri = url.host + ":" + std::to_string(url.port); + + boost::asio::streambuf writebuf, readbuf; + + std::ostream out(&writebuf); + out << proxyReq.to_string(); + + boost::asio::write(sock, writebuf.data(), boost::asio::transfer_all(), ecode); + if (ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: HTTP CONNECT write error: ", ecode.message()); + return ""; + } + boost::asio::read_until(sock, readbuf, "\r\n\r\n", ecode); + if (ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: HTTP CONNECT read error: ", ecode.message()); + return ""; + } + if(proxyRes.parse(boost::asio::buffer_cast(readbuf.data()), readbuf.size()) <= 0) + { + sock.close(); + LogPrint(eLogError, "Reseed: HTTP CONNECT malformed reply"); + return ""; + } + if(proxyRes.code != 200) + { + sock.close(); + LogPrint(eLogError, "Reseed: HTTP CONNECT got bad status: ", proxyRes.code); + return ""; + } } - data.erase(0, len); /* drop http headers from response */ - LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host); - if (res.is_chunked()) { - std::stringstream in(data), out; - if (!i2p::http::MergeChunkedResponse(in, out)) { - LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host); + else + { + // assume socks if not http, is checked before this for other types + // TODO: support username/password auth etc + uint8_t hs_writebuf[3] = {0x05, 0x01, 0x00}; + uint8_t hs_readbuf[2]; + boost::asio::write(sock, boost::asio::buffer(hs_writebuf, 3), boost::asio::transfer_all(), ecode); + if(ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake write failed: ", ecode.message()); + return ""; + } + boost::asio::read(sock, boost::asio::buffer(hs_readbuf, 2), ecode); + if(ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake read failed: ", ecode.message()); + return ""; + } + size_t sz = 0; + uint8_t buf[256]; + + buf[0] = 0x05; + buf[1] = 0x01; + buf[2] = 0x00; + buf[3] = 0x03; + sz += 4; + size_t hostsz = url.host.size(); + if(1 + 2 + hostsz + sz > sizeof(buf)) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake failed, hostname too big: ", url.host); + return ""; + } + buf[4] = (uint8_t) hostsz; + memcpy(buf+5, url.host.c_str(), hostsz); + sz += hostsz + 1; + htobe16buf(buf+sz, url.port); + sz += 2; + boost::asio::write(sock, boost::asio::buffer(buf, sz), boost::asio::transfer_all(), ecode); + if(ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake failed writing: ", ecode.message()); + return ""; + } + boost::asio::read(sock, boost::asio::buffer(buf, 10), ecode); + if(ecode) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake failed reading: ", ecode.message()); + return ""; + } + if(buf[1] != 0x00) + { + sock.close(); + LogPrint(eLogError, "Reseed: SOCKS handshake bad reply code: ", std::to_string(buf[1])); return ""; } - LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host); - data = out.str(); } - return data; } - else - LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ()); + } + } + else + { + // direct connection + auto it = boost::asio::ip::tcp::resolver(service).resolve ( + boost::asio::ip::tcp::resolver::query (url.host, std::to_string(url.port)), ecode); + if(!ecode) + s.lowest_layer().connect (*it, ecode); + } + if (!ecode) + { + SSL_set_tlsext_host_name(s.native_handle(), url.host.c_str ()); + s.handshake (boost::asio::ssl::stream_base::client, ecode); + if (!ecode) + { + LogPrint (eLogDebug, "Reseed: Connected to ", url.host, ":", url.port); + i2p::http::HTTPReq req; + req.uri = url.to_string(); + req.AddHeader("User-Agent", "Wget/1.11.4"); + req.AddHeader("Connection", "close"); + s.write_some (boost::asio::buffer (req.to_string())); + // read response + std::stringstream rs; + char recv_buf[1024]; size_t l = 0; + do { + l = s.read_some (boost::asio::buffer (recv_buf, sizeof(recv_buf)), ecode); + if (l) rs.write (recv_buf, l); + } while (!ecode && l); + // process response + std::string data = rs.str(); + i2p::http::HTTPRes res; + int len = res.parse(data); + if (len <= 0) { + LogPrint(eLogWarning, "Reseed: incomplete/broken response from ", url.host); + return ""; + } + if (res.code != 200) { + LogPrint(eLogError, "Reseed: failed to reseed from ", url.host, ", http code ", res.code); + return ""; + } + data.erase(0, len); /* drop http headers from response */ + LogPrint(eLogDebug, "Reseed: got ", data.length(), " bytes of data from ", url.host); + if (res.is_chunked()) { + std::stringstream in(data), out; + if (!i2p::http::MergeChunkedResponse(in, out)) { + LogPrint(eLogWarning, "Reseed: failed to merge chunked response from ", url.host); + return ""; + } + LogPrint(eLogDebug, "Reseed: got ", data.length(), "(", out.tellg(), ") bytes of data from ", url.host); + data = out.str(); + } + return data; } else - LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ()); + LogPrint (eLogError, "Reseed: SSL handshake failed: ", ecode.message ()); } else - LogPrint (eLogError, "Reseed: Couldn't resolve address ", url.host, ": ", ecode.message ()); + LogPrint (eLogError, "Reseed: Couldn't connect to ", url.host, ": ", ecode.message ()); return ""; - } + } } } diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index f0ad1b88..642373f2 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -132,6 +132,13 @@ namespace data } if (verifySignature) { + // reject RSA signatures + if (m_RouterIdentity->IsRSA ()) + { + LogPrint (eLogError, "RouterInfo: RSA signature type is not allowed"); + m_IsUnreachable = true; + return; + } // verify signature int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index a1cf536e..b0a08a4d 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -62,6 +62,7 @@ namespace stream m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port), m_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), + m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); @@ -73,7 +74,8 @@ namespace stream m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE), - m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) + m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()), + m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0) { RAND_bytes ((uint8_t *)&m_RecvStreamID, 4); } @@ -161,7 +163,7 @@ namespace stream { m_IsAckSendScheduled = true; auto ackTimeout = m_RTT/10; - if (ackTimeout > ACK_SEND_TIMEOUT) ackTimeout = ACK_SEND_TIMEOUT; + if (ackTimeout > m_AckDelay) ackTimeout = m_AckDelay; m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); @@ -199,7 +201,7 @@ namespace stream { // wait for SYN m_IsAckSendScheduled = true; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ACK_SEND_TIMEOUT)); + m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(SYN_TIMEOUT)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); } @@ -228,6 +230,13 @@ namespace stream if (flags & PACKET_FLAG_FROM_INCLUDED) { m_RemoteIdentity = std::make_shared(optionData, packet->GetOptionSize ()); + if (m_RemoteIdentity->IsRSA ()) + { + LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded"); + m_LocalDestination.DeletePacket (packet); + Terminate (); + return; + } optionData += m_RemoteIdentity->GetFullLen (); if (!m_RemoteLeaseSet) LogPrint (eLogDebug, "Streaming: Incoming stream from ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), ", sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); @@ -244,16 +253,23 @@ namespace stream { uint8_t signature[256]; auto signatureLen = m_RemoteIdentity->GetSignatureLen (); - memcpy (signature, optionData, signatureLen); - memset (const_cast(optionData), 0, signatureLen); - if (!m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature)) + if(signatureLen <= sizeof(signature)) { - LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); - Close (); - flags |= PACKET_FLAG_CLOSE; + memcpy (signature, optionData, signatureLen); + memset (const_cast(optionData), 0, signatureLen); + if (!m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature)) + { + LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); + Close (); + flags |= PACKET_FLAG_CLOSE; + } + memcpy (const_cast(optionData), signature, signatureLen); + optionData += signatureLen; + } + else + { + LogPrint(eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); } - memcpy (const_cast(optionData), signature, signatureLen); - optionData += signatureLen; } packet->offset = packet->GetPayload () - packet->buf; @@ -798,7 +814,7 @@ namespace stream { if (m_LastReceivedSequenceNumber < 0) { - LogPrint (eLogWarning, "Streaming: SYN has not been received after ", ACK_SEND_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); + LogPrint (eLogWarning, "Streaming: SYN has not been received after ", SYN_TIMEOUT, " milliseconds after follow on, terminate rSID=", m_RecvStreamID, ", sSID=", m_SendStreamID); m_Status = eStreamStatusReset; Close (); return; diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 94b356e8..025ceb63 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -42,13 +42,13 @@ namespace stream const size_t STREAMING_MTU = 1730; const size_t MAX_PACKET_SIZE = 4096; const size_t COMPRESSION_THRESHOLD_SIZE = 66; - const int ACK_SEND_TIMEOUT = 200; // in milliseconds const int MAX_NUM_RESEND_ATTEMPTS = 6; const int WINDOW_SIZE = 6; // in messages const int MIN_WINDOW_SIZE = 1; const int MAX_WINDOW_SIZE = 128; const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds + const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds const int MAX_RECEIVE_TIMEOUT = 30; // in seconds @@ -242,7 +242,7 @@ namespace stream std::mutex m_SendBufferMutex; SendBufferQueue m_SendBuffer; - int m_WindowSize, m_RTT, m_RTO; + int m_WindowSize, m_RTT, m_RTO, m_AckDelay; uint64_t m_LastWindowSizeIncreaseTime; int m_NumResendAttempts; }; diff --git a/libi2pd/version.h b/libi2pd/version.h index 4633ce0b..ba7a27b8 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 15 +#define I2PD_VERSION_MINOR 16 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index b7363b00..f823a92b 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -71,12 +71,12 @@ namespace client } try { - m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); - m_HttpProxy->Start(); + m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); + m_HttpProxy->Start(); } catch (std::exception& e) { - LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); + LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); } } @@ -107,7 +107,8 @@ namespace client } try { - m_SocksProxy = new i2p::proxy::SOCKSProxy(socksProxyAddr, socksProxyPort, socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); + m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, + socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); m_SocksProxy->Start(); } catch (std::exception& e) @@ -283,6 +284,13 @@ namespace client bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType) { + if (filename == "transient") + { + keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType); + LogPrint (eLogInfo, "Clients: New transient keys address ", m_AddressBook.ToAddress(keys.GetPublic ()->GetIdentHash ()), " created"); + return true; + } + bool success = true; std::string fullPath = i2p::fs::DataDirPath (filename); std::ifstream s(fullPath, std::ifstream::binary); @@ -341,10 +349,11 @@ namespace client return infos; } - std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, i2p::data::SigningKeyType sigType, - const std::map * params) + std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, + i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType, + const std::map * params) { - i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType); + i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType); auto localDestination = std::make_shared (keys, isPublic, params); std::unique_lock l(m_DestinationsMutex); m_Destinations[localDestination->GetIdentHash ()] = localDestination; @@ -422,6 +431,7 @@ namespace client options[I2CP_PARAM_TAGS_TO_SEND] = GetI2CPOption (section, I2CP_PARAM_TAGS_TO_SEND, DEFAULT_TAGS_TO_SEND); options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MIN_TUNNEL_LATENCY, DEFAULT_MIN_TUNNEL_LATENCY); options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = GetI2CPOption(section, I2CP_PARAM_MAX_TUNNEL_LATENCY, DEFAULT_MAX_TUNNEL_LATENCY); + options[I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY] = GetI2CPOption(section, I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY, DEFAULT_INITIAL_ACK_DELAY); } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const @@ -438,7 +448,7 @@ namespace client if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; + options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; } void ClientContext::ReadTunnels () @@ -533,14 +543,14 @@ namespace client if (type == I2P_TUNNELS_SECTION_TYPE_SOCKS) { // socks proxy - clientTunnel = new i2p::proxy::SOCKSProxy(address, port, false, "", destinationPort, localDestination); + clientTunnel = new i2p::proxy::SOCKSProxy(name, address, port, false, "", destinationPort, localDestination); clientEndpoint = ((i2p::proxy::SOCKSProxy*)clientTunnel)->GetLocalEndpoint (); } else if (type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY) { // http proxy std::string outproxy = section.second.get("outproxy", ""); - clientTunnel = new i2p::proxy::HTTPProxy(address, port, outproxy, localDestination); + clientTunnel = new i2p::proxy::HTTPProxy(name, address, port, outproxy, localDestination); clientEndpoint = ((i2p::proxy::HTTPProxy*)clientTunnel)->GetLocalEndpoint (); } else if (type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS) diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index afb3d4d5..9b65ef32 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -64,10 +64,12 @@ namespace client void ReloadConfig (); std::shared_ptr GetSharedLocalDestination () const { return m_SharedLocalDestination; }; - std::shared_ptr CreateNewLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1, - const std::map * params = nullptr); // transient + std::shared_ptr CreateNewLocalDestination (bool isPublic = false, // transient + i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1, + i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL, + const std::map * params = nullptr); // used by SAM only std::shared_ptr CreateNewLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); + const std::map * params = nullptr); std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; @@ -76,6 +78,7 @@ namespace client i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); AddressBook& GetAddressBook () { return m_AddressBook; }; + const BOBCommandChannel * GetBOBCommandChannel () const { return m_BOBCommandChannel; }; const SAMBridge * GetSAMBridge () const { return m_SamBridge; }; const I2CPServer * GetI2CPServer () const { return m_I2CPServer; }; @@ -87,8 +90,8 @@ namespace client template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template - void ReadI2CPOptions (const Section& section, std::map& options) const; - void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; + void ReadI2CPOptions (const Section& section, std::map& options) const; // for tunnels + void ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const; // for HTTP and SOCKS proxy void CleanupUDP(const boost::system::error_code & ecode); void ScheduleCleanupUDP(); diff --git a/libi2pd_client/HTTPProxy.cpp b/libi2pd_client/HTTPProxy.cpp index b1e1a545..ac5d907d 100644 --- a/libi2pd_client/HTTPProxy.cpp +++ b/libi2pd_client/HTTPProxy.cpp @@ -54,7 +54,7 @@ namespace proxy { void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void Terminate(); void AsyncSockRead(); - bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64); + bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm); void SanitizeHTTPRequest(i2p::http::HTTPReq & req); void SentHTTPFailed(const boost::system::error_code & ecode); void HandleStreamRequestComplete (std::shared_ptr stream); @@ -182,13 +182,15 @@ namespace proxy { std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); } - bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64) + bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) { + confirm = false; const char *param = "i2paddresshelper="; std::size_t pos = url.query.find(param); std::size_t len = std::strlen(param); std::map params; + if (pos == std::string::npos) return false; /* not found */ if (!url.parse_query(params)) @@ -197,6 +199,8 @@ namespace proxy { std::string value = params["i2paddresshelper"]; len += value.length(); b64 = i2p::http::UrlDecode(value); + // if we need update exists, request formed with update param + if (params["update"] == "true") { len += std::strlen("&update=true"); confirm = true; } url.query.replace(pos, len, ""); return true; } @@ -242,24 +246,36 @@ namespace proxy { /* parsing success, now let's look inside request */ LogPrint(eLogDebug, "HTTPProxy: requested: ", m_ClientRequest.uri); m_RequestURL.parse(m_ClientRequest.uri); + bool m_Confirm; - if (ExtractAddressHelper(m_RequestURL, b64)) + if (ExtractAddressHelper(m_RequestURL, b64, m_Confirm)) { bool addresshelper; i2p::config::GetOption("httpproxy.addresshelper", addresshelper); if (!addresshelper) { - LogPrint(eLogWarning, "HTTPProxy: addresshelper disabled"); - GenericProxyError("Invalid request", "adddresshelper is not supported"); + LogPrint(eLogWarning, "HTTPProxy: addresshelper request rejected"); + GenericProxyError("Invalid request", "addresshelper is not supported"); return true; } - i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, b64); - LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", m_RequestURL.host); - std::string full_url = m_RequestURL.to_string(); - std::stringstream ss; - ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. " - << "Click here to proceed."; - GenericProxyInfo("Addresshelper found", ss.str().c_str()); - return true; /* request processed */ + if (!i2p::client::context.GetAddressBook ().FindAddress (m_RequestURL.host) || m_Confirm) + { + i2p::client::context.GetAddressBook ().InsertAddress (m_RequestURL.host, b64); + LogPrint (eLogInfo, "HTTPProxy: added b64 from addresshelper for ", m_RequestURL.host); + std::string full_url = m_RequestURL.to_string(); + std::stringstream ss; + ss << "Host " << m_RequestURL.host << " added to router's addressbook from helper. " + << "Click here to proceed."; + GenericProxyInfo("Addresshelper found", ss.str().c_str()); + return true; /* request processed */ + } + else + { + std::stringstream ss; + ss << "Host " << m_RequestURL.host << " already in router's addressbook. " + << "Click here to update record."; + GenericProxyInfo("Addresshelper found", ss.str().c_str()); + return true; /* request processed */ + } } std::string dest_host; uint16_t dest_port; @@ -570,7 +586,7 @@ namespace proxy { { if (!stream) { LogPrint (eLogError, "HTTPProxy: error when creating the stream, check the previous warnings for more info"); - GenericProxyError("Host is down", "Can't create connection to requested host, it may be down"); + GenericProxyError("Host is down", "Can't create connection to requested host, it may be down. Please try again later."); return; } if (Kill()) @@ -582,9 +598,9 @@ namespace proxy { Done (shared_from_this()); } - HTTPProxy::HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination): + HTTPProxy::HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination): TCPIPAcceptor(address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), - m_OutproxyUrl(outproxy) + m_Name (name), m_OutproxyUrl(outproxy) { } diff --git a/libi2pd_client/HTTPProxy.h b/libi2pd_client/HTTPProxy.h index 0adb2d2e..04a43914 100644 --- a/libi2pd_client/HTTPProxy.h +++ b/libi2pd_client/HTTPProxy.h @@ -6,9 +6,9 @@ namespace proxy { class HTTPProxy: public i2p::client::TCPIPAcceptor { public: - HTTPProxy(const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination); - HTTPProxy(const std::string& address, int port, std::shared_ptr localDestination = nullptr) : - HTTPProxy(address, port, "", localDestination) {} ; + HTTPProxy(const std::string& name, const std::string& address, int port, const std::string & outproxy, std::shared_ptr localDestination); + HTTPProxy(const std::string& name, const std::string& address, int port, std::shared_ptr localDestination = nullptr) : + HTTPProxy(name, address, port, "", localDestination) {} ; ~HTTPProxy() {}; std::string GetOutproxyURL() const { return m_OutproxyUrl; } @@ -16,9 +16,10 @@ namespace proxy { protected: // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); - const char* GetName() { return "HTTP Proxy"; } + const char* GetName() { return m_Name.c_str (); } private: + std::string m_Name; std::string m_OutproxyUrl; }; } // http diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 25aec108..140140fc 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -489,11 +489,15 @@ namespace client ExtractParams (buf, params); // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; + i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; auto it = params.find (SAM_PARAM_SIGNATURE_TYPE); if (it != params.end ()) // TODO: extract string values signatureType = std::stoi(it->second); - auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType); + it = params.find (SAM_PARAM_CRYPTO_TYPE); + if (it != params.end ()) + cryptoType = std::stoi(it->second); + auto keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); #ifdef _MSC_VER size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_DEST_REPLY, keys.GetPublic ()->ToBase64 ().c_str (), keys.ToBase64 ().c_str ()); @@ -911,14 +915,18 @@ namespace client { // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; + i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (params) { auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); if (it != params->end ()) // TODO: extract string values signatureType = std::stoi(it->second); + it = params->find (SAM_PARAM_CRYPTO_TYPE); + if (it != params->end ()) + cryptoType = std::stoi(it->second); } - localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, params); + localDestination = i2p::client::context.CreateNewLocalDestination (true, signatureType, cryptoType, params); } if (localDestination) { diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index 499f0da7..f2c84e3c 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -53,6 +53,7 @@ namespace client const char SAM_PARAM_DESTINATION[] = "DESTINATION"; const char SAM_PARAM_NAME[] = "NAME"; const char SAM_PARAM_SIGNATURE_TYPE[] = "SIGNATURE_TYPE"; + const char SAM_PARAM_CRYPTO_TYPE[] = "CRYPTO_TYPE"; const char SAM_PARAM_SIZE[] = "SIZE"; const char SAM_VALUE_TRANSIENT[] = "TRANSIENT"; const char SAM_VALUE_STREAM[] = "STREAM"; diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index c68a7e58..e63c369f 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -768,9 +768,10 @@ namespace proxy shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - SOCKSServer::SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, - std::shared_ptr localDestination) : - TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()) + SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, + bool outEnable, const std::string& outAddress, uint16_t outPort, + std::shared_ptr localDestination) : + TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) { m_UseUpstreamProxy = false; if (outAddress.length() > 0 && outEnable) diff --git a/libi2pd_client/SOCKS.h b/libi2pd_client/SOCKS.h index a61287f3..87f08de4 100644 --- a/libi2pd_client/SOCKS.h +++ b/libi2pd_client/SOCKS.h @@ -14,7 +14,7 @@ namespace proxy class SOCKSServer: public i2p::client::TCPIPAcceptor { public: - SOCKSServer(const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, + SOCKSServer(const std::string& name, const std::string& address, int port, bool outEnable, const std::string& outAddress, uint16_t outPort, std::shared_ptr localDestination = nullptr); ~SOCKSServer() {}; @@ -23,9 +23,11 @@ namespace proxy protected: // Implements TCPIPAcceptor std::shared_ptr CreateHandler(std::shared_ptr socket); - const char* GetName() { return "SOCKS"; } + const char* GetName() { return m_Name.c_str (); } private: + + std::string m_Name; std::string m_UpstreamProxyAddress; uint16_t m_UpstreamProxyPort; bool m_UseUpstreamProxy; diff --git a/qt/i2pd_qt/.gitignore b/qt/i2pd_qt/.gitignore index 3bbbf71a..3abca1bd 100644 --- a/qt/i2pd_qt/.gitignore +++ b/qt/i2pd_qt/.gitignore @@ -3,5 +3,7 @@ moc_* ui_* qrc_* i2pd_qt -Makefile +Makefile* *.stash +object_script.* +i2pd_qt_plugin_import.cpp \ No newline at end of file diff --git a/qt/i2pd_qt/SignatureTypeComboboxFactory.h b/qt/i2pd_qt/SignatureTypeComboboxFactory.h index 2380b67a..41245dac 100644 --- a/qt/i2pd_qt/SignatureTypeComboboxFactory.h +++ b/qt/i2pd_qt/SignatureTypeComboboxFactory.h @@ -70,13 +70,6 @@ public: addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_TC26_A_512_GOSTR3411_512", 0), SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512); //10 if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;} ++index; - // TODO: remove later - addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST", 0), SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST); //65281 - if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;} - ++index; - addItem(signatureTypeCombobox, QApplication::translate("signatureTypeCombobox", "GOSTR3410_TC26_A_512_GOSTR3411_512_TEST", 0), SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST); //65282 - if(selectedSigType==SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST){signatureTypeCombobox->setCurrentIndex(index);foundSelected=true;} - ++index; if(!foundSelected){ addItem(signatureTypeCombobox, QString::number(selectedSigType), selectedSigType); //unknown sigtype signatureTypeCombobox->setCurrentIndex(index); diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 1a38f109..a5fa7a52 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 93da099a..e9e95ce1 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -155,8 +155,9 @@ MainWindow::MainWindow(QWidget *parent) : uiSettings->logDestinationComboBox->clear(); uiSettings->logDestinationComboBox->insertItems(0, QStringList() - << QApplication::translate("MainWindow", "stdout", 0) - << QApplication::translate("MainWindow", "file", 0) + << QApplication::translate("MainWindow", "syslog", 0) + << QApplication::translate("MainWindow", "stdout", 0) + << QApplication::translate("MainWindow", "file", 0) ); initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox); @@ -302,9 +303,9 @@ MainWindow::MainWindow(QWidget *parent) : } void MainWindow::logDestinationComboBoxValueChanged(const QString & text) { - bool stdout = text==QString("stdout"); - uiSettings->logFileLineEdit->setEnabled(!stdout); - uiSettings->logFileBrowsePushButton->setEnabled(!stdout); + bool fileEnabled = text==QString("file"); + uiSettings->logFileLineEdit->setEnabled(fileEnabled); + uiSettings->logFileBrowsePushButton->setEnabled(fileEnabled); } diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 7e55a65f..cac97a1f 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -224,7 +224,6 @@ public: } virtual void saveToStringStream(std::stringstream& out){ std::string logDest = comboBox->currentText().toStdString(); - if(logDest==std::string("stdout"))logDest=""; optionValue=logDest; MainWindowItem::saveToStringStream(out); }