mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 13:27:17 +01:00
fix code syle(spaces->tabs, tabulations)
Signed-off-by: R4SAS <r4sas@i2pmail.org>
This commit is contained in:
parent
9633c247f0
commit
7a5146ea74
|
@ -27,8 +27,8 @@ namespace util
|
||||||
i2p::log::SetThrowFunction ([](const std::string& s)
|
i2p::log::SetThrowFunction ([](const std::string& s)
|
||||||
{
|
{
|
||||||
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
|
MessageBox(0, TEXT(s.c_str ()), TEXT("i2pd"), MB_ICONERROR | MB_TASKMODAL | MB_OK );
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -1,455 +1,455 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
#include "Win32App.h"
|
#include "Win32App.h"
|
||||||
#include "Win32NetState.h"
|
#include "Win32NetState.h"
|
||||||
|
|
||||||
#define ID_ABOUT 2000
|
#define ID_ABOUT 2000
|
||||||
#define ID_EXIT 2001
|
#define ID_EXIT 2001
|
||||||
#define ID_CONSOLE 2002
|
#define ID_CONSOLE 2002
|
||||||
#define ID_APP 2003
|
#define ID_APP 2003
|
||||||
#define ID_GRACEFUL_SHUTDOWN 2004
|
#define ID_GRACEFUL_SHUTDOWN 2004
|
||||||
#define ID_STOP_GRACEFUL_SHUTDOWN 2005
|
#define ID_STOP_GRACEFUL_SHUTDOWN 2005
|
||||||
#define ID_RELOAD 2006
|
#define ID_RELOAD 2006
|
||||||
#define ID_ACCEPT_TRANSIT 2007
|
#define ID_ACCEPT_TRANSIT 2007
|
||||||
#define ID_DECLINE_TRANSIT 2008
|
#define ID_DECLINE_TRANSIT 2008
|
||||||
|
|
||||||
#define ID_TRAY_ICON 2050
|
#define ID_TRAY_ICON 2050
|
||||||
#define WM_TRAYICON (WM_USER + 1)
|
#define WM_TRAYICON (WM_USER + 1)
|
||||||
|
|
||||||
#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100
|
#define IDT_GRACEFUL_SHUTDOWN_TIMER 2100
|
||||||
#define FRAME_UPDATE_TIMER 2101
|
#define FRAME_UPDATE_TIMER 2101
|
||||||
#define IDT_GRACEFUL_TUNNELCHECK_TIMER 2102
|
#define IDT_GRACEFUL_TUNNELCHECK_TIMER 2102
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace win32
|
namespace win32
|
||||||
{
|
{
|
||||||
static DWORD GracefulShutdownEndtime = 0;
|
static DWORD GracefulShutdownEndtime = 0;
|
||||||
|
|
||||||
typedef DWORD (* IPN)();
|
typedef DWORD (* IPN)();
|
||||||
IPN GetTickCountLocal = (IPN)GetProcAddress (GetModuleHandle ("KERNEL32.dll"), "GetTickCount");
|
IPN GetTickCountLocal = (IPN)GetProcAddress (GetModuleHandle ("KERNEL32.dll"), "GetTickCount");
|
||||||
|
|
||||||
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
|
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
|
||||||
{
|
{
|
||||||
HMENU hPopup = CreatePopupMenu();
|
HMENU hPopup = CreatePopupMenu();
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
||||||
if(!i2p::context.AcceptsTunnels())
|
if(!i2p::context.AcceptsTunnels())
|
||||||
InsertMenu (hPopup, -1,
|
InsertMenu (hPopup, -1,
|
||||||
i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING,
|
i2p::util::DaemonWin32::Instance ().isGraceful ? MF_BYPOSITION | MF_STRING | MF_GRAYED : MF_BYPOSITION | MF_STRING,
|
||||||
ID_ACCEPT_TRANSIT, "Accept &transit");
|
ID_ACCEPT_TRANSIT, "Accept &transit");
|
||||||
else
|
else
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DECLINE_TRANSIT, "Decline &transit");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_RELOAD, "&Reload tunnels config");
|
||||||
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
|
if (!i2p::util::DaemonWin32::Instance ().isGraceful)
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_GRACEFUL_SHUTDOWN, "&Graceful shutdown");
|
||||||
else
|
else
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_STOP_GRACEFUL_SHUTDOWN, "Stop &graceful shutdown");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_EXIT, "E&xit");
|
||||||
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
|
SetMenuDefaultItem (hPopup, ID_CONSOLE, FALSE);
|
||||||
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
|
SendMessage (hWnd, WM_INITMENUPOPUP, (WPARAM)hPopup, 0);
|
||||||
|
|
||||||
POINT p;
|
POINT p;
|
||||||
if (!curpos)
|
if (!curpos)
|
||||||
{
|
{
|
||||||
GetCursorPos (&p);
|
GetCursorPos (&p);
|
||||||
curpos = &p;
|
curpos = &p;
|
||||||
}
|
}
|
||||||
|
|
||||||
WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
|
WORD cmd = TrackPopupMenu (hPopup, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, curpos->x, curpos->y, 0, hWnd, NULL);
|
||||||
SendMessage (hWnd, WM_COMMAND, cmd, 0);
|
SendMessage (hWnd, WM_COMMAND, cmd, 0);
|
||||||
|
|
||||||
DestroyMenu(hPopup);
|
DestroyMenu(hPopup);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddTrayIcon (HWND hWnd)
|
static void AddTrayIcon (HWND hWnd)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA nid;
|
NOTIFYICONDATA nid;
|
||||||
memset(&nid, 0, sizeof(nid));
|
memset(&nid, 0, sizeof(nid));
|
||||||
nid.cbSize = sizeof(nid);
|
nid.cbSize = sizeof(nid);
|
||||||
nid.hWnd = hWnd;
|
nid.hWnd = hWnd;
|
||||||
nid.uID = ID_TRAY_ICON;
|
nid.uID = ID_TRAY_ICON;
|
||||||
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
|
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP | NIF_INFO;
|
||||||
nid.uCallbackMessage = WM_TRAYICON;
|
nid.uCallbackMessage = WM_TRAYICON;
|
||||||
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
|
nid.hIcon = LoadIcon (GetModuleHandle(NULL), MAKEINTRESOURCE (MAINICON));
|
||||||
strcpy (nid.szTip, "i2pd");
|
strcpy (nid.szTip, "i2pd");
|
||||||
strcpy (nid.szInfo, "i2pd is starting");
|
strcpy (nid.szInfo, "i2pd is starting");
|
||||||
Shell_NotifyIcon(NIM_ADD, &nid );
|
Shell_NotifyIcon(NIM_ADD, &nid );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void RemoveTrayIcon (HWND hWnd)
|
static void RemoveTrayIcon (HWND hWnd)
|
||||||
{
|
{
|
||||||
NOTIFYICONDATA nid;
|
NOTIFYICONDATA nid;
|
||||||
nid.hWnd = hWnd;
|
nid.hWnd = hWnd;
|
||||||
nid.uID = ID_TRAY_ICON;
|
nid.uID = ID_TRAY_ICON;
|
||||||
Shell_NotifyIcon (NIM_DELETE, &nid);
|
Shell_NotifyIcon (NIM_DELETE, &nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowUptime (std::stringstream& s, int seconds)
|
static void ShowUptime (std::stringstream& s, int seconds)
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
|
|
||||||
if ((num = seconds / 86400) > 0) {
|
if ((num = seconds / 86400) > 0) {
|
||||||
s << num << " days, ";
|
s << num << " days, ";
|
||||||
seconds -= num * 86400;
|
seconds -= num * 86400;
|
||||||
}
|
}
|
||||||
if ((num = seconds / 3600) > 0) {
|
if ((num = seconds / 3600) > 0) {
|
||||||
s << num << " hours, ";
|
s << num << " hours, ";
|
||||||
seconds -= num * 3600;
|
seconds -= num * 3600;
|
||||||
}
|
}
|
||||||
if ((num = seconds / 60) > 0) {
|
if ((num = seconds / 60) > 0) {
|
||||||
s << num << " min, ";
|
s << num << " min, ";
|
||||||
seconds -= num * 60;
|
seconds -= num * 60;
|
||||||
}
|
}
|
||||||
s << seconds << " seconds\n";
|
s << seconds << " seconds\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename size> static void ShowTransfered (std::stringstream& s, size transfer)
|
template <typename size> static void ShowTransfered (std::stringstream& s, size transfer)
|
||||||
{
|
{
|
||||||
auto bytes = transfer & 0x03ff;
|
auto bytes = transfer & 0x03ff;
|
||||||
transfer >>= 10;
|
transfer >>= 10;
|
||||||
auto kbytes = transfer & 0x03ff;
|
auto kbytes = transfer & 0x03ff;
|
||||||
transfer >>= 10;
|
transfer >>= 10;
|
||||||
auto mbytes = transfer & 0x03ff;
|
auto mbytes = transfer & 0x03ff;
|
||||||
transfer >>= 10;
|
transfer >>= 10;
|
||||||
auto gbytes = transfer & 0x03ff;
|
auto gbytes = transfer & 0x03ff;
|
||||||
|
|
||||||
if (gbytes)
|
if (gbytes)
|
||||||
s << gbytes << " GB, ";
|
s << gbytes << " GB, ";
|
||||||
if (mbytes)
|
if (mbytes)
|
||||||
s << mbytes << " MB, ";
|
s << mbytes << " MB, ";
|
||||||
if (kbytes)
|
if (kbytes)
|
||||||
s << kbytes << " KB, ";
|
s << kbytes << " KB, ";
|
||||||
s << bytes << " Bytes\n";
|
s << bytes << " Bytes\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintMainWindowText (std::stringstream& s)
|
static void PrintMainWindowText (std::stringstream& s)
|
||||||
{
|
{
|
||||||
s << "\n";
|
s << "\n";
|
||||||
s << "Status: ";
|
s << "Status: ";
|
||||||
switch (i2p::context.GetStatus())
|
switch (i2p::context.GetStatus())
|
||||||
{
|
{
|
||||||
case eRouterStatusOK: s << "OK"; break;
|
case eRouterStatusOK: s << "OK"; break;
|
||||||
case eRouterStatusTesting: s << "Testing"; break;
|
case eRouterStatusTesting: s << "Testing"; break;
|
||||||
case eRouterStatusFirewalled: s << "Firewalled"; break;
|
case eRouterStatusFirewalled: s << "Firewalled"; break;
|
||||||
case eRouterStatusError:
|
case eRouterStatusError:
|
||||||
{
|
{
|
||||||
switch (i2p::context.GetError())
|
switch (i2p::context.GetError())
|
||||||
{
|
{
|
||||||
case eRouterErrorClockSkew: s << "Clock skew"; break;
|
case eRouterErrorClockSkew: s << "Clock skew"; break;
|
||||||
default: s << "Error";
|
default: s << "Error";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: s << "Unknown";
|
default: s << "Unknown";
|
||||||
}
|
}
|
||||||
s << "; ";
|
s << "; ";
|
||||||
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
|
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
|
||||||
s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ());
|
s << "Uptime: "; ShowUptime(s, i2p::context.GetUptime ());
|
||||||
if (GracefulShutdownEndtime != 0)
|
if (GracefulShutdownEndtime != 0)
|
||||||
{
|
{
|
||||||
DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000;
|
DWORD GracefulTimeLeft = (GracefulShutdownEndtime - GetTickCountLocal()) / 1000;
|
||||||
s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft);
|
s << "Graceful shutdown, time left: "; ShowUptime(s, GracefulTimeLeft);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s << "\n";
|
s << "\n";
|
||||||
s << "Inbound: " << i2p::transport::transports.GetInBandwidth() / 1024 << " KiB/s; ";
|
s << "Inbound: " << i2p::transport::transports.GetInBandwidth() / 1024 << " KiB/s; ";
|
||||||
s << "Outbound: " << i2p::transport::transports.GetOutBandwidth() / 1024 << " KiB/s\n";
|
s << "Outbound: " << i2p::transport::transports.GetOutBandwidth() / 1024 << " KiB/s\n";
|
||||||
s << "Received: "; ShowTransfered (s, i2p::transport::transports.GetTotalReceivedBytes());
|
s << "Received: "; ShowTransfered (s, i2p::transport::transports.GetTotalReceivedBytes());
|
||||||
s << "Sent: "; ShowTransfered (s, i2p::transport::transports.GetTotalSentBytes());
|
s << "Sent: "; ShowTransfered (s, i2p::transport::transports.GetTotalSentBytes());
|
||||||
s << "\n";
|
s << "\n";
|
||||||
s << "Routers: " << i2p::data::netdb.GetNumRouters () << "; ";
|
s << "Routers: " << i2p::data::netdb.GetNumRouters () << "; ";
|
||||||
s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << "; ";
|
s << "Floodfills: " << i2p::data::netdb.GetNumFloodfills () << "; ";
|
||||||
s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "\n";
|
s << "LeaseSets: " << i2p::data::netdb.GetNumLeaseSets () << "\n";
|
||||||
s << "Tunnels: ";
|
s << "Tunnels: ";
|
||||||
s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; ";
|
s << "In: " << i2p::tunnel::tunnels.CountInboundTunnels() << "; ";
|
||||||
s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; ";
|
s << "Out: " << i2p::tunnel::tunnels.CountOutboundTunnels() << "; ";
|
||||||
s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n";
|
s << "Transit: " << i2p::tunnel::tunnels.CountTransitTunnels() << "\n";
|
||||||
s << "\n";
|
s << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
static LRESULT CALLBACK WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
static UINT s_uTaskbarRestart;
|
static UINT s_uTaskbarRestart;
|
||||||
|
|
||||||
switch (uMsg)
|
switch (uMsg)
|
||||||
{
|
{
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
{
|
{
|
||||||
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||||||
AddTrayIcon (hWnd);
|
AddTrayIcon (hWnd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
RemoveTrayIcon (hWnd);
|
RemoveTrayIcon (hWnd);
|
||||||
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
||||||
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
|
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
|
||||||
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
|
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
|
||||||
PostQuitMessage (0);
|
PostQuitMessage (0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
{
|
{
|
||||||
switch (LOWORD(wParam))
|
switch (LOWORD(wParam))
|
||||||
{
|
{
|
||||||
case ID_ABOUT:
|
case ID_ABOUT:
|
||||||
{
|
{
|
||||||
std::stringstream text;
|
std::stringstream text;
|
||||||
text << "Version: " << I2PD_VERSION << " " << CODENAME;
|
text << "Version: " << I2PD_VERSION << " " << CODENAME;
|
||||||
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_EXIT:
|
case ID_EXIT:
|
||||||
{
|
{
|
||||||
PostMessage (hWnd, WM_CLOSE, 0, 0);
|
PostMessage (hWnd, WM_CLOSE, 0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_ACCEPT_TRANSIT:
|
case ID_ACCEPT_TRANSIT:
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
std::stringstream text;
|
std::stringstream text;
|
||||||
text << "I2Pd now accept transit tunnels";
|
text << "I2Pd now accept transit tunnels";
|
||||||
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_DECLINE_TRANSIT:
|
case ID_DECLINE_TRANSIT:
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
std::stringstream text;
|
std::stringstream text;
|
||||||
text << "I2Pd now decline new transit tunnels";
|
text << "I2Pd now decline new transit tunnels";
|
||||||
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_GRACEFUL_SHUTDOWN:
|
case ID_GRACEFUL_SHUTDOWN:
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (false);
|
i2p::context.SetAcceptsTunnels (false);
|
||||||
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
|
SetTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER, 10*60*1000, nullptr); // 10 minutes
|
||||||
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second
|
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr); // check tunnels every second
|
||||||
GracefulShutdownEndtime = GetTickCountLocal() + 10*60*1000;
|
GracefulShutdownEndtime = GetTickCountLocal() + 10*60*1000;
|
||||||
i2p::util::DaemonWin32::Instance ().isGraceful = true;
|
i2p::util::DaemonWin32::Instance ().isGraceful = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_STOP_GRACEFUL_SHUTDOWN:
|
case ID_STOP_GRACEFUL_SHUTDOWN:
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
|
KillTimer (hWnd, IDT_GRACEFUL_SHUTDOWN_TIMER);
|
||||||
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
|
KillTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER);
|
||||||
GracefulShutdownEndtime = 0;
|
GracefulShutdownEndtime = 0;
|
||||||
i2p::util::DaemonWin32::Instance ().isGraceful = false;
|
i2p::util::DaemonWin32::Instance ().isGraceful = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_RELOAD:
|
case ID_RELOAD:
|
||||||
{
|
{
|
||||||
i2p::client::context.ReloadConfig();
|
i2p::client::context.ReloadConfig();
|
||||||
std::stringstream text;
|
std::stringstream text;
|
||||||
text << "I2Pd reloading configs...";
|
text << "I2Pd reloading configs...";
|
||||||
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
MessageBox( hWnd, TEXT(text.str ().c_str ()), TEXT("i2pd"), MB_ICONINFORMATION | MB_OK );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_CONSOLE:
|
case ID_CONSOLE:
|
||||||
{
|
{
|
||||||
char buf[30];
|
char buf[30];
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
|
snprintf(buf, 30, "http://%s:%d", httpAddr.c_str(), httpPort);
|
||||||
ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
|
ShellExecute(NULL, "open", buf, NULL, NULL, SW_SHOWNORMAL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case ID_APP:
|
case ID_APP:
|
||||||
{
|
{
|
||||||
ShowWindow(hWnd, SW_SHOW);
|
ShowWindow(hWnd, SW_SHOW);
|
||||||
SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL);
|
SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_SYSCOMMAND:
|
case WM_SYSCOMMAND:
|
||||||
{
|
{
|
||||||
switch (wParam)
|
switch (wParam)
|
||||||
{
|
{
|
||||||
case SC_MINIMIZE:
|
case SC_MINIMIZE:
|
||||||
{
|
{
|
||||||
ShowWindow(hWnd, SW_HIDE);
|
ShowWindow(hWnd, SW_HIDE);
|
||||||
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SC_CLOSE:
|
case SC_CLOSE:
|
||||||
{
|
{
|
||||||
std::string close; i2p::config::GetOption("close", close);
|
std::string close; i2p::config::GetOption("close", close);
|
||||||
if (0 == close.compare("ask"))
|
if (0 == close.compare("ask"))
|
||||||
switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
|
switch(::MessageBox(hWnd, "Would you like to minimize instead of exiting?"
|
||||||
" You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
|
" You can add 'close' configuration option. Valid values are: ask, minimize, exit.",
|
||||||
"Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
|
"Minimize instead of exiting?", MB_ICONQUESTION | MB_YESNOCANCEL | MB_DEFBUTTON1))
|
||||||
{
|
{
|
||||||
case IDYES: close = "minimize"; break;
|
case IDYES: close = "minimize"; break;
|
||||||
case IDNO: close = "exit"; break;
|
case IDNO: close = "exit"; break;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
if (0 == close.compare("minimize"))
|
if (0 == close.compare("minimize"))
|
||||||
{
|
{
|
||||||
ShowWindow(hWnd, SW_HIDE);
|
ShowWindow(hWnd, SW_HIDE);
|
||||||
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
KillTimer (hWnd, FRAME_UPDATE_TIMER);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (0 != close.compare("exit"))
|
if (0 != close.compare("exit"))
|
||||||
{
|
{
|
||||||
::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
|
::MessageBox(hWnd, close.c_str(), "Unknown close action in config", MB_OK | MB_ICONWARNING);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case WM_TRAYICON:
|
case WM_TRAYICON:
|
||||||
{
|
{
|
||||||
switch (lParam)
|
switch (lParam)
|
||||||
{
|
{
|
||||||
case WM_LBUTTONUP:
|
case WM_LBUTTONUP:
|
||||||
case WM_RBUTTONUP:
|
case WM_RBUTTONUP:
|
||||||
{
|
{
|
||||||
SetForegroundWindow (hWnd);
|
SetForegroundWindow (hWnd);
|
||||||
ShowPopupMenu(hWnd, NULL, -1);
|
ShowPopupMenu(hWnd, NULL, -1);
|
||||||
PostMessage (hWnd, WM_APP + 1, 0, 0);
|
PostMessage (hWnd, WM_APP + 1, 0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
{
|
{
|
||||||
switch(wParam)
|
switch(wParam)
|
||||||
{
|
{
|
||||||
case IDT_GRACEFUL_SHUTDOWN_TIMER:
|
case IDT_GRACEFUL_SHUTDOWN_TIMER:
|
||||||
{
|
{
|
||||||
GracefulShutdownEndtime = 0;
|
GracefulShutdownEndtime = 0;
|
||||||
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
|
PostMessage (hWnd, WM_CLOSE, 0, 0); // exit
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
|
case IDT_GRACEFUL_TUNNELCHECK_TIMER:
|
||||||
{
|
{
|
||||||
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
|
if (i2p::tunnel::tunnels.CountTransitTunnels() == 0)
|
||||||
PostMessage (hWnd, WM_CLOSE, 0, 0);
|
PostMessage (hWnd, WM_CLOSE, 0, 0);
|
||||||
else
|
else
|
||||||
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
|
SetTimer (hWnd, IDT_GRACEFUL_TUNNELCHECK_TIMER, 1000, nullptr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case FRAME_UPDATE_TIMER:
|
case FRAME_UPDATE_TIMER:
|
||||||
{
|
{
|
||||||
InvalidateRect(hWnd, NULL, TRUE);
|
InvalidateRect(hWnd, NULL, TRUE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
{
|
{
|
||||||
HDC hDC;
|
HDC hDC;
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
RECT rp;
|
RECT rp;
|
||||||
HFONT hFont;
|
HFONT hFont;
|
||||||
std::stringstream s; PrintMainWindowText (s);
|
std::stringstream s; PrintMainWindowText (s);
|
||||||
hDC = BeginPaint (hWnd, &ps);
|
hDC = BeginPaint (hWnd, &ps);
|
||||||
GetClientRect(hWnd, &rp);
|
GetClientRect(hWnd, &rp);
|
||||||
SetTextColor(hDC, 0x00D43B69);
|
SetTextColor(hDC, 0x00D43B69);
|
||||||
hFont = CreateFont(18,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,TEXT("Times New Roman"));
|
hFont = CreateFont(18,0,0,0,0,0,0,0,DEFAULT_CHARSET,0,0,0,0,TEXT("Times New Roman"));
|
||||||
SelectObject(hDC,hFont);
|
SelectObject(hDC,hFont);
|
||||||
DrawText(hDC, TEXT(s.str().c_str()), s.str().length(), &rp, DT_CENTER|DT_VCENTER);
|
DrawText(hDC, TEXT(s.str().c_str()), s.str().length(), &rp, DT_CENTER|DT_VCENTER);
|
||||||
DeleteObject(hFont);
|
DeleteObject(hFont);
|
||||||
EndPaint(hWnd, &ps);
|
EndPaint(hWnd, &ps);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (uMsg == s_uTaskbarRestart)
|
if (uMsg == s_uTaskbarRestart)
|
||||||
AddTrayIcon (hWnd);
|
AddTrayIcon (hWnd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DefWindowProc( hWnd, uMsg, wParam, lParam);
|
return DefWindowProc( hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartWin32App ()
|
bool StartWin32App ()
|
||||||
{
|
{
|
||||||
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
|
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
|
||||||
{
|
{
|
||||||
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
|
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// register main window
|
// register main window
|
||||||
auto hInst = GetModuleHandle(NULL);
|
auto hInst = GetModuleHandle(NULL);
|
||||||
WNDCLASSEX wclx;
|
WNDCLASSEX wclx;
|
||||||
memset (&wclx, 0, sizeof(wclx));
|
memset (&wclx, 0, sizeof(wclx));
|
||||||
wclx.cbSize = sizeof(wclx);
|
wclx.cbSize = sizeof(wclx);
|
||||||
wclx.style = 0;
|
wclx.style = 0;
|
||||||
wclx.lpfnWndProc = WndProc;
|
wclx.lpfnWndProc = WndProc;
|
||||||
//wclx.cbClsExtra = 0;
|
//wclx.cbClsExtra = 0;
|
||||||
//wclx.cbWndExtra = 0;
|
//wclx.cbWndExtra = 0;
|
||||||
wclx.hInstance = hInst;
|
wclx.hInstance = hInst;
|
||||||
wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON));
|
wclx.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(MAINICON));
|
||||||
wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
|
wclx.hCursor = LoadCursor (NULL, IDC_ARROW);
|
||||||
//wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
//wclx.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
|
||||||
wclx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
wclx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||||
wclx.lpszMenuName = NULL;
|
wclx.lpszMenuName = NULL;
|
||||||
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
|
wclx.lpszClassName = I2PD_WIN32_CLASSNAME;
|
||||||
RegisterClassEx (&wclx);
|
RegisterClassEx (&wclx);
|
||||||
// create new window
|
// create new window
|
||||||
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL))
|
if (!CreateWindow(I2PD_WIN32_CLASSNAME, TEXT("i2pd"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 350, 210, NULL, NULL, hInst, NULL))
|
||||||
{
|
{
|
||||||
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
|
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SubscribeToEvents();
|
SubscribeToEvents();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RunWin32App ()
|
int RunWin32App ()
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
while (GetMessage (&msg, NULL, 0, 0 ))
|
while (GetMessage (&msg, NULL, 0, 0 ))
|
||||||
{
|
{
|
||||||
TranslateMessage (&msg);
|
TranslateMessage (&msg);
|
||||||
DispatchMessage (&msg);
|
DispatchMessage (&msg);
|
||||||
}
|
}
|
||||||
return msg.wParam;
|
return msg.wParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopWin32App ()
|
void StopWin32App ()
|
||||||
{
|
{
|
||||||
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
||||||
if (hWnd)
|
if (hWnd)
|
||||||
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
|
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
|
||||||
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
|
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
|
||||||
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
|
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GracefulShutdown ()
|
bool GracefulShutdown ()
|
||||||
{
|
{
|
||||||
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
||||||
if (hWnd)
|
if (hWnd)
|
||||||
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
|
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_GRACEFUL_SHUTDOWN, 0), 0);
|
||||||
return hWnd;
|
return hWnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StopGracefulShutdown ()
|
bool StopGracefulShutdown ()
|
||||||
{
|
{
|
||||||
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
|
||||||
if (hWnd)
|
if (hWnd)
|
||||||
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
|
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_STOP_GRACEFUL_SHUTDOWN, 0), 0);
|
||||||
return hWnd;
|
return hWnd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
#ifndef WIN32APP_H__
|
#ifndef WIN32APP_H__
|
||||||
#define WIN32APP_H__
|
#define WIN32APP_H__
|
||||||
|
|
||||||
#define I2PD_WIN32_CLASSNAME "i2pd main window"
|
#define I2PD_WIN32_CLASSNAME "i2pd main window"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace win32
|
namespace win32
|
||||||
{
|
{
|
||||||
bool StartWin32App ();
|
bool StartWin32App ();
|
||||||
void StopWin32App ();
|
void StopWin32App ();
|
||||||
int RunWin32App ();
|
int RunWin32App ();
|
||||||
bool GracefulShutdown ();
|
bool GracefulShutdown ();
|
||||||
bool StopGracefulShutdown ();
|
bool StopGracefulShutdown ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // WIN32APP_H__
|
#endif // WIN32APP_H__
|
||||||
|
|
|
@ -26,48 +26,48 @@
|
||||||
|
|
||||||
class I2PService
|
class I2PService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PService(PSTR pszServiceName,
|
I2PService(PSTR pszServiceName,
|
||||||
BOOL fCanStop = TRUE,
|
BOOL fCanStop = TRUE,
|
||||||
BOOL fCanShutdown = TRUE,
|
BOOL fCanShutdown = TRUE,
|
||||||
BOOL fCanPauseContinue = FALSE);
|
BOOL fCanPauseContinue = FALSE);
|
||||||
|
|
||||||
virtual ~I2PService(void);
|
virtual ~I2PService(void);
|
||||||
|
|
||||||
static BOOL isService();
|
static BOOL isService();
|
||||||
static BOOL Run(I2PService &service);
|
static BOOL Run(I2PService &service);
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
||||||
virtual void OnStop();
|
virtual void OnStop();
|
||||||
virtual void OnPause();
|
virtual void OnPause();
|
||||||
virtual void OnContinue();
|
virtual void OnContinue();
|
||||||
virtual void OnShutdown();
|
virtual void OnShutdown();
|
||||||
void SetServiceStatus(DWORD dwCurrentState,
|
void SetServiceStatus(DWORD dwCurrentState,
|
||||||
DWORD dwWin32ExitCode = NO_ERROR,
|
DWORD dwWin32ExitCode = NO_ERROR,
|
||||||
DWORD dwWaitHint = 0);
|
DWORD dwWaitHint = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
||||||
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
||||||
void WorkerThread();
|
void WorkerThread();
|
||||||
void Start(DWORD dwArgc, PSTR *pszArgv);
|
void Start(DWORD dwArgc, PSTR *pszArgv);
|
||||||
void Pause();
|
void Pause();
|
||||||
void Continue();
|
void Continue();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
static I2PService* s_service;
|
static I2PService* s_service;
|
||||||
PSTR m_name;
|
PSTR m_name;
|
||||||
SERVICE_STATUS m_status;
|
SERVICE_STATUS m_status;
|
||||||
SERVICE_STATUS_HANDLE m_statusHandle;
|
SERVICE_STATUS_HANDLE m_statusHandle;
|
||||||
|
|
||||||
BOOL m_fStopping;
|
BOOL m_fStopping;
|
||||||
HANDLE m_hStoppedEvent;
|
HANDLE m_hStoppedEvent;
|
||||||
|
|
||||||
std::thread* _worker;
|
std::thread* _worker;
|
||||||
};
|
};
|
||||||
|
|
||||||
void InstallService(
|
void InstallService(
|
||||||
|
@ -77,8 +77,8 @@ void InstallService(
|
||||||
PCSTR pszDependencies,
|
PCSTR pszDependencies,
|
||||||
PCSTR pszAccount,
|
PCSTR pszAccount,
|
||||||
PCSTR pszPassword
|
PCSTR pszPassword
|
||||||
);
|
);
|
||||||
|
|
||||||
void UninstallService(PCSTR pszServiceName);
|
void UninstallService(PCSTR pszServiceName);
|
||||||
|
|
||||||
#endif // WIN_32_SERVICE_H__
|
#endif // WIN_32_SERVICE_H__
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//{{NO_DEPENDENCIES}}
|
//{{NO_DEPENDENCIES}}
|
||||||
#define MAINICON 101
|
#define MAINICON 101
|
||||||
|
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -127,8 +127,8 @@ namespace i2p
|
||||||
i2p::context.SetNetID (netID);
|
i2p::context.SetNetID (netID);
|
||||||
i2p::context.Init ();
|
i2p::context.Init ();
|
||||||
|
|
||||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||||
#ifdef MESHNET
|
#ifdef MESHNET
|
||||||
// manual override for meshnet
|
// manual override for meshnet
|
||||||
ipv4 = false;
|
ipv4 = false;
|
||||||
|
@ -143,8 +143,8 @@ namespace i2p
|
||||||
i2p::context.SetSupportsV6 (ipv6);
|
i2p::context.SetSupportsV6 (ipv6);
|
||||||
i2p::context.SetSupportsV4 (ipv4);
|
i2p::context.SetSupportsV4 (ipv4);
|
||||||
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||||
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
|
i2p::context.PublishNTCPAddress (ntcp, !ipv6);
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
if (ntcp2)
|
if (ntcp2)
|
||||||
{
|
{
|
||||||
|
@ -172,10 +172,13 @@ namespace i2p
|
||||||
SetMaxNumTransitTunnels (transitTunnels);
|
SetMaxNumTransitTunnels (transitTunnels);
|
||||||
|
|
||||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||||
if (isFloodfill) {
|
if (isFloodfill)
|
||||||
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
||||||
i2p::context.SetFloodfill (true);
|
i2p::context.SetFloodfill (true);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
i2p::context.SetFloodfill (false);
|
i2p::context.SetFloodfill (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +246,8 @@ namespace i2p
|
||||||
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
i2p::transport::transports.RestrictRoutesToFamilies(fams);
|
||||||
restricted = fams.size() > 0;
|
restricted = fams.size() > 0;
|
||||||
}
|
}
|
||||||
if (routers.length() > 0) {
|
if (routers.length() > 0)
|
||||||
|
{
|
||||||
std::set<i2p::data::IdentHash> idents;
|
std::set<i2p::data::IdentHash> idents;
|
||||||
size_t pos = 0, comma;
|
size_t pos = 0, comma;
|
||||||
do
|
do
|
||||||
|
@ -279,7 +283,8 @@ namespace i2p
|
||||||
i2p::data::netdb.Start();
|
i2p::data::netdb.Start();
|
||||||
|
|
||||||
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
||||||
if (upnp) {
|
if (upnp)
|
||||||
|
{
|
||||||
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
d.UPnP = std::unique_ptr<i2p::transport::UPnP>(new i2p::transport::UPnP);
|
||||||
d.UPnP->Start ();
|
d.UPnP->Start ();
|
||||||
}
|
}
|
||||||
|
@ -292,15 +297,15 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
bool ntcp; i2p::config::GetOption("ntcp", ntcp);
|
||||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
LogPrint(eLogInfo, "Daemon: starting Transports");
|
||||||
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
||||||
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
if(!ntcp) LogPrint(eLogInfo, "Daemon: ntcp disabled");
|
||||||
|
|
||||||
i2p::transport::transports.Start(ntcp, ssu);
|
i2p::transport::transports.Start(ntcp, ssu);
|
||||||
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
if (i2p::transport::transports.IsBoundNTCP() || i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
LogPrint(eLogError, "Daemon: failed to start Transports");
|
||||||
/** shut down netdb right away */
|
/** shut down netdb right away */
|
||||||
|
@ -310,23 +315,23 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
bool http; i2p::config::GetOption("http.enabled", http);
|
bool http; i2p::config::GetOption("http.enabled", http);
|
||||||
if (http) {
|
if (http)
|
||||||
|
{
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||||
d.httpServer->Start();
|
d.httpServer->Start();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
||||||
i2p::tunnel::tunnels.Start();
|
i2p::tunnel::tunnels.Start();
|
||||||
|
|
||||||
|
@ -339,12 +344,12 @@ namespace i2p
|
||||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||||
d.m_I2PControlService->Start ();
|
d.m_I2PControlService->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||||
|
@ -361,7 +366,7 @@ namespace i2p
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
||||||
i2p::tunnel::tunnels.Stop();
|
i2p::tunnel::tunnels.Stop();
|
||||||
|
|
||||||
if (d.UPnP)
|
if (d.UPnP)
|
||||||
{
|
{
|
||||||
d.UPnP->Stop ();
|
d.UPnP->Stop ();
|
||||||
d.UPnP = nullptr;
|
d.UPnP = nullptr;
|
||||||
|
|
|
@ -13,9 +13,10 @@ namespace util
|
||||||
class Daemon_Singleton
|
class Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
|
||||||
virtual bool init(int argc, char* argv[]);
|
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||||
virtual bool start();
|
virtual bool init(int argc, char* argv[]);
|
||||||
|
virtual bool start();
|
||||||
virtual bool stop();
|
virtual bool stop();
|
||||||
virtual void run () {};
|
virtual void run () {};
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ namespace util
|
||||||
bool running;
|
bool running;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Daemon_Singleton();
|
Daemon_Singleton();
|
||||||
virtual ~Daemon_Singleton();
|
virtual ~Daemon_Singleton();
|
||||||
|
|
||||||
|
@ -39,6 +41,7 @@ namespace util
|
||||||
class DaemonQT: public i2p::util::Daemon_Singleton
|
class DaemonQT: public i2p::util::Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonQT& Instance()
|
static DaemonQT& Instance()
|
||||||
{
|
{
|
||||||
static DaemonQT instance;
|
static DaemonQT instance;
|
||||||
|
@ -51,6 +54,7 @@ namespace util
|
||||||
class DaemonWin32 : public Daemon_Singleton
|
class DaemonWin32 : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonWin32& Instance()
|
static DaemonWin32& Instance()
|
||||||
{
|
{
|
||||||
static DaemonWin32 instance;
|
static DaemonWin32 instance;
|
||||||
|
@ -72,6 +76,7 @@ namespace util
|
||||||
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
class DaemonAndroid: public i2p::util::Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonAndroid& Instance()
|
static DaemonAndroid& Instance()
|
||||||
{
|
{
|
||||||
static DaemonAndroid instance;
|
static DaemonAndroid instance;
|
||||||
|
@ -83,6 +88,7 @@ namespace util
|
||||||
class DaemonLinux : public Daemon_Singleton
|
class DaemonLinux : public Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static DaemonLinux& Instance()
|
static DaemonLinux& Instance()
|
||||||
{
|
{
|
||||||
static DaemonLinux instance;
|
static DaemonLinux instance;
|
||||||
|
@ -94,10 +100,12 @@ namespace util
|
||||||
void run ();
|
void run ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string pidfile;
|
std::string pidfile;
|
||||||
int pidFH;
|
int pidFH;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
int gracefulShutdownInterval; // in seconds
|
int gracefulShutdownInterval; // in seconds
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -892,8 +892,8 @@ namespace http {
|
||||||
void HTTPConnection::Receive ()
|
void HTTPConnection::Receive ()
|
||||||
{
|
{
|
||||||
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
|
m_Socket->async_read_some (boost::asio::buffer (m_Buffer, HTTP_CONNECTION_BUFFER_SIZE),
|
||||||
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
|
std::bind(&HTTPConnection::HandleReceive, shared_from_this (),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void HTTPConnection::HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
|
|
|
@ -79,17 +79,17 @@ namespace http
|
||||||
std::string m_Hostname;
|
std::string m_Hostname;
|
||||||
};
|
};
|
||||||
|
|
||||||
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
|
//all the below functions are also used by Qt GUI, see mainwindow.cpp -> getStatusPageHtml
|
||||||
enum OutputFormatEnum { forWebConsole, forQtUi };
|
enum OutputFormatEnum { forWebConsole, forQtUi };
|
||||||
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
|
void ShowStatus (std::stringstream& s, bool includeHiddenContent, OutputFormatEnum outputFormat);
|
||||||
void ShowLocalDestinations (std::stringstream& s);
|
void ShowLocalDestinations (std::stringstream& s);
|
||||||
void ShowLeasesSets(std::stringstream& s);
|
void ShowLeasesSets(std::stringstream& s);
|
||||||
void ShowTunnels (std::stringstream& s);
|
void ShowTunnels (std::stringstream& s);
|
||||||
void ShowTransitTunnels (std::stringstream& s);
|
void ShowTransitTunnels (std::stringstream& s);
|
||||||
void ShowTransports (std::stringstream& s);
|
void ShowTransports (std::stringstream& s);
|
||||||
void ShowSAMSessions (std::stringstream& s);
|
void ShowSAMSessions (std::stringstream& s);
|
||||||
void ShowI2PTunnels (std::stringstream& s);
|
void ShowI2PTunnels (std::stringstream& s);
|
||||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -59,29 +59,28 @@ namespace client
|
||||||
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||||
|
|
||||||
// I2PControl
|
// I2PControl
|
||||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||||
|
|
||||||
// RouterInfo
|
// RouterInfo
|
||||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||||
&I2PControlService::TunnelsSuccessRateHandler;
|
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||||
|
|
||||||
|
@ -97,10 +96,10 @@ namespace client
|
||||||
// ClientServicesInfo
|
// ClientServicesInfo
|
||||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PControlService::~I2PControlService ()
|
I2PControlService::~I2PControlService ()
|
||||||
|
@ -401,8 +400,8 @@ namespace client
|
||||||
auto it1 = m_RouterInfoHandlers.find (it->first);
|
auto it1 = m_RouterInfoHandlers.find (it->first);
|
||||||
if (it1 != m_RouterInfoHandlers.end ())
|
if (it1 != m_RouterInfoHandlers.end ())
|
||||||
{
|
{
|
||||||
if (!first) results << ",";
|
if (!first) results << ",";
|
||||||
else first = false;
|
else first = false;
|
||||||
(this->*(it1->second))(results);
|
(this->*(it1->second))(results);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -500,7 +499,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -514,7 +513,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace client
|
||||||
class I2PControlService
|
class I2PControlService
|
||||||
{
|
{
|
||||||
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
I2PControlService (const std::string& address, int port);
|
I2PControlService (const std::string& address, int port);
|
||||||
|
|
|
@ -80,10 +80,10 @@ namespace transport
|
||||||
void UPnP::Discover ()
|
void UPnP::Discover ()
|
||||||
{
|
{
|
||||||
bool isError;
|
bool isError;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||||
err = UPNPDISCOVER_SUCCESS;
|
err = UPNPDISCOVER_SUCCESS;
|
||||||
|
|
||||||
#if (MINIUPNPC_API_VERSION >= 14)
|
#if (MINIUPNPC_API_VERSION >= 14)
|
||||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
|
||||||
|
@ -92,9 +92,9 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isError = err != UPNPDISCOVER_SUCCESS;
|
isError = err != UPNPDISCOVER_SUCCESS;
|
||||||
#else // MINIUPNPC_API_VERSION >= 8
|
#else // MINIUPNPC_API_VERSION >= 8
|
||||||
err = 0;
|
err = 0;
|
||||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||||
isError = m_Devlist == NULL;
|
isError = m_Devlist == NULL;
|
||||||
#endif // MINIUPNPC_API_VERSION >= 8
|
#endif // MINIUPNPC_API_VERSION >= 8
|
||||||
{
|
{
|
||||||
|
@ -105,15 +105,15 @@ namespace transport
|
||||||
|
|
||||||
if (isError)
|
if (isError)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
|
||||||
m_upnpUrlsInitialized=err!=0;
|
m_upnpUrlsInitialized = err != 0;
|
||||||
if (err == UPNP_IGD_VALID_CONNECTED)
|
if (err == UPNP_IGD_VALID_CONNECTED)
|
||||||
{
|
{
|
||||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
if(err != UPNPCOMMAND_SUCCESS)
|
if(err != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
||||||
|
@ -124,14 +124,14 @@ namespace transport
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
||||||
if (!m_externalIPAddress[0])
|
if (!m_externalIPAddress[0])
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ namespace transport
|
||||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||||
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
||||||
|
|
||||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||||
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
||||||
|
@ -202,7 +202,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,14 +219,14 @@ namespace transport
|
||||||
|
|
||||||
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||||
{
|
{
|
||||||
if(!m_upnpUrlsInitialized) {
|
if(!m_upnpUrlsInitialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
|
||||||
int err = UPNPCOMMAND_SUCCESS;
|
int err = UPNPCOMMAND_SUCCESS;
|
||||||
|
|
||||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||||
if (err == UPNPCOMMAND_SUCCESS)
|
if (err == UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
|
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
|
||||||
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
|
||||||
|
@ -237,11 +237,11 @@ namespace transport
|
||||||
{
|
{
|
||||||
freeUPNPDevlist (m_Devlist);
|
freeUPNPDevlist (m_Devlist);
|
||||||
m_Devlist = 0;
|
m_Devlist = 0;
|
||||||
if(m_upnpUrlsInitialized){
|
if(m_upnpUrlsInitialized){
|
||||||
FreeUPNPUrls (&m_upnpUrls);
|
FreeUPNPUrls (&m_upnpUrls);
|
||||||
m_upnpUrlsInitialized=false;
|
m_upnpUrlsInitialized=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,41 +33,41 @@ namespace transport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UPnP ();
|
UPnP ();
|
||||||
~UPnP ();
|
~UPnP ();
|
||||||
void Close ();
|
void Close ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Discover ();
|
void Discover ();
|
||||||
int CheckMapping (const char* port, const char* type);
|
int CheckMapping (const char* port, const char* type);
|
||||||
void PortMapping ();
|
void PortMapping ();
|
||||||
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
||||||
void CloseMapping ();
|
void CloseMapping ();
|
||||||
void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
void CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
std::condition_variable m_Started;
|
std::condition_variable m_Started;
|
||||||
std::mutex m_StartedMutex;
|
std::mutex m_StartedMutex;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::deadline_timer m_Timer;
|
boost::asio::deadline_timer m_Timer;
|
||||||
bool m_upnpUrlsInitialized=false;
|
bool m_upnpUrlsInitialized = false;
|
||||||
struct UPNPUrls m_upnpUrls;
|
struct UPNPUrls m_upnpUrls;
|
||||||
struct IGDdatas m_upnpData;
|
struct IGDdatas m_upnpData;
|
||||||
|
|
||||||
// For miniupnpc
|
// For miniupnpc
|
||||||
struct UPNPDev * m_Devlist = 0;
|
struct UPNPDev * m_Devlist = 0;
|
||||||
char m_NetworkAddr[64];
|
char m_NetworkAddr[64];
|
||||||
char m_externalIPAddress[40];
|
char m_externalIPAddress[40];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,10 +79,10 @@ namespace transport {
|
||||||
class UPnP {
|
class UPnP {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
UPnP () {};
|
UPnP () {};
|
||||||
~UPnP () {};
|
~UPnP () {};
|
||||||
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
|
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
|
||||||
void Stop () {};
|
void Stop () {};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,5 +196,4 @@ namespace i2p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
#include "Daemon.h"
|
#include "Daemon.h"
|
||||||
|
|
||||||
#if defined(QT_GUI_LIB)
|
#if defined(QT_GUI_LIB)
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace qt
|
namespace qt
|
||||||
|
@ -10,11 +9,11 @@ namespace qt
|
||||||
int RunQT (int argc, char* argv[]);
|
int RunQT (int argc, char* argv[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
return i2p::qt::RunQT (argc, argv);
|
return i2p::qt::RunQT (argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int main( int argc, char* argv[] )
|
int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
|
|
214
libi2pd/Base.cpp
214
libi2pd/Base.cpp
|
@ -7,7 +7,8 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
static const char T32[32] = {
|
static const char T32[32] =
|
||||||
|
{
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
|
||||||
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
|
||||||
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
|
||||||
|
@ -29,15 +30,16 @@ namespace data
|
||||||
* Direct Substitution Table
|
* Direct Substitution Table
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static const char T64[64] = {
|
static const char T64[64] =
|
||||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
{
|
||||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||||
'4', '5', '6', '7', '8', '9', '-', '~'
|
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||||
|
'4', '5', '6', '7', '8', '9', '-', '~'
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * GetBase64SubstitutionTable ()
|
const char * GetBase64SubstitutionTable ()
|
||||||
|
@ -67,14 +69,12 @@ namespace data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t /* Number of bytes in the encoded buffer */
|
size_t ByteStreamToBase64 ( /* Number of bytes in the encoded buffer */
|
||||||
ByteStreamToBase64 (
|
const uint8_t * InBuffer, /* Input buffer, binary data */
|
||||||
const uint8_t * InBuffer, /* Input buffer, binary data */
|
size_t InCount, /* Number of bytes in the input buffer */
|
||||||
size_t InCount, /* Number of bytes in the input buffer */
|
char * OutBuffer, /* output buffer */
|
||||||
char * OutBuffer, /* output buffer */
|
size_t len /* length of output buffer */
|
||||||
size_t len /* length of output buffer */
|
|
||||||
)
|
)
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned char * ps;
|
unsigned char * ps;
|
||||||
unsigned char * pd;
|
unsigned char * pd;
|
||||||
|
@ -83,55 +83,60 @@ namespace data
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
int m;
|
int m;
|
||||||
size_t outCount;
|
size_t outCount;
|
||||||
|
|
||||||
ps = (unsigned char *)InBuffer;
|
ps = (unsigned char *)InBuffer;
|
||||||
n = InCount/3;
|
n = InCount / 3;
|
||||||
m = InCount%3;
|
m = InCount % 3;
|
||||||
if (!m)
|
if (!m)
|
||||||
outCount = 4*n;
|
outCount = 4 * n;
|
||||||
else
|
else
|
||||||
outCount = 4*(n+1);
|
outCount = 4 * (n + 1);
|
||||||
|
|
||||||
if (outCount > len) return 0;
|
if (outCount > len) return 0;
|
||||||
|
|
||||||
pd = (unsigned char *)OutBuffer;
|
pd = (unsigned char *)OutBuffer;
|
||||||
for ( i = 0; i<n; i++ ){
|
for ( i = 0; i < n; i++ )
|
||||||
acc_1 = *ps++;
|
{
|
||||||
acc_2 = (acc_1<<4)&0x30;
|
acc_1 = *ps++;
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_2 = (acc_1 << 4) & 0x30;
|
||||||
*pd++ = T64[acc_1];
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
acc_1 = *ps++;
|
*pd++ = T64[acc_1];
|
||||||
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
acc_1 = *ps++;
|
||||||
*pd++ = T64[acc_2];
|
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
||||||
acc_1 &= 0x0f;
|
*pd++ = T64[acc_2];
|
||||||
acc_1 <<=2;
|
acc_1 &= 0x0f;
|
||||||
acc_2 = *ps++;
|
acc_1 <<= 2;
|
||||||
acc_1 |= acc_2>>6; /* base64 digit #3 */
|
acc_2 = *ps++;
|
||||||
*pd++ = T64[acc_1];
|
acc_1 |= acc_2 >> 6; /* base64 digit #3 */
|
||||||
acc_2 &= 0x3f; /* base64 digit #4 */
|
*pd++ = T64[acc_1];
|
||||||
*pd++ = T64[acc_2];
|
acc_2 &= 0x3f; /* base64 digit #4 */
|
||||||
|
*pd++ = T64[acc_2];
|
||||||
}
|
}
|
||||||
if ( m == 1 ){
|
if ( m == 1 )
|
||||||
acc_1 = *ps++;
|
{
|
||||||
acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */
|
acc_1 = *ps++;
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_2 = (acc_1 << 4) & 0x3f; /* base64 digit #2 */
|
||||||
*pd++ = T64[acc_1];
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
*pd++ = T64[acc_2];
|
*pd++ = T64[acc_1];
|
||||||
*pd++ = P64;
|
*pd++ = T64[acc_2];
|
||||||
*pd++ = P64;
|
*pd++ = P64;
|
||||||
|
*pd++ = P64;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( m == 2 ){
|
else if ( m == 2 )
|
||||||
acc_1 = *ps++;
|
{
|
||||||
acc_2 = (acc_1<<4)&0x3f;
|
acc_1 = *ps++;
|
||||||
acc_1 >>= 2; /* base64 digit #1 */
|
acc_2 = (acc_1 << 4) & 0x3f;
|
||||||
*pd++ = T64[acc_1];
|
acc_1 >>= 2; /* base64 digit #1 */
|
||||||
acc_1 = *ps++;
|
*pd++ = T64[acc_1];
|
||||||
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
acc_1 = *ps++;
|
||||||
*pd++ = T64[acc_2];
|
acc_2 |= acc_1 >> 4; /* base64 digit #2 */
|
||||||
acc_1 &= 0x0f;
|
*pd++ = T64[acc_2];
|
||||||
acc_1 <<=2; /* base64 digit #3 */
|
acc_1 &= 0x0f;
|
||||||
*pd++ = T64[acc_1];
|
acc_1 <<= 2; /* base64 digit #3 */
|
||||||
*pd++ = P64;
|
*pd++ = T64[acc_1];
|
||||||
|
*pd++ = P64;
|
||||||
}
|
}
|
||||||
|
|
||||||
return outCount;
|
return outCount;
|
||||||
|
@ -147,12 +152,11 @@ namespace data
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
size_t /* Number of output bytes */
|
size_t Base64ToByteStream ( /* Number of output bytes */
|
||||||
Base64ToByteStream (
|
const char * InBuffer, /* BASE64 encoded buffer */
|
||||||
const char * InBuffer, /* BASE64 encoded buffer */
|
size_t InCount, /* Number of input bytes */
|
||||||
size_t InCount, /* Number of input bytes */
|
uint8_t * OutBuffer, /* output buffer length */
|
||||||
uint8_t * OutBuffer, /* output buffer length */
|
size_t len /* length of output buffer */
|
||||||
size_t len /* length of output buffer */
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
unsigned char * ps;
|
unsigned char * ps;
|
||||||
|
@ -162,42 +166,52 @@ namespace data
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
int m;
|
int m;
|
||||||
size_t outCount;
|
size_t outCount;
|
||||||
|
|
||||||
|
if (isFirstTime)
|
||||||
|
iT64Build();
|
||||||
|
|
||||||
|
n = InCount / 4;
|
||||||
|
m = InCount % 4;
|
||||||
|
|
||||||
if (isFirstTime) iT64Build();
|
|
||||||
n = InCount/4;
|
|
||||||
m = InCount%4;
|
|
||||||
if (InCount && !m)
|
if (InCount && !m)
|
||||||
outCount = 3*n;
|
outCount = 3 * n;
|
||||||
else {
|
else
|
||||||
outCount = 0;
|
{
|
||||||
return 0;
|
outCount = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ps = (unsigned char *)(InBuffer + InCount - 1);
|
ps = (unsigned char *)(InBuffer + InCount - 1);
|
||||||
while ( *ps-- == P64 ) outCount--;
|
while ( *ps-- == P64 )
|
||||||
|
outCount--;
|
||||||
ps = (unsigned char *)InBuffer;
|
ps = (unsigned char *)InBuffer;
|
||||||
|
|
||||||
if (outCount > len) return -1;
|
if (outCount > len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
pd = OutBuffer;
|
pd = OutBuffer;
|
||||||
auto endOfOutBuffer = OutBuffer + outCount;
|
auto endOfOutBuffer = OutBuffer + outCount;
|
||||||
for ( i = 0; i < n; i++ ){
|
for ( i = 0; i < n; i++ )
|
||||||
acc_1 = iT64[*ps++];
|
{
|
||||||
acc_2 = iT64[*ps++];
|
acc_1 = iT64[*ps++];
|
||||||
acc_1 <<= 2;
|
acc_2 = iT64[*ps++];
|
||||||
acc_1 |= acc_2>>4;
|
acc_1 <<= 2;
|
||||||
*pd++ = acc_1;
|
acc_1 |= acc_2 >> 4;
|
||||||
if (pd >= endOfOutBuffer) break;
|
*pd++ = acc_1;
|
||||||
|
if (pd >= endOfOutBuffer)
|
||||||
|
break;
|
||||||
|
|
||||||
acc_2 <<= 4;
|
acc_2 <<= 4;
|
||||||
acc_1 = iT64[*ps++];
|
acc_1 = iT64[*ps++];
|
||||||
acc_2 |= acc_1 >> 2;
|
acc_2 |= acc_1 >> 2;
|
||||||
*pd++ = acc_2;
|
*pd++ = acc_2;
|
||||||
if (pd >= endOfOutBuffer) break;
|
if (pd >= endOfOutBuffer)
|
||||||
|
break;
|
||||||
|
|
||||||
acc_2 = iT64[*ps++];
|
acc_2 = iT64[*ps++];
|
||||||
acc_2 |= acc_1 << 6;
|
acc_2 |= acc_1 << 6;
|
||||||
*pd++ = acc_2;
|
*pd++ = acc_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return outCount;
|
return outCount;
|
||||||
|
@ -206,20 +220,25 @@ namespace data
|
||||||
size_t Base64EncodingBufferSize (const size_t input_size)
|
size_t Base64EncodingBufferSize (const size_t input_size)
|
||||||
{
|
{
|
||||||
auto d = div (input_size, 3);
|
auto d = div (input_size, 3);
|
||||||
if (d.rem) d.quot++;
|
if (d.rem)
|
||||||
return 4*d.quot;
|
d.quot++;
|
||||||
|
|
||||||
|
return 4 * d.quot;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ToBase64Standard (const std::string& in)
|
std::string ToBase64Standard (const std::string& in)
|
||||||
{
|
{
|
||||||
auto len = Base64EncodingBufferSize (in.length ());
|
auto len = Base64EncodingBufferSize (in.length ());
|
||||||
char * str = new char[len+1];
|
char * str = new char[len + 1];
|
||||||
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
|
auto l = ByteStreamToBase64 ((const uint8_t *)in.c_str (), in.length (), str, len);
|
||||||
str[l] = 0;
|
str[l] = 0;
|
||||||
// replace '-' by '+' and '~' by '/'
|
// replace '-' by '+' and '~' by '/'
|
||||||
for (size_t i = 0; i < l; i++)
|
for (size_t i = 0; i < l; i++)
|
||||||
if (str[i] == '-') str[i] = '+';
|
if (str[i] == '-')
|
||||||
else if (str[i] == '~') str[i] = '/';
|
str[i] = '+';
|
||||||
|
else if (str[i] == '~')
|
||||||
|
str[i] = '/';
|
||||||
|
|
||||||
std::string s(str);
|
std::string s(str);
|
||||||
delete[] str;
|
delete[] str;
|
||||||
return s;
|
return s;
|
||||||
|
@ -236,10 +255,10 @@ namespace data
|
||||||
|
|
||||||
static void iT64Build()
|
static void iT64Build()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
isFirstTime = 0;
|
isFirstTime = 0;
|
||||||
for ( i=0; i<256; i++ ) iT64[i] = -1;
|
for ( i = 0; i < 256; i++ ) iT64[i] = -1;
|
||||||
for ( i=0; i<64; i++ ) iT64[(int)T64[i]] = i;
|
for ( i = 0; i < 64; i++ ) iT64[(int)T64[i]] = i;
|
||||||
iT64[(int)P64] = 0;
|
iT64[(int)P64] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,4 +321,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,13 +15,13 @@ namespace data {
|
||||||
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
|
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
|
||||||
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
|
||||||
*/
|
*/
|
||||||
size_t Base64EncodingBufferSize(const size_t input_size);
|
size_t Base64EncodingBufferSize(const size_t input_size);
|
||||||
|
|
||||||
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -17,21 +17,21 @@ namespace i2p
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
static EC_POINT * BlindPublicKeyECDSA (const EC_GROUP * group, const EC_POINT * pub, const uint8_t * seed)
|
static EC_POINT * BlindPublicKeyECDSA (const EC_GROUP * group, const EC_POINT * pub, const uint8_t * seed)
|
||||||
{
|
{
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
BIGNUM * q = BN_CTX_get (ctx);
|
BIGNUM * q = BN_CTX_get (ctx);
|
||||||
EC_GROUP_get_order (group, q, ctx);
|
EC_GROUP_get_order (group, q, ctx);
|
||||||
// calculate alpha = seed mod q
|
// calculate alpha = seed mod q
|
||||||
BIGNUM * alpha = BN_CTX_get (ctx);
|
BIGNUM * alpha = BN_CTX_get (ctx);
|
||||||
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
|
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
|
||||||
BN_mod (alpha, alpha, q, ctx); // % q
|
BN_mod (alpha, alpha, q, ctx); // % q
|
||||||
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
|
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
|
||||||
auto p = EC_POINT_new (group);
|
auto p = EC_POINT_new (group);
|
||||||
EC_POINT_mul (group, p, alpha, nullptr, nullptr, ctx); // B*alpha
|
EC_POINT_mul (group, p, alpha, nullptr, nullptr, ctx); // B*alpha
|
||||||
EC_POINT_add (group, p, pub, p, ctx); // pub + B*alpha
|
EC_POINT_add (group, p, pub, p, ctx); // pub + B*alpha
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,18 +39,18 @@ namespace data
|
||||||
{
|
{
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
BIGNUM * q = BN_CTX_get (ctx);
|
BIGNUM * q = BN_CTX_get (ctx);
|
||||||
EC_GROUP_get_order (group, q, ctx);
|
EC_GROUP_get_order (group, q, ctx);
|
||||||
// calculate alpha = seed mod q
|
// calculate alpha = seed mod q
|
||||||
BIGNUM * alpha = BN_CTX_get (ctx);
|
BIGNUM * alpha = BN_CTX_get (ctx);
|
||||||
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
|
BN_bin2bn (seed, 64, alpha); // seed is in BigEndian
|
||||||
BN_mod (alpha, alpha, q, ctx); // % q
|
BN_mod (alpha, alpha, q, ctx); // % q
|
||||||
BN_add (alpha, alpha, priv); // alpha = alpha + priv
|
BN_add (alpha, alpha, priv); // alpha = alpha + priv
|
||||||
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q
|
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod q
|
||||||
BN_mod (blindedPriv, alpha, q, ctx); // % q
|
BN_mod (blindedPriv, alpha, q, ctx); // % q
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BlindEncodedPublicKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * pub, const uint8_t * seed, uint8_t * blindedPub)
|
static void BlindEncodedPublicKeyECDSA (size_t publicKeyLen, const EC_GROUP * group, const uint8_t * pub, const uint8_t * seed, uint8_t * blindedPub)
|
||||||
{
|
{
|
||||||
|
@ -63,7 +63,7 @@ namespace data
|
||||||
EC_POINT_get_affine_coordinates_GFp (group, p1, x, y, NULL);
|
EC_POINT_get_affine_coordinates_GFp (group, p1, x, y, NULL);
|
||||||
EC_POINT_free (p1);
|
EC_POINT_free (p1);
|
||||||
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
|
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
|
||||||
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
|
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
|
||||||
BN_free (x); BN_free (y);
|
BN_free (x); BN_free (y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace data
|
||||||
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
|
i2p::crypto::bn2buf (x, blindedPub, publicKeyLen/2);
|
||||||
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
|
i2p::crypto::bn2buf (y, blindedPub + publicKeyLen/2, publicKeyLen/2);
|
||||||
BN_free (x); BN_free (y);
|
BN_free (x); BN_free (y);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Fn, typename...Args>
|
template<typename Fn, typename...Args>
|
||||||
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
|
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
|
||||||
|
@ -97,7 +97,7 @@ namespace data
|
||||||
{
|
{
|
||||||
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
|
case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
|
||||||
{
|
{
|
||||||
publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH;
|
publicKeyLength = i2p::crypto::ECDSAP256_KEY_LENGTH;
|
||||||
group = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
|
group = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -116,18 +116,18 @@ namespace data
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA");
|
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA");
|
||||||
}
|
}
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
blind (publicKeyLength, group, key, seed, std::forward<Args>(args)...);
|
blind (publicKeyLength, group, key, seed, std::forward<Args>(args)...);
|
||||||
EC_GROUP_free (group);
|
EC_GROUP_free (group);
|
||||||
}
|
}
|
||||||
return publicKeyLength;
|
return publicKeyLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
|
||||||
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
|
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
|
||||||
const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
|
const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
|
||||||
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
|
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
|
||||||
|
|
||||||
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
|
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
|
||||||
|
@ -138,7 +138,7 @@ namespace data
|
||||||
m_PublicKey.resize (len);
|
m_PublicKey.resize (len);
|
||||||
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
|
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
|
||||||
m_SigType = identity->GetSigningKeyType ();
|
m_SigType = identity->GetSigningKeyType ();
|
||||||
m_BlindedSigType = m_SigType;
|
m_BlindedSigType = m_SigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
|
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
|
||||||
|
@ -150,12 +150,12 @@ namespace data
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Blinding: malformed b33 ", b33);
|
LogPrint (eLogError, "Blinding: malformed b33 ", b33);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t checksum = crc32 (0, addr + 3, l - 3);
|
uint32_t checksum = crc32 (0, addr + 3, l - 3);
|
||||||
// checksum is Little Endian
|
// checksum is Little Endian
|
||||||
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
|
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
|
||||||
uint8_t flags = addr[0];
|
uint8_t flags = addr[0];
|
||||||
size_t offset = 1;
|
size_t offset = 1;
|
||||||
if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
|
if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
|
||||||
{
|
{
|
||||||
m_SigType = bufbe16toh (addr + offset); offset += 2;
|
m_SigType = bufbe16toh (addr + offset); offset += 2;
|
||||||
|
@ -178,7 +178,7 @@ namespace data
|
||||||
memcpy (m_PublicKey.data (), addr + offset, len);
|
memcpy (m_PublicKey.data (), addr + offset, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType);
|
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33");
|
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33");
|
||||||
|
@ -189,25 +189,25 @@ namespace data
|
||||||
if (m_PublicKey.size () > 32) return ""; // assume 25519
|
if (m_PublicKey.size () > 32) return ""; // assume 25519
|
||||||
uint8_t addr[35]; char str[60]; // TODO: define actual length
|
uint8_t addr[35]; char str[60]; // TODO: define actual length
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
|
if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
|
||||||
addr[0] = flags; // flags
|
addr[0] = flags; // flags
|
||||||
addr[1] = m_SigType; // sig type
|
addr[1] = m_SigType; // sig type
|
||||||
addr[2] = m_BlindedSigType; // blinded sig type
|
addr[2] = m_BlindedSigType; // blinded sig type
|
||||||
memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());
|
memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());
|
||||||
uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ());
|
uint32_t checksum = crc32 (0, addr + 3, m_PublicKey.size ());
|
||||||
// checksum is Little Endian
|
// checksum is Little Endian
|
||||||
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
|
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
|
||||||
auto l = ByteStreamToBase32 (addr, m_PublicKey.size () + 3, str, 60);
|
auto l = ByteStreamToBase32 (addr, m_PublicKey.size () + 3, str, 60);
|
||||||
return std::string (str, str + l);
|
return std::string (str, str + l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlindedPublicKey::GetCredential (uint8_t * credential) const
|
void BlindedPublicKey::GetCredential (uint8_t * credential) const
|
||||||
{
|
{
|
||||||
// A = destination's signing public key
|
// A = destination's signing public key
|
||||||
// stA = signature type of A, 2 bytes big endian
|
// stA = signature type of A, 2 bytes big endian
|
||||||
uint16_t stA = htobe16 (GetSigType ());
|
uint16_t stA = htobe16 (GetSigType ());
|
||||||
// stA1 = signature type of blinded A, 2 bytes big endian
|
// stA1 = signature type of blinded A, 2 bytes big endian
|
||||||
uint16_t stA1 = htobe16 (GetBlindedSigType ());
|
uint16_t stA1 = htobe16 (GetBlindedSigType ());
|
||||||
// credential = H("credential", A || stA || stA1)
|
// credential = H("credential", A || stA || stA1)
|
||||||
H ("credential", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, credential);
|
H ("credential", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, credential);
|
||||||
}
|
}
|
||||||
|
@ -224,15 +224,15 @@ namespace data
|
||||||
{
|
{
|
||||||
uint16_t stA = htobe16 (GetSigType ()), stA1 = htobe16 (GetBlindedSigType ());
|
uint16_t stA = htobe16 (GetSigType ()), stA1 = htobe16 (GetBlindedSigType ());
|
||||||
uint8_t salt[32];
|
uint8_t salt[32];
|
||||||
//seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64)
|
//seed = HKDF(H("I2PGenerateAlpha", keydata), datestring || secret, "i2pblinding1", 64)
|
||||||
H ("I2PGenerateAlpha", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt);
|
H ("I2PGenerateAlpha", { {GetPublicKey (), GetPublicKeyLen ()}, {(const uint8_t *)&stA, 2}, {(const uint8_t *)&stA1, 2} }, salt);
|
||||||
i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed);
|
i2p::crypto::HKDF (salt, (const uint8_t *)date, 8, "i2pblinding1", seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t BlindedPublicKey::GetBlindedKey (const char * date, uint8_t * blindedKey) const
|
size_t BlindedPublicKey::GetBlindedKey (const char * date, uint8_t * blindedKey) const
|
||||||
{
|
{
|
||||||
uint8_t seed[64];
|
uint8_t seed[64];
|
||||||
GenerateAlpha (date, seed);
|
GenerateAlpha (date, seed);
|
||||||
|
|
||||||
size_t publicKeyLength = 0;
|
size_t publicKeyLength = 0;
|
||||||
switch (m_SigType)
|
switch (m_SigType)
|
||||||
|
@ -244,7 +244,7 @@ namespace data
|
||||||
break;
|
break;
|
||||||
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
case i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey);
|
i2p::crypto::GetEd25519 ()->BlindPublicKey (GetPublicKey (), seed, blindedKey);
|
||||||
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
|
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -255,8 +255,8 @@ namespace data
|
||||||
|
|
||||||
size_t BlindedPublicKey::BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const
|
size_t BlindedPublicKey::BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const
|
||||||
{
|
{
|
||||||
uint8_t seed[64];
|
uint8_t seed[64];
|
||||||
GenerateAlpha (date, seed);
|
GenerateAlpha (date, seed);
|
||||||
size_t publicKeyLength = 0;
|
size_t publicKeyLength = 0;
|
||||||
switch (m_SigType)
|
switch (m_SigType)
|
||||||
{
|
{
|
||||||
|
@ -272,15 +272,15 @@ namespace data
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
|
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
|
||||||
}
|
}
|
||||||
return publicKeyLength;
|
return publicKeyLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlindedPublicKey::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const
|
void BlindedPublicKey::H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const
|
||||||
{
|
{
|
||||||
SHA256_CTX ctx;
|
SHA256_CTX ctx;
|
||||||
SHA256_Init (&ctx);
|
SHA256_Init (&ctx);
|
||||||
SHA256_Update (&ctx, p.c_str (), p.length ());
|
SHA256_Update (&ctx, p.c_str (), p.length ());
|
||||||
for (const auto& it: bufs)
|
for (const auto& it: bufs)
|
||||||
SHA256_Update (&ctx, it.first, it.second);
|
SHA256_Update (&ctx, it.first, it.second);
|
||||||
SHA256_Final (hash, &ctx);
|
SHA256_Final (hash, &ctx);
|
||||||
}
|
}
|
||||||
|
@ -289,15 +289,15 @@ namespace data
|
||||||
{
|
{
|
||||||
i2p::data::IdentHash hash;
|
i2p::data::IdentHash hash;
|
||||||
uint8_t blinded[128];
|
uint8_t blinded[128];
|
||||||
size_t publicKeyLength = 0;
|
size_t publicKeyLength = 0;
|
||||||
if (date)
|
if (date)
|
||||||
publicKeyLength = GetBlindedKey (date, blinded);
|
publicKeyLength = GetBlindedKey (date, blinded);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char currentDate[9];
|
char currentDate[9];
|
||||||
i2p::util::GetCurrentDate (currentDate);
|
i2p::util::GetCurrentDate (currentDate);
|
||||||
publicKeyLength = GetBlindedKey (currentDate, blinded);
|
publicKeyLength = GetBlindedKey (currentDate, blinded);
|
||||||
}
|
}
|
||||||
if (publicKeyLength)
|
if (publicKeyLength)
|
||||||
{
|
{
|
||||||
auto stA1 = htobe16 (m_BlindedSigType);
|
auto stA1 = htobe16 (m_BlindedSigType);
|
||||||
|
@ -308,10 +308,9 @@ namespace data
|
||||||
SHA256_Final ((uint8_t *)hash, &ctx);
|
SHA256_Final ((uint8_t *)hash, &ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported");
|
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported");
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace data
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
|
BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
|
||||||
BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p
|
BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p
|
||||||
std::string ToB33 () const;
|
std::string ToB33 () const;
|
||||||
|
|
||||||
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
|
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
|
||||||
|
@ -25,14 +25,14 @@ namespace data
|
||||||
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
|
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
|
||||||
|
|
||||||
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
|
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
|
||||||
size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length
|
size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length
|
||||||
size_t BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const; // date is 8 chars "YYYYMMDD", return public key length
|
size_t BlindPrivateKey (const uint8_t * priv, const char * date, uint8_t * blindedPriv, uint8_t * blindedPub) const; // date is 8 chars "YYYYMMDD", return public key length
|
||||||
i2p::data::IdentHash GetStoreHash (const char * date = nullptr) const; // date is 8 chars "YYYYMMDD", use current if null
|
i2p::data::IdentHash GetStoreHash (const char * date = nullptr) const; // date is 8 chars "YYYYMMDD", use current if null
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void GetCredential (uint8_t * credential) const; // 32 bytes
|
void GetCredential (uint8_t * credential) const; // 32 bytes
|
||||||
void GenerateAlpha (const char * date, uint8_t * seed) const; // 64 bytes, date is 8 chars "YYYYMMDD"
|
void GenerateAlpha (const char * date, uint8_t * seed) const; // 64 bytes, date is 8 chars "YYYYMMDD"
|
||||||
void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const;
|
void H (const std::string& p, const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * hash) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,10 +5,10 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace cpu
|
namespace cpu
|
||||||
{
|
{
|
||||||
extern bool aesni;
|
extern bool aesni;
|
||||||
extern bool avx;
|
extern bool avx;
|
||||||
|
|
||||||
void Detect();
|
void Detect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,73 +12,72 @@
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "ChaCha20.h"
|
#include "ChaCha20.h"
|
||||||
|
|
||||||
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
namespace chacha
|
namespace chacha
|
||||||
{
|
{
|
||||||
void u32t8le(uint32_t v, uint8_t * p)
|
void u32t8le(uint32_t v, uint8_t * p)
|
||||||
{
|
{
|
||||||
p[0] = v & 0xff;
|
p[0] = v & 0xff;
|
||||||
p[1] = (v >> 8) & 0xff;
|
p[1] = (v >> 8) & 0xff;
|
||||||
p[2] = (v >> 16) & 0xff;
|
p[2] = (v >> 16) & 0xff;
|
||||||
p[3] = (v >> 24) & 0xff;
|
p[3] = (v >> 24) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t u8t32le(const uint8_t * p)
|
uint32_t u8t32le(const uint8_t * p)
|
||||||
{
|
{
|
||||||
uint32_t value = p[3];
|
uint32_t value = p[3];
|
||||||
|
|
||||||
value = (value << 8) | p[2];
|
value = (value << 8) | p[2];
|
||||||
value = (value << 8) | p[1];
|
value = (value << 8) | p[1];
|
||||||
value = (value << 8) | p[0];
|
value = (value << 8) | p[0];
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rotl32(uint32_t x, int n)
|
uint32_t rotl32(uint32_t x, int n)
|
||||||
{
|
{
|
||||||
return x << n | (x >> (-n & 31));
|
return x << n | (x >> (-n & 31));
|
||||||
}
|
}
|
||||||
|
|
||||||
void quarterround(uint32_t *x, int a, int b, int c, int d)
|
void quarterround(uint32_t *x, int a, int b, int c, int d)
|
||||||
{
|
{
|
||||||
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16);
|
||||||
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12);
|
||||||
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
|
x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8);
|
||||||
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Chacha20Block::operator << (const Chacha20State & st)
|
void Chacha20Block::operator << (const Chacha20State & st)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
u32t8le(st.data[i], data + (i << 2));
|
u32t8le(st.data[i], data + (i << 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void block (Chacha20State &input, int rounds)
|
void block (Chacha20State &input, int rounds)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Chacha20State x;
|
Chacha20State x;
|
||||||
x.Copy(input);
|
x.Copy(input);
|
||||||
|
|
||||||
for (i = rounds; i > 0; i -= 2)
|
|
||||||
{
|
|
||||||
quarterround(x.data, 0, 4, 8, 12);
|
|
||||||
quarterround(x.data, 1, 5, 9, 13);
|
|
||||||
quarterround(x.data, 2, 6, 10, 14);
|
|
||||||
quarterround(x.data, 3, 7, 11, 15);
|
|
||||||
quarterround(x.data, 0, 5, 10, 15);
|
|
||||||
quarterround(x.data, 1, 6, 11, 12);
|
|
||||||
quarterround(x.data, 2, 7, 8, 13);
|
|
||||||
quarterround(x.data, 3, 4, 9, 14);
|
|
||||||
}
|
|
||||||
x += input;
|
|
||||||
input.block << x;
|
|
||||||
|
|
||||||
|
for (i = rounds; i > 0; i -= 2)
|
||||||
|
{
|
||||||
|
quarterround(x.data, 0, 4, 8, 12);
|
||||||
|
quarterround(x.data, 1, 5, 9, 13);
|
||||||
|
quarterround(x.data, 2, 6, 10, 14);
|
||||||
|
quarterround(x.data, 3, 7, 11, 15);
|
||||||
|
quarterround(x.data, 0, 5, 10, 15);
|
||||||
|
quarterround(x.data, 1, 6, 11, 12);
|
||||||
|
quarterround(x.data, 2, 7, 8, 13);
|
||||||
|
quarterround(x.data, 3, 4, 9, 14);
|
||||||
|
}
|
||||||
|
x += input;
|
||||||
|
input.block << x;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter)
|
||||||
|
@ -87,52 +86,52 @@ void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t *
|
||||||
state.data[1] = 0x3320646e;
|
state.data[1] = 0x3320646e;
|
||||||
state.data[2] = 0x79622d32;
|
state.data[2] = 0x79622d32;
|
||||||
state.data[3] = 0x6b206574;
|
state.data[3] = 0x6b206574;
|
||||||
for (size_t i = 0; i < 8; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
state.data[4 + i] = chacha::u8t32le(key + i * 4);
|
||||||
|
|
||||||
state.data[12] = htole32 (counter);
|
state.data[12] = htole32 (counter);
|
||||||
for (size_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < 3; i++)
|
||||||
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
state.data[13 + i] = chacha::u8t32le(nonce + i * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
|
void Chacha20SetCounter (Chacha20State& state, uint32_t counter)
|
||||||
{
|
{
|
||||||
state.data[12] = htole32 (counter);
|
state.data[12] = htole32 (counter);
|
||||||
state.offset = 0;
|
state.offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz)
|
||||||
{
|
{
|
||||||
if (state.offset > 0)
|
if (state.offset > 0)
|
||||||
{
|
{
|
||||||
// previous block if any
|
// previous block if any
|
||||||
auto s = chacha::blocksize - state.offset;
|
auto s = chacha::blocksize - state.offset;
|
||||||
if (sz < s) s = sz;
|
if (sz < s) s = sz;
|
||||||
for (size_t i = 0; i < s; i++)
|
for (size_t i = 0; i < s; i++)
|
||||||
buf[i] ^= state.block.data[state.offset + i];
|
buf[i] ^= state.block.data[state.offset + i];
|
||||||
buf += s;
|
buf += s;
|
||||||
sz -= s;
|
sz -= s;
|
||||||
state.offset += s;
|
state.offset += s;
|
||||||
if (state.offset >= chacha::blocksize) state.offset = 0;
|
if (state.offset >= chacha::blocksize) state.offset = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < sz; i += chacha::blocksize)
|
for (size_t i = 0; i < sz; i += chacha::blocksize)
|
||||||
{
|
{
|
||||||
chacha::block(state, chacha::rounds);
|
chacha::block(state, chacha::rounds);
|
||||||
state.data[12]++;
|
state.data[12]++;
|
||||||
for (size_t j = i; j < i + chacha::blocksize; j++)
|
for (size_t j = i; j < i + chacha::blocksize; j++)
|
||||||
{
|
{
|
||||||
if (j >= sz)
|
if (j >= sz)
|
||||||
{
|
{
|
||||||
state.offset = j & 0x3F; // % 64
|
state.offset = j & 0x3F; // % 64
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf[j] ^= state.block.data[j - i];
|
buf[j] ^= state.block.data[j - i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace chacha
|
} // namespace chacha
|
||||||
|
} // namespace crypto
|
||||||
|
} // namespace i2p
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -21,23 +21,23 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
const std::size_t CHACHA20_KEY_BYTES = 32;
|
const std::size_t CHACHA20_KEY_BYTES = 32;
|
||||||
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
const std::size_t CHACHA20_NOUNCE_BYTES = 12;
|
||||||
|
|
||||||
namespace chacha
|
namespace chacha
|
||||||
{
|
{
|
||||||
constexpr std::size_t blocksize = 64;
|
constexpr std::size_t blocksize = 64;
|
||||||
constexpr int rounds = 20;
|
constexpr int rounds = 20;
|
||||||
|
|
||||||
struct Chacha20State;
|
struct Chacha20State;
|
||||||
struct Chacha20Block
|
struct Chacha20Block
|
||||||
{
|
{
|
||||||
Chacha20Block () {};
|
Chacha20Block () {};
|
||||||
Chacha20Block (Chacha20Block &&) = delete;
|
Chacha20Block (Chacha20Block &&) = delete;
|
||||||
|
|
||||||
uint8_t data[blocksize];
|
uint8_t data[blocksize];
|
||||||
|
|
||||||
void operator << (const Chacha20State & st);
|
void operator << (const Chacha20State & st);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Chacha20State
|
struct Chacha20State
|
||||||
|
@ -54,19 +54,19 @@ namespace chacha
|
||||||
|
|
||||||
void Copy(const Chacha20State & other)
|
void Copy(const Chacha20State & other)
|
||||||
{
|
{
|
||||||
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
memcpy(data, other.data, sizeof(uint32_t) * 16);
|
||||||
}
|
}
|
||||||
uint32_t data[16];
|
uint32_t data[16];
|
||||||
Chacha20Block block;
|
Chacha20Block block;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
void Chacha20Init (Chacha20State& state, const uint8_t * nonce, const uint8_t * key, uint32_t counter);
|
||||||
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
|
void Chacha20SetCounter (Chacha20State& state, uint32_t counter);
|
||||||
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
|
void Chacha20Encrypt (Chacha20State& state, uint8_t * buf, size_t sz); // encrypt buf in place
|
||||||
}
|
} // namespace chacha
|
||||||
}
|
} // namespace crypto
|
||||||
}
|
} // namespace i2p
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -242,7 +242,7 @@ namespace config {
|
||||||
"1.pool.ntp.org,"
|
"1.pool.ntp.org,"
|
||||||
"2.pool.ntp.org,"
|
"2.pool.ntp.org,"
|
||||||
"3.pool.ntp.org"
|
"3.pool.ntp.org"
|
||||||
), "Comma separated list of NTCP servers")
|
), "Comma separated list of NTCP servers")
|
||||||
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
|
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
169
libi2pd/Config.h
169
libi2pd/Config.h
|
@ -18,98 +18,101 @@
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace config {
|
namespace config {
|
||||||
extern boost::program_options::variables_map m_Options;
|
extern boost::program_options::variables_map m_Options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize list of acceptable parameters
|
* @brief Initialize list of acceptable parameters
|
||||||
*
|
*
|
||||||
* Should be called before any Parse* functions.
|
* Should be called before any Parse* functions.
|
||||||
*/
|
*/
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parse cmdline parameters, and show help if requested
|
* @brief Parse cmdline parameters, and show help if requested
|
||||||
* @param argc Cmdline arguments count, should be passed from main().
|
* @param argc Cmdline arguments count, should be passed from main().
|
||||||
* @param argv Cmdline parameters array, should be passed from main()
|
* @param argv Cmdline parameters array, should be passed from main()
|
||||||
*
|
*
|
||||||
* If --help is given in parameters, shows its list with description
|
* If --help is given in parameters, shows its list with description
|
||||||
* and terminates the program with exitcode 0.
|
* and terminates the program with exitcode 0.
|
||||||
*
|
*
|
||||||
* In case of parameter misuse boost throws an exception.
|
* In case of parameter misuse boost throws an exception.
|
||||||
* We internally handle type boost::program_options::unknown_option,
|
* We internally handle type boost::program_options::unknown_option,
|
||||||
* and then terminate the program with exitcode 1.
|
* and then terminate the program with exitcode 1.
|
||||||
*
|
*
|
||||||
* Other exceptions will be passed to higher level.
|
* Other exceptions will be passed to higher level.
|
||||||
*/
|
*/
|
||||||
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
|
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load and parse given config file
|
* @brief Load and parse given config file
|
||||||
* @param path Path to config file
|
* @param path Path to config file
|
||||||
*
|
*
|
||||||
* If error occurred when opening file path is points to,
|
* If error occurred when opening file path is points to,
|
||||||
* we show the error message and terminate program.
|
* we show the error message and terminate program.
|
||||||
*
|
*
|
||||||
* In case of parameter misuse boost throws an exception.
|
* In case of parameter misuse boost throws an exception.
|
||||||
* We internally handle type boost::program_options::unknown_option,
|
* We internally handle type boost::program_options::unknown_option,
|
||||||
* and then terminate program with exitcode 1.
|
* and then terminate program with exitcode 1.
|
||||||
*
|
*
|
||||||
* Other exceptions will be passed to higher level.
|
* Other exceptions will be passed to higher level.
|
||||||
*/
|
*/
|
||||||
void ParseConfig(const std::string& path);
|
void ParseConfig(const std::string& path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Used to combine options from cmdline, config and default values
|
* @brief Used to combine options from cmdline, config and default values
|
||||||
*/
|
*/
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
/* @brief Accessor to parameters by name
|
/**
|
||||||
* @param name Name of the requested parameter
|
* @brief Accessor to parameters by name
|
||||||
* @param value Variable where to store option
|
* @param name Name of the requested parameter
|
||||||
* @return this function returns false if parameter not found
|
* @param value Variable where to store option
|
||||||
*
|
* @return this function returns false if parameter not found
|
||||||
* Example: uint16_t port; GetOption("sam.port", port);
|
*
|
||||||
*/
|
* Example: uint16_t port; GetOption("sam.port", port);
|
||||||
template<typename T>
|
*/
|
||||||
bool GetOption(const char *name, T& value) {
|
template<typename T>
|
||||||
if (!m_Options.count(name))
|
bool GetOption(const char *name, T& value)
|
||||||
return false;
|
{
|
||||||
value = m_Options[name].as<T>();
|
if (!m_Options.count(name))
|
||||||
return true;
|
return false;
|
||||||
}
|
value = m_Options[name].as<T>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool GetOption(const std::string& name, T& value)
|
bool GetOption(const std::string& name, T& value)
|
||||||
{
|
{
|
||||||
return GetOption (name.c_str (), value);
|
return GetOption (name.c_str (), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetOptionAsAny(const char *name, boost::any& value);
|
bool GetOptionAsAny(const char *name, boost::any& value);
|
||||||
bool GetOptionAsAny(const std::string& name, boost::any& value);
|
bool GetOptionAsAny(const std::string& name, boost::any& value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set value of given parameter
|
* @brief Set value of given parameter
|
||||||
* @param name Name of settable parameter
|
* @param name Name of settable parameter
|
||||||
* @param value New parameter value
|
* @param value New parameter value
|
||||||
* @return true if value set up successful, false otherwise
|
* @return true if value set up successful, false otherwise
|
||||||
*
|
*
|
||||||
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool SetOption(const char *name, const T& value) {
|
bool SetOption(const char *name, const T& value)
|
||||||
if (!m_Options.count(name))
|
{
|
||||||
return false;
|
if (!m_Options.count(name))
|
||||||
m_Options.at(name).value() = value;
|
return false;
|
||||||
notify(m_Options);
|
m_Options.at(name).value() = value;
|
||||||
return true;
|
notify(m_Options);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check is value explicitly given or default
|
* @brief Check is value explicitly given or default
|
||||||
* @param name Name of checked parameter
|
* @param name Name of checked parameter
|
||||||
* @return true if value set to default, false otherwise
|
* @return true if value set to default, false otherwise
|
||||||
*/
|
*/
|
||||||
bool IsDefault(const char *name);
|
bool IsDefault(const char *name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,14 +286,14 @@ namespace crypto
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
|
m_Ctx = EVP_PKEY_CTX_new_id (NID_X25519, NULL);
|
||||||
m_Pkey = nullptr;
|
m_Pkey = nullptr;
|
||||||
#else
|
#else
|
||||||
m_Ctx = BN_CTX_new ();
|
m_Ctx = BN_CTX_new ();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
|
X25519Keys::X25519Keys (const uint8_t * priv, const uint8_t * pub)
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
||||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||||
if (pub)
|
if (pub)
|
||||||
|
@ -302,33 +302,33 @@ namespace crypto
|
||||||
{
|
{
|
||||||
size_t len = 32;
|
size_t len = 32;
|
||||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
m_Ctx = BN_CTX_new ();
|
m_Ctx = BN_CTX_new ();
|
||||||
memcpy (m_PrivateKey, priv, 32);
|
memcpy (m_PrivateKey, priv, 32);
|
||||||
if (pub)
|
if (pub)
|
||||||
memcpy (m_PublicKey, pub, 32);
|
memcpy (m_PublicKey, pub, 32);
|
||||||
else
|
else
|
||||||
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
X25519Keys::~X25519Keys ()
|
X25519Keys::~X25519Keys ()
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
EVP_PKEY_CTX_free (m_Ctx);
|
EVP_PKEY_CTX_free (m_Ctx);
|
||||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||||
#else
|
#else
|
||||||
BN_CTX_free (m_Ctx);
|
BN_CTX_free (m_Ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void X25519Keys::GenerateKeys ()
|
void X25519Keys::GenerateKeys ()
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
if (m_Pkey)
|
if (m_Pkey)
|
||||||
{
|
{
|
||||||
EVP_PKEY_free (m_Pkey);
|
EVP_PKEY_free (m_Pkey);
|
||||||
m_Pkey = nullptr;
|
m_Pkey = nullptr;
|
||||||
}
|
}
|
||||||
EVP_PKEY_keygen_init (m_Ctx);
|
EVP_PKEY_keygen_init (m_Ctx);
|
||||||
|
@ -337,26 +337,26 @@ namespace crypto
|
||||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
|
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); // TODO: do we really need to re-create m_Ctx?
|
||||||
size_t len = 32;
|
size_t len = 32;
|
||||||
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len);
|
||||||
#else
|
#else
|
||||||
RAND_bytes (m_PrivateKey, 32);
|
RAND_bytes (m_PrivateKey, 32);
|
||||||
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
|
void X25519Keys::Agree (const uint8_t * pub, uint8_t * shared)
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
EVP_PKEY_derive_init (m_Ctx);
|
EVP_PKEY_derive_init (m_Ctx);
|
||||||
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
|
auto pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_X25519, NULL, pub, 32);
|
||||||
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
|
EVP_PKEY_derive_set_peer (m_Ctx, pkey);
|
||||||
size_t len = 32;
|
size_t len = 32;
|
||||||
EVP_PKEY_derive (m_Ctx, shared, &len);
|
EVP_PKEY_derive (m_Ctx, shared, &len);
|
||||||
EVP_PKEY_free (pkey);
|
EVP_PKEY_free (pkey);
|
||||||
#else
|
#else
|
||||||
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
|
GetEd25519 ()->ScalarMul (pub, m_PrivateKey, shared, m_Ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void X25519Keys::GetPrivateKey (uint8_t * priv) const
|
void X25519Keys::GetPrivateKey (uint8_t * priv) const
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
|
@ -369,14 +369,14 @@ namespace crypto
|
||||||
|
|
||||||
void X25519Keys::SetPrivateKey (const uint8_t * priv)
|
void X25519Keys::SetPrivateKey (const uint8_t * priv)
|
||||||
{
|
{
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
|
if (m_Ctx) EVP_PKEY_CTX_free (m_Ctx);
|
||||||
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
if (m_Pkey) EVP_PKEY_free (m_Pkey);
|
||||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32);
|
||||||
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL);
|
||||||
#else
|
#else
|
||||||
memcpy (m_PrivateKey, priv, 32);
|
memcpy (m_PrivateKey, priv, 32);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
|
@ -681,12 +681,12 @@ namespace crypto
|
||||||
|
|
||||||
// AES
|
// AES
|
||||||
#ifdef __AES__
|
#ifdef __AES__
|
||||||
#ifdef ARM64AES
|
#ifdef ARM64AES
|
||||||
void init_aesenc(void){
|
void init_aesenc(void){
|
||||||
// TODO: Implementation
|
// TODO: Implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define KeyExpansion256(round0,round1) \
|
#define KeyExpansion256(round0,round1) \
|
||||||
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
|
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
|
||||||
|
@ -884,7 +884,6 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
|
||||||
{
|
{
|
||||||
#ifdef __AES__
|
#ifdef __AES__
|
||||||
|
@ -1139,10 +1138,10 @@ namespace crypto
|
||||||
}
|
}
|
||||||
|
|
||||||
EVP_CIPHER_CTX_free (ctx);
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
#else
|
#else
|
||||||
chacha::Chacha20State state;
|
chacha::Chacha20State state;
|
||||||
// generate one time poly key
|
// generate one time poly key
|
||||||
chacha::Chacha20Init (state, nonce, key, 0);
|
chacha::Chacha20Init (state, nonce, key, 0);
|
||||||
uint64_t polyKey[8];
|
uint64_t polyKey[8];
|
||||||
memset(polyKey, 0, sizeof(polyKey));
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
||||||
|
@ -1158,7 +1157,7 @@ namespace crypto
|
||||||
{
|
{
|
||||||
// padding1
|
// padding1
|
||||||
rem = 16 - rem;
|
rem = 16 - rem;
|
||||||
polyHash.Update (padding, rem);
|
polyHash.Update (padding, rem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// encrypt/decrypt data and add to hash
|
// encrypt/decrypt data and add to hash
|
||||||
|
@ -1174,20 +1173,20 @@ namespace crypto
|
||||||
{
|
{
|
||||||
polyHash.Update (buf, msgLen); // before decryption
|
polyHash.Update (buf, msgLen); // before decryption
|
||||||
chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt
|
chacha::Chacha20Encrypt (state, buf, msgLen); // decrypt
|
||||||
}
|
}
|
||||||
|
|
||||||
auto rem = msgLen & 0x0F; // %16
|
auto rem = msgLen & 0x0F; // %16
|
||||||
if (rem)
|
if (rem)
|
||||||
{
|
{
|
||||||
// padding2
|
// padding2
|
||||||
rem = 16 - rem;
|
rem = 16 - rem;
|
||||||
polyHash.Update (padding, rem);
|
polyHash.Update (padding, rem);
|
||||||
}
|
}
|
||||||
// adLen and msgLen
|
// adLen and msgLen
|
||||||
htole64buf (padding, adLen);
|
htole64buf (padding, adLen);
|
||||||
htole64buf (padding + 8, msgLen);
|
htole64buf (padding + 8, msgLen);
|
||||||
polyHash.Update (padding, 16);
|
polyHash.Update (padding, 16);
|
||||||
|
|
||||||
if (encrypt)
|
if (encrypt)
|
||||||
// calculate Poly1305 tag and write in after encrypted data
|
// calculate Poly1305 tag and write in after encrypted data
|
||||||
polyHash.Finish ((uint64_t *)(buf + msgLen));
|
polyHash.Finish ((uint64_t *)(buf + msgLen));
|
||||||
|
@ -1195,7 +1194,7 @@ namespace crypto
|
||||||
{
|
{
|
||||||
uint64_t tag[4];
|
uint64_t tag[4];
|
||||||
// calculate Poly1305 tag
|
// calculate Poly1305 tag
|
||||||
polyHash.Finish (tag);
|
polyHash.Finish (tag);
|
||||||
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
|
if (memcmp (tag, msg + msgLen, 16)) ret = false; // compare with provided
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1211,20 +1210,20 @@ namespace crypto
|
||||||
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), 0, 0, 0);
|
||||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, 0);
|
||||||
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
|
||||||
for (const auto& it: bufs)
|
for (const auto& it: bufs)
|
||||||
EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second);
|
EVP_EncryptUpdate(ctx, it.first, &outlen, it.first, it.second);
|
||||||
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
EVP_EncryptFinal_ex(ctx, NULL, &outlen);
|
||||||
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, mac);
|
||||||
EVP_CIPHER_CTX_free (ctx);
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
#else
|
#else
|
||||||
chacha::Chacha20State state;
|
chacha::Chacha20State state;
|
||||||
// generate one time poly key
|
// generate one time poly key
|
||||||
chacha::Chacha20Init (state, nonce, key, 0);
|
chacha::Chacha20Init (state, nonce, key, 0);
|
||||||
uint64_t polyKey[8];
|
uint64_t polyKey[8];
|
||||||
memset(polyKey, 0, sizeof(polyKey));
|
memset(polyKey, 0, sizeof(polyKey));
|
||||||
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
chacha::Chacha20Encrypt (state, (uint8_t *)polyKey, 64);
|
||||||
Poly1305 polyHash (polyKey);
|
Poly1305 polyHash (polyKey);
|
||||||
// encrypt buffers
|
// encrypt buffers
|
||||||
Chacha20SetCounter (state, 1);
|
Chacha20SetCounter (state, 1);
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
for (const auto& it: bufs)
|
for (const auto& it: bufs)
|
||||||
|
@ -1234,22 +1233,22 @@ namespace crypto
|
||||||
size += it.second;
|
size += it.second;
|
||||||
}
|
}
|
||||||
// padding
|
// padding
|
||||||
uint8_t padding[16];
|
uint8_t padding[16];
|
||||||
memset (padding, 0, 16);
|
memset (padding, 0, 16);
|
||||||
auto rem = size & 0x0F; // %16
|
auto rem = size & 0x0F; // %16
|
||||||
if (rem)
|
if (rem)
|
||||||
{
|
{
|
||||||
// padding2
|
// padding2
|
||||||
rem = 16 - rem;
|
rem = 16 - rem;
|
||||||
polyHash.Update (padding, rem);
|
polyHash.Update (padding, rem);
|
||||||
}
|
}
|
||||||
// adLen and msgLen
|
// adLen and msgLen
|
||||||
// adLen is always zero
|
// adLen is always zero
|
||||||
htole64buf (padding + 8, size);
|
htole64buf (padding + 8, size);
|
||||||
polyHash.Update (padding, 16);
|
polyHash.Update (padding, 16);
|
||||||
// MAC
|
// MAC
|
||||||
polyHash.Finish ((uint64_t *)mac);
|
polyHash.Finish ((uint64_t *)mac);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
void ChaCha20 (const uint8_t * msg, size_t msgLen, const uint8_t * key, const uint8_t * nonce, uint8_t * out)
|
||||||
|
@ -1265,13 +1264,13 @@ namespace crypto
|
||||||
EVP_CIPHER_CTX_free (ctx);
|
EVP_CIPHER_CTX_free (ctx);
|
||||||
#else
|
#else
|
||||||
chacha::Chacha20State state;
|
chacha::Chacha20State state;
|
||||||
chacha::Chacha20Init (state, nonce, key, 1);
|
chacha::Chacha20Init (state, nonce, key, 1);
|
||||||
if (out != msg) memcpy (out, msg, msgLen);
|
if (out != msg) memcpy (out, msg, msgLen);
|
||||||
chacha::Chacha20Encrypt (state, out, msgLen);
|
chacha::Chacha20Encrypt (state, out, msgLen);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info,
|
||||||
uint8_t * out, size_t outLen)
|
uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
#if OPENSSL_HKDF
|
#if OPENSSL_HKDF
|
||||||
|
@ -1279,10 +1278,10 @@ namespace crypto
|
||||||
EVP_PKEY_derive_init (pctx);
|
EVP_PKEY_derive_init (pctx);
|
||||||
EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
|
EVP_PKEY_CTX_set_hkdf_md (pctx, EVP_sha256());
|
||||||
if (key && keyLen)
|
if (key && keyLen)
|
||||||
{
|
{
|
||||||
EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
|
EVP_PKEY_CTX_set1_hkdf_salt (pctx, salt, 32);
|
||||||
EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
|
EVP_PKEY_CTX_set1_hkdf_key (pctx, key, keyLen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// zerolen
|
// zerolen
|
||||||
|
@ -1290,22 +1289,22 @@ namespace crypto
|
||||||
uint8_t tempKey[32]; unsigned int len;
|
uint8_t tempKey[32]; unsigned int len;
|
||||||
HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len);
|
HMAC(EVP_sha256(), salt, 32, nullptr, 0, tempKey, &len);
|
||||||
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
|
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
|
||||||
}
|
}
|
||||||
if (info.length () > 0)
|
if (info.length () > 0)
|
||||||
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
|
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
|
||||||
EVP_PKEY_derive (pctx, out, &outLen);
|
EVP_PKEY_derive (pctx, out, &outLen);
|
||||||
EVP_PKEY_CTX_free (pctx);
|
EVP_PKEY_CTX_free (pctx);
|
||||||
#else
|
#else
|
||||||
uint8_t prk[32]; unsigned int len;
|
uint8_t prk[32]; unsigned int len;
|
||||||
HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len);
|
HMAC(EVP_sha256(), salt, 32, key, keyLen, prk, &len);
|
||||||
auto l = info.length ();
|
auto l = info.length ();
|
||||||
memcpy (out, info.c_str (), l); out[l] = 0x01;
|
memcpy (out, info.c_str (), l); out[l] = 0x01;
|
||||||
HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
|
HMAC(EVP_sha256(), prk, 32, out, l + 1, out, &len);
|
||||||
if (outLen > 32) // 64
|
if (outLen > 32) // 64
|
||||||
{
|
{
|
||||||
memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
|
memcpy (out + 32, info.c_str (), l); out[l + 32] = 0x02;
|
||||||
HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len);
|
HMAC(EVP_sha256(), prk, 32, out, l + 33, out + 32, &len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,10 +1322,10 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
void InitCrypto (bool precomputation)
|
void InitCrypto (bool precomputation)
|
||||||
{
|
{
|
||||||
i2p::cpu::Detect ();
|
i2p::cpu::Detect ();
|
||||||
#if LEGACY_OPENSSL
|
#if LEGACY_OPENSSL
|
||||||
SSL_library_init ();
|
SSL_library_init ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1364,4 +1363,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,13 +28,13 @@
|
||||||
#else
|
#else
|
||||||
# define LEGACY_OPENSSL 0
|
# define LEGACY_OPENSSL 0
|
||||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||||
# define OPENSSL_HKDF 1
|
# define OPENSSL_HKDF 1
|
||||||
# define OPENSSL_EDDSA 1
|
# define OPENSSL_EDDSA 1
|
||||||
# define OPENSSL_X25519 1
|
# define OPENSSL_X25519 1
|
||||||
# define OPENSSL_SIPHASH 1
|
# define OPENSSL_SIPHASH 1
|
||||||
# endif
|
# endif
|
||||||
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
|
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
|
||||||
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
|
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -81,20 +81,20 @@ namespace crypto
|
||||||
const uint8_t * GetPublicKey () const { return m_PublicKey; };
|
const uint8_t * GetPublicKey () const { return m_PublicKey; };
|
||||||
void GetPrivateKey (uint8_t * priv) const;
|
void GetPrivateKey (uint8_t * priv) const;
|
||||||
void SetPrivateKey (const uint8_t * priv); // wihout calculating public
|
void SetPrivateKey (const uint8_t * priv); // wihout calculating public
|
||||||
void Agree (const uint8_t * pub, uint8_t * shared);
|
void Agree (const uint8_t * pub, uint8_t * shared);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_PublicKey[32];
|
uint8_t m_PublicKey[32];
|
||||||
#if OPENSSL_X25519
|
#if OPENSSL_X25519
|
||||||
EVP_PKEY_CTX * m_Ctx;
|
EVP_PKEY_CTX * m_Ctx;
|
||||||
EVP_PKEY * m_Pkey;
|
EVP_PKEY * m_Pkey;
|
||||||
#else
|
#else
|
||||||
BN_CTX * m_Ctx;
|
BN_CTX * m_Ctx;
|
||||||
uint8_t m_PrivateKey[32];
|
uint8_t m_PrivateKey[32];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
|
void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false);
|
||||||
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||||
|
@ -117,15 +117,15 @@ namespace crypto
|
||||||
void operator^=(const ChipherBlock& other) // XOR
|
void operator^=(const ChipherBlock& other) // XOR
|
||||||
{
|
{
|
||||||
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
if (!(((size_t)buf | (size_t)other.buf) & 0x03)) // multiple of 4 ?
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
|
reinterpret_cast<uint32_t *>(buf)[i] ^= reinterpret_cast<const uint32_t *>(other.buf)[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
buf[i] ^= other.buf[i];
|
buf[i] ^= other.buf[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ namespace crypto
|
||||||
|
|
||||||
// HKDF
|
// HKDF
|
||||||
|
|
||||||
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
|
void HKDF (const uint8_t * salt, const uint8_t * key, size_t keyLen, const std::string& info, uint8_t * out, size_t outLen = 64); // salt - 32, out - 32 or 64, info <= 32
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation);
|
void InitCrypto (bool precomputation);
|
||||||
|
|
|
@ -151,7 +151,7 @@ namespace crypto
|
||||||
ECIESX25519AEADRatchetEncryptor::ECIESX25519AEADRatchetEncryptor (const uint8_t * pub)
|
ECIESX25519AEADRatchetEncryptor::ECIESX25519AEADRatchetEncryptor (const uint8_t * pub)
|
||||||
{
|
{
|
||||||
memcpy (m_PublicKey, pub, 32);
|
memcpy (m_PublicKey, pub, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool)
|
void ECIESX25519AEADRatchetEncryptor::Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool)
|
||||||
{
|
{
|
||||||
|
@ -166,16 +166,15 @@ namespace crypto
|
||||||
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding)
|
bool ECIESX25519AEADRatchetDecryptor::Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding)
|
||||||
{
|
{
|
||||||
m_StaticKeys.Agree (epub, sharedSecret);
|
m_StaticKeys.Agree (epub, sharedSecret);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub)
|
void CreateECIESX25519AEADRatchetRandomKeys (uint8_t * priv, uint8_t * pub)
|
||||||
{
|
{
|
||||||
X25519Keys k;
|
X25519Keys k;
|
||||||
k.GenerateKeys ();
|
k.GenerateKeys ();
|
||||||
k.GetPrivateKey (priv);
|
k.GetPrivateKey (priv);
|
||||||
memcpy (pub, k.GetPublicKey (), 32);
|
memcpy (pub, k.GetPublicKey (), 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace crypto
|
||||||
ElGamalDecryptor (const uint8_t * priv);
|
ElGamalDecryptor (const uint8_t * priv);
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
size_t GetPublicKeyLen () const { return 256; };
|
size_t GetPublicKeyLen () const { return 256; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_PrivateKey[256];
|
uint8_t m_PrivateKey[256];
|
||||||
|
@ -76,7 +76,7 @@ namespace crypto
|
||||||
~ECIESP256Decryptor ();
|
~ECIESP256Decryptor ();
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
size_t GetPublicKeyLen () const { return 64; };
|
size_t GetPublicKeyLen () const { return 64; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
EC_GROUP * m_Curve;
|
EC_GROUP * m_Curve;
|
||||||
|
@ -109,7 +109,7 @@ namespace crypto
|
||||||
~ECIESGOSTR3410Decryptor ();
|
~ECIESGOSTR3410Decryptor ();
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||||
size_t GetPublicKeyLen () const { return 64; };
|
size_t GetPublicKeyLen () const { return 64; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
BIGNUM * m_PrivateKey;
|
BIGNUM * m_PrivateKey;
|
||||||
|
@ -119,14 +119,14 @@ namespace crypto
|
||||||
|
|
||||||
// ECIES-X25519-AEAD-Ratchet
|
// ECIES-X25519-AEAD-Ratchet
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor
|
class ECIESX25519AEADRatchetEncryptor: public CryptoKeyEncryptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
|
ECIESX25519AEADRatchetEncryptor (const uint8_t * pub);
|
||||||
~ECIESX25519AEADRatchetEncryptor () {};
|
~ECIESX25519AEADRatchetEncryptor () {};
|
||||||
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
|
void Encrypt (const uint8_t *, uint8_t * pub, BN_CTX *, bool);
|
||||||
// copies m_PublicKey to pub
|
// copies m_PublicKey to pub
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ namespace crypto
|
||||||
|
|
||||||
ECIESX25519AEADRatchetDecryptor (const uint8_t * priv);
|
ECIESX25519AEADRatchetDecryptor (const uint8_t * priv);
|
||||||
~ECIESX25519AEADRatchetDecryptor () {};
|
~ECIESX25519AEADRatchetDecryptor () {};
|
||||||
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding);
|
bool Decrypt (const uint8_t * epub, uint8_t * sharedSecret, BN_CTX * ctx, bool zeroPadding);
|
||||||
// agree with static and return in sharedSecret (32 bytes)
|
// agree with static and return in sharedSecret (32 bytes)
|
||||||
size_t GetPublicKeyLen () const { return 32; };
|
size_t GetPublicKeyLen () const { return 32; };
|
||||||
|
|
||||||
|
@ -153,4 +153,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -77,5 +77,4 @@ namespace worker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,10 +13,10 @@ namespace datagram
|
||||||
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
|
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
|
||||||
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
|
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
|
||||||
{
|
{
|
||||||
auto identityLen = m_Owner->GetIdentity ()->GetFullLen ();
|
auto identityLen = m_Owner->GetIdentity ()->GetFullLen ();
|
||||||
m_From.resize (identityLen);
|
m_From.resize (identityLen);
|
||||||
m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen);
|
m_Owner->GetIdentity ()->ToBuffer (m_From.data (), identityLen);
|
||||||
m_Signature.resize (m_Owner->GetIdentity ()->GetSignatureLen ());
|
m_Signature.resize (m_Owner->GetIdentity ()->GetSignatureLen ());
|
||||||
}
|
}
|
||||||
|
|
||||||
DatagramDestination::~DatagramDestination ()
|
DatagramDestination::~DatagramDestination ()
|
||||||
|
@ -36,7 +36,7 @@ namespace datagram
|
||||||
m_Owner->Sign (payload, len, m_Signature.data ());
|
m_Owner->Sign (payload, len, m_Signature.data ());
|
||||||
|
|
||||||
auto session = ObtainSession(identity);
|
auto session = ObtainSession(identity);
|
||||||
auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}},
|
auto msg = CreateDataMessage ({{m_From.data (), m_From.size ()}, {m_Signature.data (), m_Signature.size ()}, {payload, len}},
|
||||||
fromPort, toPort, false, !session->IsRatchets ()); // datagram
|
fromPort, toPort, false, !session->IsRatchets ()); // datagram
|
||||||
session->SendMsg(msg);
|
session->SendMsg(msg);
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ namespace datagram
|
||||||
auto session = ObtainSession(identity);
|
auto session = ObtainSession(identity);
|
||||||
auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw
|
auto msg = CreateDataMessage ({{payload, len}}, fromPort, toPort, true, !session->IsRatchets ()); // raw
|
||||||
session->SendMsg(msg);
|
session->SendMsg(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len)
|
void DatagramDestination::HandleDatagram (uint16_t fromPort, uint16_t toPort,uint8_t * const &buf, size_t len)
|
||||||
{
|
{
|
||||||
i2p::data::IdentityEx identity;
|
i2p::data::IdentityEx identity;
|
||||||
|
@ -86,8 +86,8 @@ namespace datagram
|
||||||
m_RawReceiver (fromPort, toPort, buf, len);
|
m_RawReceiver (fromPort, toPort, buf, len);
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
|
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
|
||||||
}
|
}
|
||||||
|
|
||||||
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
|
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
|
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
|
||||||
|
@ -107,23 +107,22 @@ namespace datagram
|
||||||
{
|
{
|
||||||
if (isRaw)
|
if (isRaw)
|
||||||
HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen);
|
HandleRawDatagram (fromPort, toPort, uncompressed, uncompressedLen);
|
||||||
else
|
else
|
||||||
HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen);
|
HandleDatagram (fromPort, toPort, uncompressed, uncompressedLen);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Datagram: decompression failed");
|
LogPrint (eLogWarning, "Datagram: decompression failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
|
std::shared_ptr<I2NPMessage> DatagramDestination::CreateDataMessage (
|
||||||
const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
||||||
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
|
uint16_t fromPort, uint16_t toPort, bool isRaw, bool checksum)
|
||||||
{
|
{
|
||||||
auto msg = NewI2NPMessage ();
|
auto msg = NewI2NPMessage ();
|
||||||
uint8_t * buf = msg->GetPayload ();
|
uint8_t * buf = msg->GetPayload ();
|
||||||
buf += 4; // reserve for length
|
buf += 4; // reserve for length
|
||||||
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
|
size_t size = m_Gzip ? m_Deflator.Deflate (payloads, buf, msg->maxLen - msg->len) :
|
||||||
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
|
i2p::data::GzipNoCompression (payloads, buf, msg->maxLen - msg->len);
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
htobe32buf (msg->GetPayload (), size); // length
|
htobe32buf (msg->GetPayload (), size); // length
|
||||||
|
@ -186,7 +185,7 @@ namespace datagram
|
||||||
}
|
}
|
||||||
|
|
||||||
DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
DatagramSession::DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination,
|
||||||
const i2p::data::IdentHash & remoteIdent) :
|
const i2p::data::IdentHash & remoteIdent) :
|
||||||
m_LocalDestination(localDestination),
|
m_LocalDestination(localDestination),
|
||||||
m_RemoteIdent(remoteIdent),
|
m_RemoteIdent(remoteIdent),
|
||||||
m_SendQueueTimer(localDestination->GetService()),
|
m_SendQueueTimer(localDestination->GetService()),
|
||||||
|
@ -384,4 +383,3 @@ namespace datagram
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,68 +32,71 @@ namespace datagram
|
||||||
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
|
const uint64_t DATAGRAM_SESSION_LEASE_HANDOVER_FUDGE = 1000;
|
||||||
// milliseconds minimum time between path switches
|
// milliseconds minimum time between path switches
|
||||||
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
|
const uint64_t DATAGRAM_SESSION_PATH_MIN_LIFETIME = 5 * 1000;
|
||||||
// max 64 messages buffered in send queue for each datagram session
|
// max 64 messages buffered in send queue for each datagram session
|
||||||
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
|
const size_t DATAGRAM_SEND_QUEUE_MAX_SIZE = 64;
|
||||||
|
|
||||||
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
|
class DatagramSession : public std::enable_shared_from_this<DatagramSession>
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
|
|
||||||
|
|
||||||
void Start ();
|
public:
|
||||||
void Stop ();
|
|
||||||
|
DatagramSession(std::shared_ptr<i2p::client::ClientDestination> localDestination, const i2p::data::IdentHash & remoteIdent);
|
||||||
|
|
||||||
|
void Start ();
|
||||||
|
void Stop ();
|
||||||
|
|
||||||
|
|
||||||
/** @brief ack the garlic routing path */
|
/** @brief ack the garlic routing path */
|
||||||
void Ack();
|
void Ack();
|
||||||
|
|
||||||
/** send an i2np message to remote endpoint for this session */
|
/** send an i2np message to remote endpoint for this session */
|
||||||
void SendMsg(std::shared_ptr<I2NPMessage> msg);
|
void SendMsg(std::shared_ptr<I2NPMessage> msg);
|
||||||
/** get the last time in milliseconds for when we used this datagram session */
|
/** get the last time in milliseconds for when we used this datagram session */
|
||||||
uint64_t LastActivity() const { return m_LastUse; }
|
uint64_t LastActivity() const { return m_LastUse; }
|
||||||
|
|
||||||
bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
|
bool IsRatchets () const { return m_RoutingSession && m_RoutingSession->IsRatchets (); }
|
||||||
|
|
||||||
struct Info
|
struct Info
|
||||||
{
|
{
|
||||||
std::shared_ptr<const i2p::data::IdentHash> IBGW;
|
std::shared_ptr<const i2p::data::IdentHash> IBGW;
|
||||||
std::shared_ptr<const i2p::data::IdentHash> OBEP;
|
std::shared_ptr<const i2p::data::IdentHash> OBEP;
|
||||||
const uint64_t activity;
|
const uint64_t activity;
|
||||||
|
|
||||||
Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
|
Info() : IBGW(nullptr), OBEP(nullptr), activity(0) {}
|
||||||
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
|
Info(const uint8_t * ibgw, const uint8_t * obep, const uint64_t a) :
|
||||||
activity(a) {
|
activity(a) {
|
||||||
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
|
if(ibgw) IBGW = std::make_shared<i2p::data::IdentHash>(ibgw);
|
||||||
else IBGW = nullptr;
|
else IBGW = nullptr;
|
||||||
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
|
if(obep) OBEP = std::make_shared<i2p::data::IdentHash>(obep);
|
||||||
else OBEP = nullptr;
|
else OBEP = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Info GetSessionInfo() const;
|
Info GetSessionInfo() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void FlushSendQueue();
|
void FlushSendQueue();
|
||||||
void ScheduleFlushSendQueue();
|
void ScheduleFlushSendQueue();
|
||||||
|
|
||||||
void HandleSend(std::shared_ptr<I2NPMessage> msg);
|
void HandleSend(std::shared_ptr<I2NPMessage> msg);
|
||||||
|
|
||||||
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
|
std::shared_ptr<i2p::garlic::GarlicRoutingPath> GetSharedRoutingPath();
|
||||||
|
|
||||||
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
|
void HandleLeaseSetUpdated(std::shared_ptr<i2p::data::LeaseSet> ls);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
|
|
||||||
i2p::data::IdentHash m_RemoteIdent;
|
std::shared_ptr<i2p::client::ClientDestination> m_LocalDestination;
|
||||||
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
i2p::data::IdentHash m_RemoteIdent;
|
||||||
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
|
std::shared_ptr<const i2p::data::LeaseSet> m_RemoteLeaseSet;
|
||||||
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
|
std::shared_ptr<i2p::garlic::GarlicRoutingSession> m_RoutingSession;
|
||||||
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
|
std::shared_ptr<const i2p::data::Lease> m_CurrentRemoteLease;
|
||||||
boost::asio::deadline_timer m_SendQueueTimer;
|
std::shared_ptr<i2p::tunnel::OutboundTunnel> m_CurrentOutboundTunnel;
|
||||||
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
boost::asio::deadline_timer m_SendQueueTimer;
|
||||||
uint64_t m_LastUse;
|
std::vector<std::shared_ptr<I2NPMessage> > m_SendQueue;
|
||||||
bool m_RequestingLS;
|
uint64_t m_LastUse;
|
||||||
|
bool m_RequestingLS;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
|
typedef std::shared_ptr<DatagramSession> DatagramSession_ptr;
|
||||||
|
@ -104,17 +107,15 @@ namespace datagram
|
||||||
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
|
typedef std::function<void (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> Receiver;
|
||||||
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
|
typedef std::function<void (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)> RawReceiver;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
|
||||||
DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip);
|
|
||||||
~DatagramDestination ();
|
~DatagramDestination ();
|
||||||
|
|
||||||
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
||||||
void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
void SendRawDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0);
|
||||||
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
|
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
|
||||||
|
|
||||||
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
|
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
|
||||||
void ResetReceiver () { m_Receiver = nullptr; };
|
void ResetReceiver () { m_Receiver = nullptr; };
|
||||||
|
|
||||||
|
@ -123,7 +124,7 @@ namespace datagram
|
||||||
|
|
||||||
void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
|
void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
|
||||||
void ResetRawReceiver () { m_RawReceiver = nullptr; };
|
void ResetRawReceiver () { m_RawReceiver = nullptr; };
|
||||||
|
|
||||||
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
|
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
|
||||||
|
|
||||||
// clean up stale sessions
|
// clean up stale sessions
|
||||||
|
@ -131,14 +132,14 @@ namespace datagram
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
|
std::shared_ptr<DatagramSession> ObtainSession(const i2p::data::IdentHash & ident);
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
std::shared_ptr<I2NPMessage> CreateDataMessage (const std::vector<std::pair<const uint8_t *, size_t> >& payloads,
|
||||||
uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true);
|
uint16_t fromPort, uint16_t toPort, bool isRaw = false, bool checksum = true);
|
||||||
|
|
||||||
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
|
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
|
||||||
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
|
||||||
|
|
||||||
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
|
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
|
||||||
Receiver FindReceiver(uint16_t port);
|
Receiver FindReceiver(uint16_t port);
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ namespace i2p
|
||||||
namespace client
|
namespace client
|
||||||
{
|
{
|
||||||
LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
|
LeaseSetDestination::LeaseSetDestination (boost::asio::io_service& service,
|
||||||
bool isPublic, const std::map<std::string, std::string> * params):
|
bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0),
|
m_Service (service), m_IsPublic (isPublic), m_PublishReplyToken (0),
|
||||||
m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
|
m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
|
||||||
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
|
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
|
||||||
m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
|
m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
|
||||||
|
@ -160,13 +160,12 @@ namespace client
|
||||||
|
|
||||||
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
||||||
{
|
{
|
||||||
|
|
||||||
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
||||||
if (itr != params.end())
|
if (itr != params.end())
|
||||||
{
|
{
|
||||||
m_IsPublic = itr->second != "true";
|
m_IsPublic = itr->second != "true";
|
||||||
}
|
}
|
||||||
|
|
||||||
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
||||||
std::map<std::string, int&> intOpts = {
|
std::map<std::string, int&> intOpts = {
|
||||||
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
||||||
|
@ -185,7 +184,7 @@ namespace client
|
||||||
outQuant = pool->GetNumOutboundTunnels();
|
outQuant = pool->GetNumOutboundTunnels();
|
||||||
minLatency = 0;
|
minLatency = 0;
|
||||||
maxLatency = 0;
|
maxLatency = 0;
|
||||||
|
|
||||||
for (auto & opt : intOpts)
|
for (auto & opt : intOpts)
|
||||||
{
|
{
|
||||||
itr = params.find(opt.first);
|
itr = params.find(opt.first);
|
||||||
|
@ -197,7 +196,7 @@ namespace client
|
||||||
pool->RequireLatency(minLatency, maxLatency);
|
pool->RequireLatency(minLatency, maxLatency);
|
||||||
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
|
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
std::shared_ptr<i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
||||||
|
@ -266,7 +265,7 @@ namespace client
|
||||||
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 (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet)
|
void LeaseSetDestination::SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
@ -281,7 +280,7 @@ namespace client
|
||||||
{
|
{
|
||||||
s->m_PublishVerificationTimer.cancel ();
|
s->m_PublishVerificationTimer.cancel ();
|
||||||
s->Publish ();
|
s->Publish ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,12 +564,12 @@ namespace client
|
||||||
m_PublishReplyToken = 0;
|
m_PublishReplyToken = 0;
|
||||||
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
|
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");
|
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
|
||||||
Publish ();
|
Publish ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds from Java floodfill for crypto type ", (int)GetIdentity ()->GetCryptoKeyType ());
|
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 confirmation back for unknown crypto type
|
// Java floodfill never sends confirmation back for unknown crypto type
|
||||||
// assume it successive and try to verify
|
// assume it successive and try to verify
|
||||||
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
|
m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT));
|
||||||
|
@ -591,7 +590,7 @@ namespace client
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
|
LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
// we must capture this for gcc 4.7 due the bug
|
// we must capture this for gcc 4.7 due the bug
|
||||||
RequestLeaseSet (ls->GetStoreHash (),
|
RequestLeaseSet (ls->GetStoreHash (),
|
||||||
|
@ -643,9 +642,9 @@ namespace client
|
||||||
if (requestComplete)
|
if (requestComplete)
|
||||||
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
|
m_Service.post ([requestComplete](void){requestComplete (nullptr);});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto storeHash = dest->GetStoreHash ();
|
auto storeHash = dest->GetStoreHash ();
|
||||||
auto leaseSet = FindLeaseSet (storeHash);
|
auto leaseSet = FindLeaseSet (storeHash);
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
if (requestComplete)
|
if (requestComplete)
|
||||||
|
@ -720,7 +719,7 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest,
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
||||||
{
|
{
|
||||||
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
||||||
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
|
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
|
||||||
|
@ -783,7 +782,7 @@ namespace client
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
|
LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds");
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -829,13 +828,13 @@ namespace client
|
||||||
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
|
i2p::data::CryptoKeyType LeaseSetDestination::GetPreferredCryptoType () const
|
||||||
{
|
{
|
||||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
|
return i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET;
|
||||||
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
return i2p::data::CRYPTO_KEY_TYPE_ELGAMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
ClientDestination::ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||||
bool isPublic, const std::map<std::string, std::string> * params):
|
bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
LeaseSetDestination (service, isPublic, params),
|
LeaseSetDestination (service, isPublic, params),
|
||||||
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
|
||||||
m_DatagramDestination (nullptr), m_RefCounter (0),
|
m_DatagramDestination (nullptr), m_RefCounter (0),
|
||||||
m_ReadyChecker(service)
|
m_ReadyChecker(service)
|
||||||
|
@ -846,7 +845,7 @@ namespace client
|
||||||
// extract encryption type params for LS2
|
// extract encryption type params for LS2
|
||||||
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
std::set<i2p::data::CryptoKeyType> encryptionKeyTypes;
|
||||||
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
if ((GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2 ||
|
||||||
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) && params)
|
||||||
{
|
{
|
||||||
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
auto it = params->find (I2CP_PARAM_LEASESET_ENCRYPTION_TYPE);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
|
@ -864,37 +863,37 @@ namespace client
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Destination: Unexpected crypto type ", it1, ". ", ex.what ());
|
LogPrint (eLogInfo, "Destination: Unexpected crypto type ", it1, ". ", ex.what ());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if no param or valid crypto type use from identity
|
// if no param or valid crypto type use from identity
|
||||||
bool isSingleKey = false;
|
bool isSingleKey = false;
|
||||||
if (encryptionKeyTypes.empty ())
|
if (encryptionKeyTypes.empty ())
|
||||||
{
|
{
|
||||||
isSingleKey = true;
|
isSingleKey = true;
|
||||||
encryptionKeyTypes.insert (GetIdentity ()->GetCryptoKeyType ());
|
encryptionKeyTypes.insert (GetIdentity ()->GetCryptoKeyType ());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& it: encryptionKeyTypes)
|
for (auto& it: encryptionKeyTypes)
|
||||||
{
|
{
|
||||||
auto encryptionKey = new EncryptionKey (it);
|
auto encryptionKey = new EncryptionKey (it);
|
||||||
if (isPublic)
|
if (isPublic)
|
||||||
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
||||||
else
|
else
|
||||||
encryptionKey->GenerateKeys ();
|
encryptionKey->GenerateKeys ();
|
||||||
encryptionKey->CreateDecryptor ();
|
encryptionKey->CreateDecryptor ();
|
||||||
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
if (it == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
||||||
m_ECIESx25519EncryptionKey.reset (encryptionKey);
|
m_ECIESx25519EncryptionKey.reset (encryptionKey);
|
||||||
else
|
else
|
||||||
m_StandardEncryptionKey.reset (encryptionKey);
|
m_StandardEncryptionKey.reset (encryptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPublic)
|
if (isPublic)
|
||||||
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (params)
|
if (params)
|
||||||
{
|
{
|
||||||
// extract streaming params
|
// extract streaming params
|
||||||
|
@ -910,9 +909,9 @@ namespace client
|
||||||
{
|
{
|
||||||
m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
|
m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
|
||||||
if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
|
if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
|
||||||
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);
|
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);
|
||||||
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
|
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
|
||||||
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
|
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
|
LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
|
||||||
if (m_AuthKeys->size ())
|
if (m_AuthKeys->size ())
|
||||||
|
@ -920,7 +919,7 @@ namespace client
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
|
LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
|
||||||
m_AuthKeys = nullptr;
|
m_AuthKeys = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1001,7 @@ namespace client
|
||||||
m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true);
|
m_DatagramDestination->HandleDataMessagePayload (fromPort, toPort, buf, length, true);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destination: Missing raw datagram destination");
|
LogPrint (eLogError, "Destination: Missing raw datagram destination");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
|
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1104,7 @@ namespace client
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
|
i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination (bool gzip)
|
||||||
{
|
{
|
||||||
if (m_DatagramDestination == nullptr)
|
if (m_DatagramDestination == nullptr)
|
||||||
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
|
m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis (), gzip);
|
||||||
|
@ -1130,7 +1129,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (!keys) return;
|
if (!keys) return;
|
||||||
std::string ident = GetIdentHash().ToBase32();
|
std::string ident = GetIdentHash().ToBase32();
|
||||||
std::string path = i2p::fs::DataDirPath("destinations",
|
std::string path = i2p::fs::DataDirPath("destinations",
|
||||||
isSingleKey ? (ident + ".dat") : (ident + "." + std::to_string (keys->keyType) + ".dat"));
|
isSingleKey ? (ident + ".dat") : (ident + "." + std::to_string (keys->keyType) + ".dat"));
|
||||||
std::ifstream f(path, std::ifstream::binary);
|
std::ifstream f(path, std::ifstream::binary);
|
||||||
|
|
||||||
|
@ -1142,12 +1141,12 @@ namespace client
|
||||||
|
|
||||||
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
|
LogPrint (eLogInfo, "Destination: Creating new temporary keys of type for address ", ident, ".b32.i2p");
|
||||||
memset (keys->priv, 0, 256);
|
memset (keys->priv, 0, 256);
|
||||||
memset (keys->pub, 0, 256);
|
memset (keys->pub, 0, 256);
|
||||||
keys->GenerateKeys ();
|
keys->GenerateKeys ();
|
||||||
// TODO:: persist crypto key type
|
// TODO:: persist crypto key type
|
||||||
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out);
|
||||||
if (f1) {
|
if (f1) {
|
||||||
f1.write ((char *)keys->pub, 256);
|
f1.write ((char *)keys->pub, 256);
|
||||||
f1.write ((char *)keys->priv, 256);
|
f1.write ((char *)keys->priv, 256);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1160,11 +1159,11 @@ namespace client
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
{
|
{
|
||||||
if (m_StandardEncryptionKey)
|
if (m_StandardEncryptionKey)
|
||||||
{
|
{
|
||||||
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_StandardEncryptionKey->pub, tunnels);
|
leaseSet = std::make_shared<i2p::data::LocalLeaseSet> (GetIdentity (), m_StandardEncryptionKey->pub, tunnels);
|
||||||
// sign
|
// sign
|
||||||
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1");
|
LogPrint (eLogError, "Destinations: Wrong encryption key type for LeaseSet type 1");
|
||||||
}
|
}
|
||||||
|
@ -1175,9 +1174,9 @@ namespace client
|
||||||
if (m_ECIESx25519EncryptionKey)
|
if (m_ECIESx25519EncryptionKey)
|
||||||
keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} );
|
keySections.push_back ({m_ECIESx25519EncryptionKey->keyType, 32, m_ECIESx25519EncryptionKey->pub} );
|
||||||
if (m_StandardEncryptionKey)
|
if (m_StandardEncryptionKey)
|
||||||
keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} );
|
keySections.push_back ({m_StandardEncryptionKey->keyType, (uint16_t)m_StandardEncryptionKey->decryptor->GetPublicKeyLen (), m_StandardEncryptionKey->pub} );
|
||||||
|
|
||||||
bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
bool isPublishedEncrypted = GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
||||||
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
|
||||||
m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted);
|
m_Keys, keySections, tunnels, IsPublic (), isPublishedEncrypted);
|
||||||
if (isPublishedEncrypted) // encrypt if type 5
|
if (isPublishedEncrypted) // encrypt if type 5
|
||||||
|
@ -1204,18 +1203,18 @@ namespace client
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
|
bool ClientDestination::SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const
|
||||||
{
|
{
|
||||||
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey;
|
return keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET ? (bool)m_ECIESx25519EncryptionKey : (bool)m_StandardEncryptionKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
|
const uint8_t * ClientDestination::GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const
|
||||||
{
|
{
|
||||||
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
if (keyType == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET)
|
||||||
return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr;
|
return m_ECIESx25519EncryptionKey ? m_ECIESx25519EncryptionKey->pub : nullptr;
|
||||||
return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr;
|
return m_StandardEncryptionKey ? m_StandardEncryptionKey->pub : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
|
void ClientDestination::ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params)
|
||||||
{
|
{
|
||||||
for (auto it: *params)
|
for (auto it: *params)
|
||||||
|
@ -1229,7 +1228,7 @@ namespace client
|
||||||
m_AuthKeys->push_back (pubKey);
|
m_AuthKeys->push_back (pubKey);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
|
LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1241,10 +1240,10 @@ namespace client
|
||||||
if (it.second->DeleteStream (recvStreamID))
|
if (it.second->DeleteStream (recvStreamID))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
|
RunnableClientDestination::RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
|
||||||
RunnableService ("Destination"),
|
RunnableService ("Destination"),
|
||||||
ClientDestination (GetIOService (), keys, isPublic, params)
|
ClientDestination (GetIOService (), keys, isPublic, params)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1253,7 +1252,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (IsRunning ())
|
if (IsRunning ())
|
||||||
Stop ();
|
Stop ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnableClientDestination::Start ()
|
void RunnableClientDestination::Start ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,13 +52,13 @@ namespace client
|
||||||
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
|
const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname";
|
||||||
const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname";
|
const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname";
|
||||||
const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType";
|
const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType";
|
||||||
const int DEFAULT_LEASESET_TYPE = 1;
|
const int DEFAULT_LEASESET_TYPE = 1;
|
||||||
const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType";
|
const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType";
|
||||||
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
|
const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64
|
||||||
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
|
const char I2CP_PARAM_LEASESET_AUTH_TYPE[] = "i2cp.leaseSetAuthType";
|
||||||
const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn
|
const char I2CP_PARAM_LEASESET_CLIENT_DH[] = "i2cp.leaseSetClient.dh"; // group of i2cp.leaseSetClient.dh.nnn
|
||||||
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
|
const char I2CP_PARAM_LEASESET_CLIENT_PSK[] = "i2cp.leaseSetClient.psk"; // group of i2cp.leaseSetClient.psk.nnn
|
||||||
|
|
||||||
// latency
|
// latency
|
||||||
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
|
const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min";
|
||||||
const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
|
const int DEFAULT_MIN_TUNNEL_LATENCY = 0;
|
||||||
|
@ -94,7 +94,6 @@ namespace client
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
LeaseSetDestination (boost::asio::io_service& service, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
|
@ -107,12 +106,12 @@ namespace client
|
||||||
|
|
||||||
/** i2cp reconfigure */
|
/** i2cp reconfigure */
|
||||||
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
|
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
|
||||||
|
|
||||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
||||||
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<i2p::data::LeaseSet> FindLeaseSet (const i2p::data::IdentHash& ident);
|
std::shared_ptr<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::BlindedPublicKey> dest, RequestComplete requestComplete = nullptr);
|
bool RequestDestinationWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> 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::BlindedPublicKey> dest, bool notify = true);
|
void CancelDestinationRequestWithEncryptedLeaseSet (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, bool notify = true);
|
||||||
|
|
||||||
|
@ -155,7 +154,7 @@ namespace client
|
||||||
void HandleDeliveryStatusMessage (uint32_t msgID);
|
void HandleDeliveryStatusMessage (uint32_t msgID);
|
||||||
|
|
||||||
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
|
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = 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);
|
||||||
void CleanupRemoteLeaseSets ();
|
void CleanupRemoteLeaseSets ();
|
||||||
|
@ -202,11 +201,11 @@ namespace client
|
||||||
EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); };
|
EncryptionKey (i2p::data::CryptoKeyType t):keyType(t) { memset (pub, 0, 256); memset (priv, 0, 256); };
|
||||||
void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); };
|
void GenerateKeys () { i2p::data::PrivateKeys::GenerateCryptoKeyPair (keyType, priv, pub); };
|
||||||
void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); };
|
void CreateDecryptor () { decryptor = i2p::data::PrivateKeys::CreateDecryptor (keyType, priv); };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
ClientDestination (boost::asio::io_service& service, const i2p::data::PrivateKeys& keys,
|
||||||
bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
~ClientDestination ();
|
~ClientDestination ();
|
||||||
|
|
||||||
|
@ -235,13 +234,13 @@ namespace client
|
||||||
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
int GetStreamingAckDelay () const { return m_StreamingAckDelay; }
|
||||||
|
|
||||||
// datagram
|
// datagram
|
||||||
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
i2p::datagram::DatagramDestination * GetDatagramDestination () const { return m_DatagramDestination; };
|
||||||
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
i2p::datagram::DatagramDestination * CreateDatagramDestination (bool gzip = true);
|
||||||
|
|
||||||
// implements LocalDestination
|
// implements LocalDestination
|
||||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, i2p::data::CryptoKeyType preferredCrypto) const;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
std::shared_ptr<const i2p::data::IdentityEx> GetIdentity () const { return m_Keys.GetPublic (); };
|
||||||
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
|
bool SupportsEncryptionType (i2p::data::CryptoKeyType keyType) const;
|
||||||
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const;
|
const uint8_t * GetEncryptionPublicKey (i2p::data::CryptoKeyType keyType) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -259,8 +258,8 @@ namespace client
|
||||||
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
|
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
|
||||||
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
std::unique_ptr<EncryptionKey> m_StandardEncryptionKey;
|
std::unique_ptr<EncryptionKey> m_StandardEncryptionKey;
|
||||||
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
std::unique_ptr<EncryptionKey> m_ECIESx25519EncryptionKey;
|
||||||
|
@ -273,7 +272,7 @@ namespace client
|
||||||
|
|
||||||
boost::asio::deadline_timer m_ReadyChecker;
|
boost::asio::deadline_timer m_ReadyChecker;
|
||||||
|
|
||||||
std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP
|
std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -287,7 +286,7 @@ namespace client
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
RunnableClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params = nullptr);
|
||||||
~RunnableClientDestination ();
|
~RunnableClientDestination ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,22 +25,22 @@ namespace garlic
|
||||||
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
|
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
|
||||||
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
|
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
|
||||||
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
|
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
|
||||||
|
|
||||||
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
|
|
||||||
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession;
|
|
||||||
class RatchetTagSet
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
|
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
|
||||||
|
// - 16 /* I2NP header */ - 16 /* poly hash */ - 8 /* tag */ - 4 /* garlic length */
|
||||||
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
|
||||||
void NextSessionTagRatchet ();
|
class ECIESX25519AEADRatchetSession;
|
||||||
uint64_t GetNextSessionTag ();
|
class RatchetTagSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
|
||||||
|
|
||||||
|
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
||||||
|
void NextSessionTagRatchet ();
|
||||||
|
uint64_t GetNextSessionTag ();
|
||||||
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
const uint8_t * GetNextRootKey () const { return m_NextRootKey; };
|
||||||
int GetNextIndex () const { return m_NextIndex; };
|
int GetNextIndex () const { return m_NextIndex; };
|
||||||
void GetSymmKey (int index, uint8_t * key);
|
void GetSymmKey (int index, uint8_t * key);
|
||||||
|
|
||||||
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
std::shared_ptr<ECIESX25519AEADRatchetSession> GetSession () { return m_Session.lock (); };
|
||||||
|
@ -49,54 +49,54 @@ namespace garlic
|
||||||
|
|
||||||
void Expire ();
|
void Expire ();
|
||||||
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
bool IsExpired (uint64_t ts) const { return m_ExpirationTimestamp && ts > m_ExpirationTimestamp; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
union
|
|
||||||
{
|
|
||||||
uint64_t ll[8];
|
|
||||||
uint8_t buf[64];
|
|
||||||
|
|
||||||
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
|
union
|
||||||
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
|
{
|
||||||
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
|
uint64_t ll[8];
|
||||||
|
uint8_t buf[64];
|
||||||
} m_KeyData;
|
|
||||||
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
|
||||||
int m_NextIndex, m_NextSymmKeyIndex;
|
|
||||||
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
|
||||||
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
|
||||||
int m_TagSetID = 0;
|
|
||||||
uint64_t m_ExpirationTimestamp = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ECIESx25519BlockType
|
const uint8_t * GetSessTagCK () const { return buf; }; // sessTag_chainKey = keydata[0:31]
|
||||||
|
const uint8_t * GetSessTagConstant () const { return buf + 32; }; // SESSTAG_CONSTANT = keydata[32:63]
|
||||||
|
uint64_t GetTag () const { return ll[4]; }; // tag = keydata[32:39]
|
||||||
|
|
||||||
|
} m_KeyData;
|
||||||
|
uint8_t m_SessTagConstant[32], m_SymmKeyCK[32], m_CurrentSymmKeyCK[64], m_NextRootKey[32];
|
||||||
|
int m_NextIndex, m_NextSymmKeyIndex;
|
||||||
|
std::unordered_map<int, i2p::data::Tag<32> > m_ItermediateSymmKeys;
|
||||||
|
std::weak_ptr<ECIESX25519AEADRatchetSession> m_Session;
|
||||||
|
int m_TagSetID = 0;
|
||||||
|
uint64_t m_ExpirationTimestamp = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ECIESx25519BlockType
|
||||||
{
|
{
|
||||||
eECIESx25519BlkDateTime = 0,
|
eECIESx25519BlkDateTime = 0,
|
||||||
eECIESx25519BlkSessionID = 1,
|
eECIESx25519BlkSessionID = 1,
|
||||||
eECIESx25519BlkTermination = 4,
|
eECIESx25519BlkTermination = 4,
|
||||||
eECIESx25519BlkOptions = 5,
|
eECIESx25519BlkOptions = 5,
|
||||||
eECIESx25519BlkNextKey = 7,
|
eECIESx25519BlkNextKey = 7,
|
||||||
eECIESx25519BlkAck = 8,
|
eECIESx25519BlkAck = 8,
|
||||||
eECIESx25519BlkAckRequest = 9,
|
eECIESx25519BlkAckRequest = 9,
|
||||||
eECIESx25519BlkGalicClove = 11,
|
eECIESx25519BlkGalicClove = 11,
|
||||||
eECIESx25519BlkPadding = 254
|
eECIESx25519BlkPadding = 254
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
|
const uint8_t ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG = 0x01;
|
||||||
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
|
const uint8_t ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG = 0x02;
|
||||||
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
|
const uint8_t ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG = 0x04;
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
|
class ECIESX25519AEADRatchetSession: public GarlicRoutingSession, public std::enable_shared_from_this<ECIESX25519AEADRatchetSession>
|
||||||
{
|
{
|
||||||
enum SessionState
|
enum SessionState
|
||||||
{
|
{
|
||||||
eSessionStateNew =0,
|
eSessionStateNew = 0,
|
||||||
eSessionStateNewSessionReceived,
|
eSessionStateNewSessionReceived,
|
||||||
eSessionStateNewSessionSent,
|
eSessionStateNewSessionSent,
|
||||||
eSessionStateNewSessionReplySent,
|
eSessionStateNewSessionReplySent,
|
||||||
eSessionStateEstablished
|
eSessionStateEstablished
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DHRatchet
|
struct DHRatchet
|
||||||
{
|
{
|
||||||
|
@ -104,65 +104,65 @@ namespace garlic
|
||||||
i2p::crypto::X25519Keys key;
|
i2p::crypto::X25519Keys key;
|
||||||
uint8_t remote[32]; // last remote public key
|
uint8_t remote[32]; // last remote public key
|
||||||
bool newKey = true;
|
bool newKey = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
|
public:
|
||||||
~ECIESX25519AEADRatchetSession ();
|
|
||||||
|
ECIESX25519AEADRatchetSession (GarlicDestination * owner, bool attachLeaseSet);
|
||||||
|
~ECIESX25519AEADRatchetSession ();
|
||||||
|
|
||||||
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
|
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
|
||||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
||||||
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
|
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
|
||||||
|
|
||||||
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
|
void SetDestination (const i2p::data::IdentHash& dest) // TODO:
|
||||||
{
|
{
|
||||||
if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest));
|
if (!m_Destination) m_Destination.reset (new i2p::data::IdentHash (dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckExpired (uint64_t ts); // true is expired
|
bool CheckExpired (uint64_t ts); // true is expired
|
||||||
bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; }
|
bool CanBeRestarted (uint64_t ts) const { return ts > m_LastActivityTimestamp + ECIESX25519_RESTART_TIMEOUT; }
|
||||||
|
|
||||||
bool IsRatchets () const { return true; };
|
bool IsRatchets () const { return true; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ResetKeys ();
|
void ResetKeys ();
|
||||||
void MixHash (const uint8_t * buf, size_t len);
|
void MixHash (const uint8_t * buf, size_t len);
|
||||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||||
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
||||||
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
|
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
|
||||||
|
|
||||||
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
bool HandleNewIncomingSession (const uint8_t * buf, size_t len);
|
||||||
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
|
bool HandleNewOutgoingSessionReply (uint8_t * buf, size_t len);
|
||||||
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
|
bool HandleExistingSessionMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index);
|
||||||
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
|
void HandlePayload (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset, int index);
|
||||||
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset);
|
void HandleNextKey (const uint8_t * buf, size_t len, const std::shared_ptr<RatchetTagSet>& receiveTagset);
|
||||||
|
|
||||||
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
||||||
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
|
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len, bool isDestination = false);
|
||||||
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
||||||
|
|
||||||
void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
|
void GenerateMoreReceiveTags (std::shared_ptr<RatchetTagSet> receiveTagset, int numTags);
|
||||||
void NewNextSendRatchet ();
|
void NewNextSendRatchet ();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
private:
|
||||||
|
|
||||||
|
uint8_t m_H[32], m_CK[64] /* [chainkey, key] */, m_RemoteStaticKey[32];
|
||||||
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
|
uint8_t m_Aepk[32]; // Alice's ephemeral keys, for incoming only
|
||||||
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
|
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
|
||||||
i2p::crypto::X25519Keys m_EphemeralKeys;
|
i2p::crypto::X25519Keys m_EphemeralKeys;
|
||||||
SessionState m_State = eSessionStateNew;
|
SessionState m_State = eSessionStateNew;
|
||||||
uint64_t m_LastActivityTimestamp = 0; // incoming
|
uint64_t m_LastActivityTimestamp = 0; // incoming
|
||||||
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
|
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRTagset;
|
||||||
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
||||||
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
|
std::list<std::pair<uint16_t, int> > m_AckRequests; // (tagsetid, index)
|
||||||
bool m_SendReverseKey = false, m_SendForwardKey = false;
|
bool m_SendReverseKey = false, m_SendForwardKey = false;
|
||||||
std::unique_ptr<DHRatchet> m_NextReceiveRatchet, m_NextSendRatchet;
|
std::unique_ptr<DHRatchet> m_NextReceiveRatchet, m_NextSendRatchet;
|
||||||
|
@ -174,8 +174,8 @@ namespace garlic
|
||||||
i2p::data::IdentHash GetDestination () const
|
i2p::data::IdentHash GetDestination () const
|
||||||
{
|
{
|
||||||
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
std::shared_ptr<I2NPMessage> WrapECIESX25519AEADRatchetMessage (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ namespace crypto
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded,
|
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded,
|
||||||
const uint8_t * buf, size_t len, uint8_t * signature) const
|
const uint8_t * buf, size_t len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
BN_CTX * bnCtx = BN_CTX_new ();
|
BN_CTX * bnCtx = BN_CTX_new ();
|
||||||
|
@ -153,7 +153,7 @@ namespace crypto
|
||||||
BN_CTX_free (bnCtx);
|
BN_CTX_free (bnCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded,
|
void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded,
|
||||||
const uint8_t * buf, size_t len, uint8_t * signature) const
|
const uint8_t * buf, size_t len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
BN_CTX * bnCtx = BN_CTX_new ();
|
BN_CTX * bnCtx = BN_CTX_new ();
|
||||||
|
@ -164,16 +164,16 @@ namespace crypto
|
||||||
SHA512_CTX ctx;
|
SHA512_CTX ctx;
|
||||||
SHA512_Init (&ctx);
|
SHA512_Init (&ctx);
|
||||||
SHA512_Update (&ctx, T, 80);
|
SHA512_Update (&ctx, T, 80);
|
||||||
SHA512_Update (&ctx, publicKeyEncoded, 32);
|
SHA512_Update (&ctx, publicKeyEncoded, 32);
|
||||||
SHA512_Update (&ctx, buf, len); // data
|
SHA512_Update (&ctx, buf, len); // data
|
||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
SHA512_Final (digest, &ctx);
|
SHA512_Final (digest, &ctx);
|
||||||
BIGNUM * r = DecodeBN<64> (digest);
|
BIGNUM * r = DecodeBN<64> (digest);
|
||||||
BN_mod (r, r, l, bnCtx); // % l
|
BN_mod (r, r, l, bnCtx); // % l
|
||||||
EncodeBN (r, digest, 32);
|
EncodeBN (r, digest, 32);
|
||||||
// calculate R
|
// calculate R
|
||||||
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
|
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
|
||||||
EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R);
|
EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R);
|
||||||
// calculate S
|
// calculate S
|
||||||
SHA512_Init (&ctx);
|
SHA512_Init (&ctx);
|
||||||
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
||||||
|
@ -182,7 +182,7 @@ namespace crypto
|
||||||
SHA512_Final (digest, &ctx);
|
SHA512_Final (digest, &ctx);
|
||||||
BIGNUM * h = DecodeBN<64> (digest);
|
BIGNUM * h = DecodeBN<64> (digest);
|
||||||
// S = (r + h*a) % l
|
// S = (r + h*a) % l
|
||||||
BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (privateKey);
|
BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (privateKey);
|
||||||
BN_mod_mul (h, h, a, l, bnCtx); // %l
|
BN_mod_mul (h, h, a, l, bnCtx); // %l
|
||||||
BN_mod_add (h, h, r, l, bnCtx); // %l
|
BN_mod_add (h, h, r, l, bnCtx); // %l
|
||||||
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
|
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
|
||||||
|
@ -190,7 +190,7 @@ namespace crypto
|
||||||
BN_free (r); BN_free (h); BN_free (a);
|
BN_free (r); BN_free (h); BN_free (a);
|
||||||
BN_CTX_free (bnCtx);
|
BN_CTX_free (bnCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
||||||
{
|
{
|
||||||
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
|
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
|
||||||
|
@ -467,7 +467,7 @@ namespace crypto
|
||||||
--bits;
|
--bits;
|
||||||
auto k_t = BN_is_bit_set(k, bits) ? 1 : 0;
|
auto k_t = BN_is_bit_set(k, bits) ? 1 : 0;
|
||||||
swap ^= k_t;
|
swap ^= k_t;
|
||||||
if (swap)
|
if (swap)
|
||||||
{
|
{
|
||||||
std::swap (x2, x3);
|
std::swap (x2, x3);
|
||||||
std::swap (z2, z3);
|
std::swap (z2, z3);
|
||||||
|
@ -492,7 +492,7 @@ namespace crypto
|
||||||
BN_mod_mul(z3, x1, z2, q, ctx);
|
BN_mod_mul(z3, x1, z2, q, ctx);
|
||||||
BN_mod_mul(z2, tmp1, tmp0, q, ctx);
|
BN_mod_mul(z2, tmp1, tmp0, q, ctx);
|
||||||
}
|
}
|
||||||
if (swap)
|
if (swap)
|
||||||
{
|
{
|
||||||
std::swap (x2, x3);
|
std::swap (x2, x3);
|
||||||
std::swap (z2, z3);
|
std::swap (z2, z3);
|
||||||
|
@ -533,9 +533,9 @@ namespace crypto
|
||||||
{
|
{
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
// calculate alpha = seed mod l
|
// calculate alpha = seed mod l
|
||||||
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
|
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
|
||||||
BN_mod (alpha, alpha, l, ctx); // % l
|
BN_mod (alpha, alpha, l, ctx); // % l
|
||||||
uint8_t priv[32];
|
uint8_t priv[32];
|
||||||
EncodeBN (alpha, priv, 32); // back to Little Endian
|
EncodeBN (alpha, priv, 32); // back to Little Endian
|
||||||
BN_free (alpha);
|
BN_free (alpha);
|
||||||
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
|
// A' = BLIND_PUBKEY(A, alpha) = A + DERIVE_PUBLIC(alpha)
|
||||||
|
@ -548,16 +548,16 @@ namespace crypto
|
||||||
{
|
{
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
// calculate alpha = seed mod l
|
// calculate alpha = seed mod l
|
||||||
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
|
BIGNUM * alpha = DecodeBN<64> (seed); // seed is in Little Endian
|
||||||
BN_mod (alpha, alpha, l, ctx); // % l
|
BN_mod (alpha, alpha, l, ctx); // % l
|
||||||
BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian
|
BIGNUM * p = DecodeBN<32> (priv); // priv is in Little Endian
|
||||||
BN_add (alpha, alpha, p); // alpha = alpha + priv
|
BN_add (alpha, alpha, p); // alpha = alpha + priv
|
||||||
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L
|
// a' = BLIND_PRIVKEY(a, alpha) = (a + alpha) mod L
|
||||||
BN_mod (alpha, alpha, l, ctx); // % l
|
BN_mod (alpha, alpha, l, ctx); // % l
|
||||||
EncodeBN (alpha, blindedPriv, 32);
|
EncodeBN (alpha, blindedPriv, 32);
|
||||||
// A' = DERIVE_PUBLIC(a')
|
// A' = DERIVE_PUBLIC(a')
|
||||||
auto A1 = MulB (blindedPriv, ctx);
|
auto A1 = MulB (blindedPriv, ctx);
|
||||||
EncodePublicKey (A1, blindedPub, ctx);
|
EncodePublicKey (A1, blindedPub, ctx);
|
||||||
BN_free (alpha); BN_free (p);
|
BN_free (alpha); BN_free (p);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
|
@ -574,14 +574,14 @@ namespace crypto
|
||||||
{
|
{
|
||||||
uint8_t seed[32];
|
uint8_t seed[32];
|
||||||
RAND_bytes (seed, 32);
|
RAND_bytes (seed, 32);
|
||||||
BIGNUM * p = DecodeBN<32> (seed);
|
BIGNUM * p = DecodeBN<32> (seed);
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_mod (p, p, l, ctx); // % l
|
BN_mod (p, p, l, ctx); // % l
|
||||||
EncodeBN (p, priv, 32);
|
EncodeBN (p, priv, 32);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
BN_free (p);
|
BN_free (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::unique_ptr<Ed25519> g_Ed25519;
|
static std::unique_ptr<Ed25519> g_Ed25519;
|
||||||
std::unique_ptr<Ed25519>& GetEd25519 ()
|
std::unique_ptr<Ed25519>& GetEd25519 ()
|
||||||
{
|
{
|
||||||
|
@ -597,4 +597,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,10 +86,10 @@ namespace crypto
|
||||||
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;
|
||||||
void SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
void SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
||||||
|
|
||||||
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
|
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
|
||||||
void CreateRedDSAPrivateKey (uint8_t * priv); // priv is 32 bytes
|
void CreateRedDSAPrivateKey (uint8_t * priv); // priv is 32 bytes
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
|
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
|
||||||
|
@ -97,8 +97,8 @@ namespace crypto
|
||||||
EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const;
|
EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const;
|
||||||
EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const; // B*e, e is 32 bytes Little Endian
|
EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const; // B*e, e is 32 bytes Little Endian
|
||||||
EDDSAPoint Normalize (const EDDSAPoint& p, BN_CTX * ctx) const;
|
EDDSAPoint Normalize (const EDDSAPoint& p, BN_CTX * ctx) const;
|
||||||
|
|
||||||
bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const;
|
bool IsOnCurve (const EDDSAPoint& p, BN_CTX * ctx) const;
|
||||||
BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const;
|
BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const;
|
||||||
EDDSAPoint DecodePoint (const uint8_t * buf, BN_CTX * ctx) const;
|
EDDSAPoint DecodePoint (const uint8_t * buf, BN_CTX * ctx) const;
|
||||||
void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const;
|
void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const;
|
||||||
|
@ -109,7 +109,7 @@ namespace crypto
|
||||||
|
|
||||||
#if !OPENSSL_X25519
|
#if !OPENSSL_X25519
|
||||||
// for x25519
|
// for x25519
|
||||||
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
|
BIGNUM * ScalarMul (const BIGNUM * p, const BIGNUM * e, BN_CTX * ctx) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -121,13 +121,11 @@ namespace crypto
|
||||||
// if j > 128 we use 256 - j and carry 1 to next byte
|
// if j > 128 we use 256 - j and carry 1 to next byte
|
||||||
// Bi256[0][0] = B, base point
|
// Bi256[0][0] = B, base point
|
||||||
EDDSAPoint Bi256Carry; // Bi256[32][0]
|
EDDSAPoint Bi256Carry; // Bi256[32][0]
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Ed25519>& GetEd25519 ();
|
std::unique_ptr<Ed25519>& GetEd25519 ();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
|
|
||||||
Elligator2::Elligator2 ()
|
Elligator2::Elligator2 ()
|
||||||
{
|
{
|
||||||
// TODO: share with Ed22519
|
// TODO: share with Ed22519
|
||||||
|
@ -21,32 +21,32 @@ namespace crypto
|
||||||
A = BN_new (); BN_set_word (A, 486662);
|
A = BN_new (); BN_set_word (A, 486662);
|
||||||
nA = BN_new (); BN_sub (nA, p, A);
|
nA = BN_new (); BN_sub (nA, p, A);
|
||||||
|
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
// calculate sqrt(-1)
|
// calculate sqrt(-1)
|
||||||
sqrtn1 = BN_new ();
|
sqrtn1 = BN_new ();
|
||||||
BN_set_word (sqrtn1, 2);
|
BN_set_word (sqrtn1, 2);
|
||||||
BN_mod_exp (sqrtn1, sqrtn1, p14, p, ctx); // 2^((p-1)/4
|
BN_mod_exp (sqrtn1, sqrtn1, p14, p, ctx); // 2^((p-1)/4
|
||||||
|
|
||||||
u = BN_new (); BN_set_word (u, 2);
|
u = BN_new (); BN_set_word (u, 2);
|
||||||
iu = BN_new (); BN_mod_inverse (iu, u, p, ctx);
|
iu = BN_new (); BN_mod_inverse (iu, u, p, ctx);
|
||||||
|
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
Elligator2::~Elligator2 ()
|
Elligator2::~Elligator2 ()
|
||||||
{
|
{
|
||||||
BN_free (p); BN_free (p38); BN_free (p12); BN_free (p14);
|
BN_free (p); BN_free (p38); BN_free (p12); BN_free (p14);
|
||||||
BN_free (sqrtn1); BN_free (A); BN_free (nA);
|
BN_free (sqrtn1); BN_free (A); BN_free (nA);
|
||||||
BN_free (u); BN_free (iu);
|
BN_free (u); BN_free (iu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
|
bool Elligator2::Encode (const uint8_t * key, uint8_t * encoded, bool highY, bool random) const
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
|
|
||||||
uint8_t key1[32];
|
uint8_t key1[32];
|
||||||
for (size_t i = 0; i < 16; i++) // from Little Endian
|
for (size_t i = 0; i < 16; i++) // from Little Endian
|
||||||
{
|
{
|
||||||
key1[i] = key[31 - i];
|
key1[i] = key[31 - i];
|
||||||
|
@ -59,35 +59,35 @@ namespace crypto
|
||||||
|
|
||||||
BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA
|
BIGNUM * uxxA = BN_CTX_get (ctx); // u*x*xA
|
||||||
BN_mod_mul (uxxA, u, x, p, ctx);
|
BN_mod_mul (uxxA, u, x, p, ctx);
|
||||||
BN_mod_mul (uxxA, uxxA, xA, p, ctx);
|
BN_mod_mul (uxxA, uxxA, xA, p, ctx);
|
||||||
|
|
||||||
if (Legendre (uxxA, ctx) != -1)
|
if (Legendre (uxxA, ctx) != -1)
|
||||||
{
|
{
|
||||||
uint8_t randByte = 0; // random highest bits and high y
|
uint8_t randByte = 0; // random highest bits and high y
|
||||||
if (random)
|
if (random)
|
||||||
{
|
{
|
||||||
RAND_bytes (&randByte, 1);
|
RAND_bytes (&randByte, 1);
|
||||||
highY = randByte & 0x01;
|
highY = randByte & 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
BIGNUM * r = BN_CTX_get (ctx);
|
BIGNUM * r = BN_CTX_get (ctx);
|
||||||
if (highY)
|
if (highY)
|
||||||
{
|
{
|
||||||
BN_mod_inverse (r, x, p, ctx);
|
BN_mod_inverse (r, x, p, ctx);
|
||||||
BN_mod_mul (r, r, xA, p, ctx);
|
BN_mod_mul (r, r, xA, p, ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BN_mod_inverse (r, xA, p, ctx);
|
BN_mod_inverse (r, xA, p, ctx);
|
||||||
BN_mod_mul (r, r, x, p, ctx);
|
BN_mod_mul (r, r, x, p, ctx);
|
||||||
}
|
}
|
||||||
BN_mod_mul (r, r, iu, p, ctx);
|
BN_mod_mul (r, r, iu, p, ctx);
|
||||||
|
|
||||||
SquareRoot (r, r, ctx);
|
SquareRoot (r, r, ctx);
|
||||||
bn2buf (r, encoded, 32);
|
bn2buf (r, encoded, 32);
|
||||||
|
|
||||||
if (random)
|
if (random)
|
||||||
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
|
encoded[0] |= (randByte & 0xC0); // copy two highest bits from randByte
|
||||||
for (size_t i = 0; i < 16; i++) // To Little Endian
|
for (size_t i = 0; i < 16; i++) // To Little Endian
|
||||||
{
|
{
|
||||||
uint8_t tmp = encoded[i];
|
uint8_t tmp = encoded[i];
|
||||||
|
@ -98,7 +98,7 @@ namespace crypto
|
||||||
else
|
else
|
||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -109,31 +109,31 @@ namespace crypto
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
|
|
||||||
uint8_t encoded1[32];
|
uint8_t encoded1[32];
|
||||||
for (size_t i = 0; i < 16; i++) // from Little Endian
|
for (size_t i = 0; i < 16; i++) // from Little Endian
|
||||||
{
|
{
|
||||||
encoded1[i] = encoded[31 - i];
|
encoded1[i] = encoded[31 - i];
|
||||||
encoded1[31 - i] = encoded[i];
|
encoded1[31 - i] = encoded[i];
|
||||||
}
|
}
|
||||||
encoded1[0] &= 0x3F; // drop two highest bits
|
encoded1[0] &= 0x3F; // drop two highest bits
|
||||||
|
|
||||||
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
|
BIGNUM * r = BN_CTX_get (ctx); BN_bin2bn (encoded1, 32, r);
|
||||||
|
|
||||||
if (BN_cmp (r, p12) <= 0) // r < (p-1)/2
|
if (BN_cmp (r, p12) <= 0) // r < (p-1)/2
|
||||||
{
|
{
|
||||||
// v = -A/(1+u*r^2)
|
// v = -A/(1+u*r^2)
|
||||||
BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx);
|
BIGNUM * v = BN_CTX_get (ctx); BN_mod_sqr (v, r, p, ctx);
|
||||||
BN_mod_mul (v, v, u, p, ctx);
|
BN_mod_mul (v, v, u, p, ctx);
|
||||||
BN_add_word (v, 1);
|
BN_add_word (v, 1);
|
||||||
BN_mod_inverse (v, v, p, ctx);
|
BN_mod_inverse (v, v, p, ctx);
|
||||||
BN_mod_mul (v, v, nA, p, ctx);
|
BN_mod_mul (v, v, nA, p, ctx);
|
||||||
|
|
||||||
BIGNUM * vpA = BN_CTX_get (ctx);
|
BIGNUM * vpA = BN_CTX_get (ctx);
|
||||||
BN_add (vpA, v, A); // v + A
|
BN_add (vpA, v, A); // v + A
|
||||||
// t = v^3+A*v^2+v = v^2*(v+A)+v
|
// t = v^3+A*v^2+v = v^2*(v+A)+v
|
||||||
BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx);
|
BIGNUM * t = BN_CTX_get (ctx); BN_mod_sqr (t, v, p, ctx);
|
||||||
BN_mod_mul (t, t, vpA, p, ctx);
|
BN_mod_mul (t, t, vpA, p, ctx);
|
||||||
BN_mod_add (t, t, v, p, ctx);
|
BN_mod_add (t, t, v, p, ctx);
|
||||||
|
|
||||||
int legendre = Legendre (t, ctx);
|
int legendre = Legendre (t, ctx);
|
||||||
BIGNUM * x = BN_CTX_get (ctx);
|
BIGNUM * x = BN_CTX_get (ctx);
|
||||||
|
@ -143,9 +143,9 @@ namespace crypto
|
||||||
{
|
{
|
||||||
BN_sub (x, p, v);
|
BN_sub (x, p, v);
|
||||||
BN_mod_sub (x, x, A, p, ctx);
|
BN_mod_sub (x, x, A, p, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bn2buf (x, key, 32);
|
bn2buf (x, key, 32);
|
||||||
for (size_t i = 0; i < 16; i++) // To Little Endian
|
for (size_t i = 0; i < 16; i++) // To Little Endian
|
||||||
{
|
{
|
||||||
uint8_t tmp = key[i];
|
uint8_t tmp = key[i];
|
||||||
|
@ -156,7 +156,7 @@ namespace crypto
|
||||||
else
|
else
|
||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -170,21 +170,21 @@ namespace crypto
|
||||||
BN_add_word (t, 1);
|
BN_add_word (t, 1);
|
||||||
|
|
||||||
if (!BN_cmp (t, p))
|
if (!BN_cmp (t, p))
|
||||||
BN_mod_mul (r, r, sqrtn1, p, ctx);
|
BN_mod_mul (r, r, sqrtn1, p, ctx);
|
||||||
|
|
||||||
if (BN_cmp (r, p12) > 0) // r > (p-1)/2
|
if (BN_cmp (r, p12) > 0) // r > (p-1)/2
|
||||||
BN_sub (r, p, r);
|
BN_sub (r, p, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const
|
int Elligator2::Legendre (const BIGNUM * a, BN_CTX * ctx) const
|
||||||
{
|
{
|
||||||
// assume a < p, so don't check for a % p = 0, but a = 0 only
|
// assume a < p, so don't check for a % p = 0, but a = 0 only
|
||||||
if (BN_is_zero(a)) return 0;
|
if (BN_is_zero(a)) return 0;
|
||||||
BIGNUM * r = BN_CTX_get (ctx);
|
BIGNUM * r = BN_CTX_get (ctx);
|
||||||
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
|
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
|
||||||
if (BN_is_word(r, 1))
|
if (BN_is_word(r, 1))
|
||||||
return 1;
|
return 1;
|
||||||
else if (BN_is_zero(r))
|
else if (BN_is_zero(r))
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -204,4 +204,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ namespace crypto
|
||||||
bool Encode (const uint8_t * key, uint8_t * encoded, bool highY = false, bool random = true) const;
|
bool Encode (const uint8_t * key, uint8_t * encoded, bool highY = false, bool random = true) const;
|
||||||
bool Decode (const uint8_t * encoded, uint8_t * key) const;
|
bool Decode (const uint8_t * encoded, uint8_t * key) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const;
|
void SquareRoot (const BIGNUM * x, BIGNUM * r, BN_CTX * ctx) const;
|
||||||
int Legendre (const BIGNUM * a, BN_CTX * ctx) const; // a/p
|
int Legendre (const BIGNUM * a, BN_CTX * ctx) const; // a/p
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
BIGNUM * p, * p38, * p12, * p14, * sqrtn1, * A, * nA, * u, * iu;
|
BIGNUM * p, * p38, * p12, * p14, * sqrtn1, * A, * nA, * u, * iu;
|
||||||
|
@ -35,5 +35,3 @@ namespace crypto
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
221
libi2pd/FS.h
221
libi2pd/FS.h
|
@ -17,133 +17,136 @@
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace fs {
|
namespace fs {
|
||||||
extern std::string dirSep;
|
extern std::string dirSep;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class to work with NetDb & Router profiles
|
* @brief Class to work with NetDb & Router profiles
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
*
|
*
|
||||||
* const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
|
* const char alphabet[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
|
||||||
* auto h = HashedStorage("name", "y", "z-", ".txt");
|
* auto h = HashedStorage("name", "y", "z-", ".txt");
|
||||||
* h.SetPlace("/tmp/hs-test");
|
* h.SetPlace("/tmp/hs-test");
|
||||||
* h.GetName() -> gives "name"
|
* h.GetName() -> gives "name"
|
||||||
* h.GetRoot() -> gives "/tmp/hs-test/name"
|
* h.GetRoot() -> gives "/tmp/hs-test/name"
|
||||||
* h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
|
* h.Init(alphabet, 8); <- creates needed dirs, 8 is size of alphabet
|
||||||
* h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt
|
* h.Path("abcd"); <- returns /tmp/hs-test/name/ya/z-abcd.txt
|
||||||
* h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
|
* h.Remove("abcd"); <- removes /tmp/hs-test/name/ya/z-abcd.txt, if it exists
|
||||||
* std::vector<std::string> files;
|
* std::vector<std::string> files;
|
||||||
* h.Traverse(files); <- finds all files in storage and saves in given vector
|
* h.Traverse(files); <- finds all files in storage and saves in given vector
|
||||||
*/
|
*/
|
||||||
class HashedStorage {
|
class HashedStorage
|
||||||
protected:
|
{
|
||||||
std::string root; /**< path to storage with it's name included */
|
protected:
|
||||||
std::string name; /**< name of the storage */
|
|
||||||
std::string prefix1; /**< hashed directory prefix */
|
|
||||||
std::string prefix2; /**< prefix of file in storage */
|
|
||||||
std::string suffix; /**< suffix of file in storage (extension) */
|
|
||||||
|
|
||||||
public:
|
std::string root; /**< path to storage with it's name included */
|
||||||
typedef std::function<void(const std::string &)> FilenameVisitor;
|
std::string name; /**< name of the storage */
|
||||||
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
|
std::string prefix1; /**< hashed directory prefix */
|
||||||
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
|
std::string prefix2; /**< prefix of file in storage */
|
||||||
|
std::string suffix; /**< suffix of file in storage (extension) */
|
||||||
|
|
||||||
/** create subdirs in storage */
|
public:
|
||||||
bool Init(const char* chars, size_t cnt);
|
|
||||||
const std::string & GetRoot() const { return root; }
|
|
||||||
const std::string & GetName() const { return name; }
|
|
||||||
/** set directory where to place storage directory */
|
|
||||||
void SetPlace(const std::string & path);
|
|
||||||
/** path to file with given ident */
|
|
||||||
std::string Path(const std::string & ident) const;
|
|
||||||
/** remove file by ident */
|
|
||||||
void Remove(const std::string & ident);
|
|
||||||
/** find all files in storage and store list in provided vector */
|
|
||||||
void Traverse(std::vector<std::string> & files);
|
|
||||||
/** visit every file in this storage with a visitor */
|
|
||||||
void Iterate(FilenameVisitor v);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** @brief Returns current application name, default 'i2pd' */
|
typedef std::function<void(const std::string &)> FilenameVisitor;
|
||||||
|
HashedStorage(const char *n, const char *p1, const char *p2, const char *s):
|
||||||
|
name(n), prefix1(p1), prefix2(p2), suffix(s) {};
|
||||||
|
|
||||||
|
/** create subdirs in storage */
|
||||||
|
bool Init(const char* chars, size_t cnt);
|
||||||
|
const std::string & GetRoot() const { return root; }
|
||||||
|
const std::string & GetName() const { return name; }
|
||||||
|
/** set directory where to place storage directory */
|
||||||
|
void SetPlace(const std::string & path);
|
||||||
|
/** path to file with given ident */
|
||||||
|
std::string Path(const std::string & ident) const;
|
||||||
|
/** remove file by ident */
|
||||||
|
void Remove(const std::string & ident);
|
||||||
|
/** find all files in storage and store list in provided vector */
|
||||||
|
void Traverse(std::vector<std::string> & files);
|
||||||
|
/** visit every file in this storage with a visitor */
|
||||||
|
void Iterate(FilenameVisitor v);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @brief Returns current application name, default 'i2pd' */
|
||||||
const std::string & GetAppName ();
|
const std::string & GetAppName ();
|
||||||
/** @brief Set application name, affects autodetection of datadir */
|
/** @brief Set application name, affects autodetection of datadir */
|
||||||
void SetAppName (const std::string& name);
|
void SetAppName (const std::string& name);
|
||||||
|
|
||||||
/** @brief Returns datadir path */
|
/** @brief Returns datadir path */
|
||||||
const std::string & GetDataDir();
|
const std::string & GetDataDir();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set datadir either from cmdline option or using autodetection
|
* @brief Set datadir either from cmdline option or using autodetection
|
||||||
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
||||||
* @param isService Value of cmdline parameter --service
|
* @param isService Value of cmdline parameter --service
|
||||||
*
|
*
|
||||||
* Examples of autodetected paths:
|
* Examples of autodetected paths:
|
||||||
*
|
*
|
||||||
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
|
* Windows < Vista: C:\Documents and Settings\Username\Application Data\i2pd\
|
||||||
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
|
* Windows >= Vista: C:\Users\Username\AppData\Roaming\i2pd\
|
||||||
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
|
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
|
||||||
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
|
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
|
||||||
*/
|
*/
|
||||||
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
|
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create subdirectories inside datadir
|
* @brief Create subdirectories inside datadir
|
||||||
*/
|
*/
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get list of files in directory
|
* @brief Get list of files in directory
|
||||||
* @param path Path to directory
|
* @param path Path to directory
|
||||||
* @param files Vector to store found files
|
* @param files Vector to store found files
|
||||||
* @return true on success and false if directory not exists
|
* @return true on success and false if directory not exists
|
||||||
*/
|
*/
|
||||||
bool ReadDir(const std::string & path, std::vector<std::string> & files);
|
bool ReadDir(const std::string & path, std::vector<std::string> & files);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Remove file with given path
|
* @brief Remove file with given path
|
||||||
* @param path Absolute path to file
|
* @param path Absolute path to file
|
||||||
* @return true on success, false if file not exists, throws exception on error
|
* @return true on success, false if file not exists, throws exception on error
|
||||||
*/
|
*/
|
||||||
bool Remove(const std::string & path);
|
bool Remove(const std::string & path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check existence of file
|
* @brief Check existence of file
|
||||||
* @param path Absolute path to file
|
* @param path Absolute path to file
|
||||||
* @return true if file exists, false otherwise
|
* @return true if file exists, false otherwise
|
||||||
*/
|
*/
|
||||||
bool Exists(const std::string & path);
|
bool Exists(const std::string & path);
|
||||||
|
|
||||||
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
|
uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch
|
||||||
|
|
||||||
bool CreateDirectory (const std::string& path);
|
bool CreateDirectory (const std::string& path);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void _ExpandPath(std::stringstream & path, T c) {
|
void _ExpandPath(std::stringstream & path, T c) {
|
||||||
path << i2p::fs::dirSep << c;
|
path << i2p::fs::dirSep << c;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ... Other>
|
template<typename T, typename ... Other>
|
||||||
void _ExpandPath(std::stringstream & path, T c, Other ... other) {
|
void _ExpandPath(std::stringstream & path, T c, Other ... other) {
|
||||||
_ExpandPath(path, c);
|
_ExpandPath(path, c);
|
||||||
_ExpandPath(path, other ...);
|
_ExpandPath(path, other ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get path relative to datadir
|
* @brief Get path relative to datadir
|
||||||
*
|
*
|
||||||
* Examples (with datadir = "/tmp/i2pd"):
|
* Examples (with datadir = "/tmp/i2pd"):
|
||||||
*
|
*
|
||||||
* i2p::fs::Path("test") -> '/tmp/i2pd/test'
|
* i2p::fs::Path("test") -> '/tmp/i2pd/test'
|
||||||
* i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
|
* i2p::fs::Path("test", "file.txt") -> '/tmp/i2pd/test/file.txt'
|
||||||
*/
|
*/
|
||||||
template<typename ... Other>
|
template<typename ... Other>
|
||||||
std::string DataDirPath(Other ... components) {
|
std::string DataDirPath(Other ... components) {
|
||||||
std::stringstream s("");
|
std::stringstream s("");
|
||||||
s << i2p::fs::GetDataDir();
|
s << i2p::fs::GetDataDir();
|
||||||
_ExpandPath(s, components ...);
|
_ExpandPath(s, components ...);
|
||||||
|
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Storage, typename... Filename>
|
template<typename Storage, typename... Filename>
|
||||||
std::string StorageRootPath (const Storage& storage, Filename... filenames)
|
std::string StorageRootPath (const Storage& storage, Filename... filenames)
|
||||||
|
|
|
@ -179,4 +179,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ namespace garlic
|
||||||
if (!m_SharedRoutingPath) return nullptr;
|
if (!m_SharedRoutingPath) return nullptr;
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
|
if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED ||
|
||||||
!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
|
!m_SharedRoutingPath->outboundTunnel->IsEstablished () ||
|
||||||
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
|
ts*1000LL > m_SharedRoutingPath->remoteLease->endDate ||
|
||||||
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
|
ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT)
|
||||||
m_SharedRoutingPath = nullptr;
|
m_SharedRoutingPath = nullptr;
|
||||||
if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
|
if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++;
|
||||||
return m_SharedRoutingPath;
|
return m_SharedRoutingPath;
|
||||||
|
@ -68,7 +68,7 @@ namespace garlic
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts)
|
void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts)
|
||||||
{
|
{
|
||||||
|
@ -78,8 +78,8 @@ namespace garlic
|
||||||
GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID);
|
GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID);
|
||||||
m_LeaseSetUpdateMsgID = 0;
|
m_LeaseSetUpdateMsgID = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> GarlicRoutingSession::CreateEncryptedDeliveryStatusMsg (uint32_t msgID)
|
std::shared_ptr<I2NPMessage> GarlicRoutingSession::CreateEncryptedDeliveryStatusMsg (uint32_t msgID)
|
||||||
{
|
{
|
||||||
auto msg = CreateDeliveryStatusMsg (msgID);
|
auto msg = CreateDeliveryStatusMsg (msgID);
|
||||||
|
@ -94,12 +94,12 @@ namespace garlic
|
||||||
msg = garlic.WrapSingleMessage (msg);
|
msg = garlic.WrapSingleMessage (msg);
|
||||||
}
|
}
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
|
ElGamalAESSession::ElGamalAESSession (GarlicDestination * owner,
|
||||||
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
|
std::shared_ptr<const i2p::data::RoutingDestination> destination, int numTags, bool attachLeaseSet):
|
||||||
GarlicRoutingSession (owner, attachLeaseSet),
|
GarlicRoutingSession (owner, attachLeaseSet),
|
||||||
m_Destination (destination), m_NumTags (numTags)
|
m_Destination (destination), m_NumTags (numTags)
|
||||||
{
|
{
|
||||||
// create new session tags and session key
|
// create new session tags and session key
|
||||||
RAND_bytes (m_SessionKey, 32);
|
RAND_bytes (m_SessionKey, 32);
|
||||||
|
@ -115,7 +115,7 @@ namespace garlic
|
||||||
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
|
m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
std::shared_ptr<I2NPMessage> ElGamalAESSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
auto m = NewI2NPMessage ();
|
auto m = NewI2NPMessage ();
|
||||||
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
|
||||||
|
@ -181,7 +181,7 @@ namespace garlic
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
|
size_t ElGamalAESSession::CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
size_t blockSize = 0;
|
size_t blockSize = 0;
|
||||||
bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
|
bool createNewTags = GetOwner () && m_NumTags && ((int)m_SessionTags.size () <= m_NumTags*2/3);
|
||||||
|
@ -329,10 +329,10 @@ namespace garlic
|
||||||
// create msg
|
// create msg
|
||||||
auto msg = CreateEncryptedDeliveryStatusMsg (msgID);
|
auto msg = CreateEncryptedDeliveryStatusMsg (msgID);
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
|
memcpy (buf + size, msg->GetBuffer (), msg->GetLength ());
|
||||||
size += msg->GetLength ();
|
size += msg->GetLength ();
|
||||||
}
|
}
|
||||||
// fill clove
|
// fill clove
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch () + 8000; // 8 sec
|
||||||
uint32_t cloveID;
|
uint32_t cloveID;
|
||||||
|
@ -353,7 +353,7 @@ namespace garlic
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
|
ElGamalAESSession::UnconfirmedTags * ElGamalAESSession::GenerateSessionTags ()
|
||||||
{
|
{
|
||||||
auto tags = new UnconfirmedTags (m_NumTags);
|
auto tags = new UnconfirmedTags (m_NumTags);
|
||||||
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
|
tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
@ -487,7 +487,7 @@ namespace garlic
|
||||||
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
|
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
{
|
{
|
||||||
|
@ -500,15 +500,15 @@ namespace garlic
|
||||||
found = true;
|
found = true;
|
||||||
auto session = it1->second.tagset->GetSession ();
|
auto session = it1->second.tagset->GetSession ();
|
||||||
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
if (!session || !session->HandleNextMessage (buf, length, it1->second.tagset, it1->second.index))
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
m_ECIESx25519Tags.erase (it1);
|
m_ECIESx25519Tags.erase (it1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) // assume new session
|
if (!found) // assume new session
|
||||||
{
|
{
|
||||||
// AES tag not found. Handle depending on encryption type
|
// AES tag not found. Handle depending on encryption type
|
||||||
// try ElGamal/AES first if leading block is 514
|
// try ElGamal/AES first if leading block is 514
|
||||||
ElGamalBlock elGamal;
|
ElGamalBlock elGamal;
|
||||||
if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
|
if (mod == 2 && length >= 514 && SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) &&
|
||||||
Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
|
Decrypt (buf, (uint8_t *)&elGamal, m_Ctx, i2p::data::CRYPTO_KEY_TYPE_ELGAMAL))
|
||||||
|
@ -521,16 +521,16 @@ namespace garlic
|
||||||
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
HandleAESBlock (buf + 514, length - 514, decryption, msg->from);
|
||||||
}
|
}
|
||||||
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
else if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
{
|
{
|
||||||
// otherwise ECIESx25519
|
// otherwise ECIESx25519
|
||||||
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
||||||
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr<AESDecryption> decryption,
|
||||||
|
@ -703,41 +703,41 @@ namespace garlic
|
||||||
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
|
std::shared_ptr<GarlicRoutingSession> GarlicDestination::GetRoutingSession (
|
||||||
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
|
std::shared_ptr<const i2p::data::RoutingDestination> destination, bool attachLeaseSet)
|
||||||
{
|
{
|
||||||
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
|
if (destination->GetEncryptionType () == i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET &&
|
||||||
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET))
|
||||||
{
|
{
|
||||||
ECIESX25519AEADRatchetSessionPtr session;
|
ECIESX25519AEADRatchetSessionPtr session;
|
||||||
uint8_t staticKey[32];
|
uint8_t staticKey[32];
|
||||||
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
|
destination->Encrypt (nullptr, staticKey, nullptr); // we are supposed to get static key
|
||||||
auto it = m_ECIESx25519Sessions.find (staticKey);
|
auto it = m_ECIESx25519Sessions.find (staticKey);
|
||||||
if (it != m_ECIESx25519Sessions.end ())
|
if (it != m_ECIESx25519Sessions.end ())
|
||||||
session = it->second;
|
session = it->second;
|
||||||
if (!session)
|
if (!session)
|
||||||
{
|
{
|
||||||
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
|
session = std::make_shared<ECIESX25519AEADRatchetSession> (this, true);
|
||||||
session->SetRemoteStaticKey (staticKey);
|
session->SetRemoteStaticKey (staticKey);
|
||||||
}
|
}
|
||||||
session->SetDestination (destination->GetIdentHash ()); // TODO: remove
|
session->SetDestination (destination->GetIdentHash ()); // TODO: remove
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ElGamalAESSessionPtr session;
|
ElGamalAESSessionPtr session;
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
||||||
auto it = m_Sessions.find (destination->GetIdentHash ());
|
auto it = m_Sessions.find (destination->GetIdentHash ());
|
||||||
if (it != m_Sessions.end ())
|
if (it != m_Sessions.end ())
|
||||||
session = it->second;
|
session = it->second;
|
||||||
}
|
}
|
||||||
if (!session)
|
if (!session)
|
||||||
{
|
{
|
||||||
session = std::make_shared<ElGamalAESSession> (this, destination,
|
session = std::make_shared<ElGamalAESSession> (this, destination,
|
||||||
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
|
attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests
|
||||||
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
std::unique_lock<std::mutex> l(m_SessionsMutex);
|
||||||
m_Sessions[destination->GetIdentHash ()] = session;
|
m_Sessions[destination->GetIdentHash ()] = session;
|
||||||
}
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::CleanupExpiredTags ()
|
void GarlicDestination::CleanupExpiredTags ()
|
||||||
|
@ -791,7 +791,7 @@ namespace garlic
|
||||||
if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
if (it->second.tagset->IsExpired (ts) || ts > it->second.creationTime + ECIESX25519_INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
it = m_ECIESx25519Tags.erase (it);
|
it = m_ECIESx25519Tags.erase (it);
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();)
|
for (auto it = m_ECIESx25519Sessions.begin (); it != m_ECIESx25519Sessions.end ();)
|
||||||
|
@ -800,7 +800,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
it->second->SetOwner (nullptr);
|
it->second->SetOwner (nullptr);
|
||||||
it = m_ECIESx25519Sessions.erase (it);
|
it = m_ECIESx25519Sessions.erase (it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -925,28 +925,28 @@ namespace garlic
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
|
i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files);
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
for (auto it: files)
|
for (auto it: files)
|
||||||
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
i2p::fs::Remove (it);
|
i2p::fs::Remove (it);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
const uint8_t * buf1 = buf;
|
const uint8_t * buf1 = buf;
|
||||||
uint8_t flag = buf[0]; buf++; // flag
|
uint8_t flag = buf[0]; buf++; // flag
|
||||||
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
|
GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03);
|
||||||
switch (deliveryType)
|
switch (deliveryType)
|
||||||
{
|
{
|
||||||
case eGarlicDeliveryTypeDestination:
|
case eGarlicDeliveryTypeDestination:
|
||||||
LogPrint (eLogDebug, "Garlic: type destination");
|
LogPrint (eLogDebug, "Garlic: type destination");
|
||||||
buf += 32; // TODO: check destination
|
buf += 32; // TODO: check destination
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
// no break here
|
// no break here
|
||||||
case eGarlicDeliveryTypeLocal:
|
case eGarlicDeliveryTypeLocal:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: type local");
|
LogPrint (eLogDebug, "Garlic: type local");
|
||||||
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
||||||
buf += (4 + 4); // msgID + expiration
|
buf += (4 + 4); // msgID + expiration
|
||||||
ptrdiff_t offset = buf - buf1;
|
ptrdiff_t offset = buf - buf1;
|
||||||
|
@ -957,8 +957,8 @@ namespace garlic
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eGarlicDeliveryTypeTunnel:
|
case eGarlicDeliveryTypeTunnel:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: type tunnel");
|
LogPrint (eLogDebug, "Garlic: type tunnel");
|
||||||
// gwHash and gwTunnel sequence is reverted
|
// gwHash and gwTunnel sequence is reverted
|
||||||
const uint8_t * gwHash = buf;
|
const uint8_t * gwHash = buf;
|
||||||
buf += 32;
|
buf += 32;
|
||||||
|
@ -968,47 +968,47 @@ namespace garlic
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
|
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
|
||||||
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
||||||
buf += (4 + 4); // msgID + expiration
|
buf += (4 + 4); // msgID + expiration
|
||||||
offset += 13;
|
offset += 13;
|
||||||
if (GetTunnelPool ())
|
if (GetTunnelPool ())
|
||||||
{
|
{
|
||||||
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
|
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
|
||||||
if (tunnel)
|
if (tunnel)
|
||||||
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
|
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset));
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
|
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
|
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
|
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
|
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
|
||||||
{
|
{
|
||||||
auto index = tagset->GetNextIndex ();
|
auto index = tagset->GetNextIndex ();
|
||||||
uint64_t tag = tagset->GetNextSessionTag ();
|
uint64_t tag = tagset->GetNextSessionTag ();
|
||||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
|
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset, i2p::util::GetSecondsSinceEpoch ()});
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
||||||
{
|
{
|
||||||
i2p::data::Tag<32> staticKeyTag (staticKey);
|
i2p::data::Tag<32> staticKeyTag (staticKey);
|
||||||
auto it = m_ECIESx25519Sessions.find (staticKeyTag);
|
auto it = m_ECIESx25519Sessions.find (staticKeyTag);
|
||||||
if (it != m_ECIESx25519Sessions.end ())
|
if (it != m_ECIESx25519Sessions.end ())
|
||||||
{
|
{
|
||||||
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
|
if (it->second->CanBeRestarted (i2p::util::GetSecondsSinceEpoch ()))
|
||||||
m_ECIESx25519Sessions.erase (it);
|
m_ECIESx25519Sessions.erase (it);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_ECIESx25519Sessions.emplace (staticKeyTag, session);
|
m_ECIESx25519Sessions.emplace (staticKeyTag, session);
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1020,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
it->second->SetOwner (nullptr);
|
it->second->SetOwner (nullptr);
|
||||||
m_ECIESx25519Sessions.erase (it);
|
m_ECIESx25519Sessions.erase (it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
106
libi2pd/Garlic.h
106
libi2pd/Garlic.h
|
@ -87,8 +87,8 @@ namespace garlic
|
||||||
class GarlicDestination;
|
class GarlicDestination;
|
||||||
class GarlicRoutingSession
|
class GarlicRoutingSession
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enum LeaseSetUpdateStatus
|
enum LeaseSetUpdateStatus
|
||||||
{
|
{
|
||||||
eLeaseSetUpToDate = 0,
|
eLeaseSetUpToDate = 0,
|
||||||
|
@ -103,10 +103,10 @@ namespace garlic
|
||||||
GarlicRoutingSession ();
|
GarlicRoutingSession ();
|
||||||
virtual ~GarlicRoutingSession ();
|
virtual ~GarlicRoutingSession ();
|
||||||
virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
|
virtual std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg) = 0;
|
||||||
virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
|
virtual bool CleanupUnconfirmedTags () { return false; }; // for I2CP, override in ElGamalAESSession
|
||||||
virtual bool MessageConfirmed (uint32_t msgID);
|
virtual bool MessageConfirmed (uint32_t msgID);
|
||||||
virtual bool IsRatchets () const { return false; };
|
virtual bool IsRatchets () const { return false; };
|
||||||
|
|
||||||
void SetLeaseSetUpdated ()
|
void SetLeaseSetUpdated ()
|
||||||
{
|
{
|
||||||
if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated;
|
if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated;
|
||||||
|
@ -115,23 +115,23 @@ namespace garlic
|
||||||
bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; };
|
bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; };
|
||||||
uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; }
|
uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; }
|
||||||
void CleanupUnconfirmedLeaseSet (uint64_t ts);
|
void CleanupUnconfirmedLeaseSet (uint64_t ts);
|
||||||
|
|
||||||
std::shared_ptr<GarlicRoutingPath> GetSharedRoutingPath ();
|
std::shared_ptr<GarlicRoutingPath> GetSharedRoutingPath ();
|
||||||
void SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path);
|
void SetSharedRoutingPath (std::shared_ptr<GarlicRoutingPath> path);
|
||||||
|
|
||||||
GarlicDestination * GetOwner () const { return m_Owner; }
|
GarlicDestination * GetOwner () const { return m_Owner; }
|
||||||
void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
|
void SetOwner (GarlicDestination * owner) { m_Owner = owner; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
|
LeaseSetUpdateStatus GetLeaseSetUpdateStatus () const { return m_LeaseSetUpdateStatus; }
|
||||||
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
|
void SetLeaseSetUpdateStatus (LeaseSetUpdateStatus status) { m_LeaseSetUpdateStatus = status; }
|
||||||
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
|
uint32_t GetLeaseSetUpdateMsgID () const { return m_LeaseSetUpdateMsgID; }
|
||||||
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
|
void SetLeaseSetUpdateMsgID (uint32_t msgID) { m_LeaseSetUpdateMsgID = msgID; }
|
||||||
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
|
void SetLeaseSetSubmissionTime (uint64_t ts) { m_LeaseSetSubmissionTime = ts; }
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID);
|
std::shared_ptr<I2NPMessage> CreateEncryptedDeliveryStatusMsg (uint32_t msgID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
GarlicDestination * m_Owner;
|
GarlicDestination * m_Owner;
|
||||||
|
@ -143,38 +143,39 @@ namespace garlic
|
||||||
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
std::shared_ptr<GarlicRoutingPath> m_SharedRoutingPath;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
virtual size_t GetNumOutgoingTags () const { return 0; };
|
virtual size_t GetNumOutgoingTags () const { return 0; };
|
||||||
};
|
};
|
||||||
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
|
//using GarlicRoutingSessionPtr = std::shared_ptr<GarlicRoutingSession>;
|
||||||
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
|
typedef std::shared_ptr<GarlicRoutingSession> GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8
|
||||||
|
|
||||||
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
|
class ElGamalAESSession: public GarlicRoutingSession, public std::enable_shared_from_this<ElGamalAESSession>
|
||||||
{
|
{
|
||||||
struct UnconfirmedTags
|
struct UnconfirmedTags
|
||||||
{
|
{
|
||||||
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
|
UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; };
|
||||||
~UnconfirmedTags () { delete[] sessionTags; };
|
~UnconfirmedTags () { delete[] sessionTags; };
|
||||||
uint32_t msgID;
|
uint32_t msgID;
|
||||||
int numTags;
|
int numTags;
|
||||||
SessionTag * sessionTags;
|
SessionTag * sessionTags;
|
||||||
uint32_t tagsCreationTime;
|
uint32_t tagsCreationTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
ElGamalAESSession (GarlicDestination * owner, std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||||
int numTags, bool attachLeaseSet);
|
int numTags, bool attachLeaseSet);
|
||||||
ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
|
ElGamalAESSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption
|
||||||
~ElGamalAESSession () {};
|
~ElGamalAESSession () {};
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
bool MessageConfirmed (uint32_t msgID);
|
bool MessageConfirmed (uint32_t msgID);
|
||||||
bool CleanupExpiredTags (); // returns true if something left
|
bool CleanupExpiredTags (); // returns true if something left
|
||||||
bool CleanupUnconfirmedTags (); // returns true if something has been deleted
|
bool CleanupUnconfirmedTags (); // returns true if something has been deleted
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
|
size_t CreateAESBlock (uint8_t * buf, std::shared_ptr<const I2NPMessage> msg);
|
||||||
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
|
size_t CreateGarlicPayload (uint8_t * payload, std::shared_ptr<const I2NPMessage> msg, UnconfirmedTags * newTags);
|
||||||
|
@ -183,32 +184,33 @@ namespace garlic
|
||||||
|
|
||||||
void TagsConfirmed (uint32_t msgID);
|
void TagsConfirmed (uint32_t msgID);
|
||||||
UnconfirmedTags * GenerateSessionTags ();
|
UnconfirmedTags * GenerateSessionTags ();
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
|
|
||||||
|
|
||||||
i2p::crypto::AESKey m_SessionKey;
|
private:
|
||||||
|
|
||||||
|
std::shared_ptr<const i2p::data::RoutingDestination> m_Destination;
|
||||||
|
|
||||||
|
i2p::crypto::AESKey m_SessionKey;
|
||||||
std::list<SessionTag> m_SessionTags;
|
std::list<SessionTag> m_SessionTags;
|
||||||
int m_NumTags;
|
int m_NumTags;
|
||||||
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
|
std::map<uint32_t, std::unique_ptr<UnconfirmedTags> > m_UnconfirmedTagsMsgs; // msgID->tags
|
||||||
|
|
||||||
i2p::crypto::CBCEncryption m_Encryption;
|
i2p::crypto::CBCEncryption m_Encryption;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
public:
|
|
||||||
// for HTTP only
|
// for HTTP only
|
||||||
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
size_t GetNumOutgoingTags () const { return m_SessionTags.size (); };
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
|
typedef std::shared_ptr<ElGamalAESSession> ElGamalAESSessionPtr;
|
||||||
|
|
||||||
class ECIESX25519AEADRatchetSession;
|
class ECIESX25519AEADRatchetSession;
|
||||||
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
|
typedef std::shared_ptr<ECIESX25519AEADRatchetSession> ECIESX25519AEADRatchetSessionPtr;
|
||||||
class RatchetTagSet;
|
class RatchetTagSet;
|
||||||
typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
|
typedef std::shared_ptr<RatchetTagSet> RatchetTagSetPtr;
|
||||||
struct ECIESX25519AEADRatchetIndexTagset
|
struct ECIESX25519AEADRatchetIndexTagset
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
RatchetTagSetPtr tagset;
|
RatchetTagSetPtr tagset;
|
||||||
uint64_t creationTime; // seconds since epoch
|
uint64_t creationTime; // seconds since epoch
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -226,12 +228,12 @@ namespace garlic
|
||||||
void CleanupExpiredTags ();
|
void CleanupExpiredTags ();
|
||||||
void RemoveDeliveryStatusSession (uint32_t msgID);
|
void RemoveDeliveryStatusSession (uint32_t msgID);
|
||||||
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
std::shared_ptr<I2NPMessage> WrapMessage (std::shared_ptr<const i2p::data::RoutingDestination> destination,
|
||||||
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
std::shared_ptr<I2NPMessage> msg, bool attachLeaseSet = false);
|
||||||
|
|
||||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||||
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||||
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
||||||
void RemoveECIESx25519Session (const uint8_t * staticKey);
|
void RemoveECIESx25519Session (const uint8_t * staticKey);
|
||||||
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
||||||
|
@ -266,10 +268,10 @@ namespace garlic
|
||||||
int m_NumTags;
|
int m_NumTags;
|
||||||
std::mutex m_SessionsMutex;
|
std::mutex m_SessionsMutex;
|
||||||
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
|
std::unordered_map<i2p::data::IdentHash, ElGamalAESSessionPtr> m_Sessions;
|
||||||
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
|
std::unordered_map<i2p::data::Tag<32>, ECIESX25519AEADRatchetSessionPtr> m_ECIESx25519Sessions; // static key -> session
|
||||||
// incoming
|
// incoming
|
||||||
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
||||||
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
|
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
|
||||||
// DeliveryStatus
|
// DeliveryStatus
|
||||||
std::mutex m_DeliveryStatusSessionsMutex;
|
std::mutex m_DeliveryStatusSessionsMutex;
|
||||||
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
||||||
|
|
|
@ -13,11 +13,11 @@ namespace crypto
|
||||||
|
|
||||||
enum GOSTR3410ParamSet
|
enum GOSTR3410ParamSet
|
||||||
{
|
{
|
||||||
eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1
|
eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1
|
||||||
// XchA = A, XchB = C
|
// XchA = A, XchB = C
|
||||||
//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
|
//eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0
|
||||||
//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
|
//eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1
|
||||||
eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1
|
eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1
|
||||||
eGOSTR3410NumParamSets
|
eGOSTR3410NumParamSets
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,13 +40,13 @@ namespace data
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Gzip: Incorrect length");
|
LogPrint (eLogError, "Gzip: Incorrect length");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (len > outLen) len = outLen;
|
if (len > outLen) len = outLen;
|
||||||
memcpy (out, in + 15, len);
|
memcpy (out, in + 15, len);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_IsDirty) inflateReset (&m_Inflator);
|
if (m_IsDirty) inflateReset (&m_Inflator);
|
||||||
m_IsDirty = true;
|
m_IsDirty = true;
|
||||||
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
m_Inflator.next_in = const_cast<uint8_t *>(in);
|
||||||
|
@ -59,7 +59,7 @@ namespace data
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
LogPrint (eLogError, "Gzip: Inflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
|
void GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& os)
|
||||||
|
@ -126,7 +126,7 @@ namespace data
|
||||||
{
|
{
|
||||||
out[9] = 0xff; // OS is always unknown
|
out[9] = 0xff; // OS is always unknown
|
||||||
return outLen - m_Deflator.avail_out;
|
return outLen - m_Deflator.avail_out;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -147,21 +147,21 @@ namespace data
|
||||||
auto flush = (it == bufs.back ()) ? Z_FINISH : Z_NO_FLUSH;
|
auto flush = (it == bufs.back ()) ? Z_FINISH : Z_NO_FLUSH;
|
||||||
err = deflate (&m_Deflator, flush);
|
err = deflate (&m_Deflator, flush);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
if (flush && err == Z_STREAM_END)
|
if (flush && err == Z_STREAM_END)
|
||||||
{
|
{
|
||||||
out[9] = 0xff; // OS is always unknown
|
out[9] = 0xff; // OS is always unknown
|
||||||
return outLen - m_Deflator.avail_out;
|
return outLen - m_Deflator.avail_out;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset = outLen - m_Deflator.avail_out;
|
offset = outLen - m_Deflator.avail_out;
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
LogPrint (eLogError, "Gzip: Deflate error ", err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen)
|
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
||||||
|
@ -176,7 +176,7 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen)
|
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
static const uint8_t gzipHeader[11] = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x01 };
|
||||||
memcpy (out, gzipHeader, 11);
|
memcpy (out, gzipHeader, 11);
|
||||||
uint32_t crc = 0;
|
uint32_t crc = 0;
|
||||||
|
@ -186,9 +186,9 @@ namespace data
|
||||||
len1 = len;
|
len1 = len;
|
||||||
len += it.second;
|
len += it.second;
|
||||||
if (outLen < len + 23) return 0;
|
if (outLen < len + 23) return 0;
|
||||||
memcpy (out + 15 + len1, it.first, it.second);
|
memcpy (out + 15 + len1, it.first, it.second);
|
||||||
crc = crc32 (crc, it.first, it.second);
|
crc = crc32 (crc, it.first, it.second);
|
||||||
}
|
}
|
||||||
if (len > 0xffff) return 0;
|
if (len > 0xffff) return 0;
|
||||||
htole32buf (out + len + 15, crc);
|
htole32buf (out + len + 15, crc);
|
||||||
htole32buf (out + len + 19, len);
|
htole32buf (out + len + 19, len);
|
||||||
|
@ -196,6 +196,6 @@ namespace data
|
||||||
htole16buf (out + 13, 0xffff - len);
|
htole16buf (out + 13, 0xffff - len);
|
||||||
return len + 23;
|
return len + 23;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
class GzipInflator
|
class GzipInflator
|
||||||
{
|
{
|
||||||
|
@ -45,7 +45,6 @@ namespace data
|
||||||
|
|
||||||
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K
|
size_t GzipNoCompression (const uint8_t * in, uint16_t inLen, uint8_t * out, size_t outLen); // for < 64K
|
||||||
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K
|
size_t GzipNoCompression (const std::vector<std::pair<const uint8_t *, size_t> >& bufs, uint8_t * out, size_t outLen); // for total size < 64K
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -180,9 +180,9 @@ namespace i2p
|
||||||
// excluded
|
// excluded
|
||||||
if (cnt > 512)
|
if (cnt > 512)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
|
LogPrint (eLogWarning, "I2NP: Too many peers to exclude ", cnt, " for DatabaseLookup");
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
htobe16buf (buf, cnt);
|
htobe16buf (buf, cnt);
|
||||||
buf += 2;
|
buf += 2;
|
||||||
if (cnt > 0)
|
if (cnt > 0)
|
||||||
|
@ -205,7 +205,7 @@ namespace i2p
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
|
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident,
|
||||||
std::vector<i2p::data::IdentHash> routers)
|
std::vector<i2p::data::IdentHash> routers)
|
||||||
{
|
{
|
||||||
auto m = NewI2NPShortMessage ();
|
auto m = NewI2NPShortMessage ();
|
||||||
uint8_t * buf = m->GetPayload ();
|
uint8_t * buf = m->GetPayload ();
|
||||||
|
@ -268,7 +268,7 @@ namespace i2p
|
||||||
auto m = NewI2NPShortMessage ();
|
auto m = NewI2NPShortMessage ();
|
||||||
uint8_t * payload = m->GetPayload ();
|
uint8_t * payload = m->GetPayload ();
|
||||||
memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32);
|
memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32);
|
||||||
payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet
|
payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet
|
||||||
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
|
htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0);
|
||||||
size_t size = DATABASE_STORE_HEADER_SIZE;
|
size_t size = DATABASE_STORE_HEADER_SIZE;
|
||||||
memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
|
memcpy (payload + size, leaseSet->GetBuffer (), leaseSet->GetBufferLen ());
|
||||||
|
@ -278,7 +278,7 @@ namespace i2p
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::LocalLeaseSet> leaseSet, uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
|
||||||
{
|
{
|
||||||
if (!leaseSet) return nullptr;
|
if (!leaseSet) return nullptr;
|
||||||
auto m = NewI2NPShortMessage ();
|
auto m = NewI2NPShortMessage ();
|
||||||
|
@ -347,11 +347,11 @@ namespace i2p
|
||||||
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
|
||||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
|
||||||
clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||||
clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
|
clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET,
|
||||||
clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
|
clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
|
||||||
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
|
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80,
|
||||||
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40);
|
clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40);
|
||||||
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
|
i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
|
||||||
record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0;
|
record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0;
|
||||||
}
|
}
|
||||||
|
@ -386,7 +386,7 @@ namespace i2p
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
|
auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID);
|
||||||
if (tunnel)
|
if (tunnel)
|
||||||
{
|
{
|
||||||
// endpoint of inbound tunnel
|
// endpoint of inbound tunnel
|
||||||
|
@ -414,7 +414,7 @@ namespace i2p
|
||||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||||
eI2NPVariableTunnelBuildReply, buf, len,
|
eI2NPVariableTunnelBuildReply, buf, len,
|
||||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
|
@ -440,7 +440,7 @@ namespace i2p
|
||||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
|
||||||
eI2NPTunnelBuildReply, buf, len,
|
eI2NPTunnelBuildReply, buf, len,
|
||||||
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
|
@ -592,13 +592,13 @@ namespace i2p
|
||||||
switch (typeID)
|
switch (typeID)
|
||||||
{
|
{
|
||||||
case eI2NPVariableTunnelBuild:
|
case eI2NPVariableTunnelBuild:
|
||||||
HandleVariableTunnelBuildMsg (msgID, buf, size);
|
HandleVariableTunnelBuildMsg (msgID, buf, size);
|
||||||
break;
|
break;
|
||||||
case eI2NPVariableTunnelBuildReply:
|
case eI2NPVariableTunnelBuildReply:
|
||||||
HandleVariableTunnelBuildReplyMsg (msgID, buf, size);
|
HandleVariableTunnelBuildReplyMsg (msgID, buf, size);
|
||||||
break;
|
break;
|
||||||
case eI2NPTunnelBuild:
|
case eI2NPTunnelBuild:
|
||||||
HandleTunnelBuildMsg (buf, size);
|
HandleTunnelBuildMsg (buf, size);
|
||||||
break;
|
break;
|
||||||
case eI2NPTunnelBuildReply:
|
case eI2NPTunnelBuildReply:
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -667,7 +667,7 @@ namespace i2p
|
||||||
Flush ();
|
Flush ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
|
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace i2p
|
||||||
const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4;
|
const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4;
|
||||||
|
|
||||||
// I2NP NTCP2 header
|
// I2NP NTCP2 header
|
||||||
const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4;
|
const size_t I2NP_NTCP2_HEADER_SIZE = I2NP_HEADER_EXPIRATION_OFFSET + 4;
|
||||||
|
|
||||||
// Tunnel Gateway header
|
// Tunnel Gateway header
|
||||||
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
|
const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0;
|
||||||
|
@ -75,7 +75,7 @@ namespace i2p
|
||||||
|
|
||||||
enum I2NPMessageType
|
enum I2NPMessageType
|
||||||
{
|
{
|
||||||
eI2NPDummyMsg = 0,
|
eI2NPDummyMsg = 0,
|
||||||
eI2NPDatabaseStore = 1,
|
eI2NPDatabaseStore = 1,
|
||||||
eI2NPDatabaseLookup = 2,
|
eI2NPDatabaseLookup = 2,
|
||||||
eI2NPDatabaseSearchReply = 3,
|
eI2NPDatabaseSearchReply = 3,
|
||||||
|
@ -209,7 +209,7 @@ namespace tunnel
|
||||||
SetExpiration (bufbe32toh (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET)*1000LL);
|
SetExpiration (bufbe32toh (ntcp2 + I2NP_HEADER_EXPIRATION_OFFSET)*1000LL);
|
||||||
SetSize (len - offset - I2NP_HEADER_SIZE);
|
SetSize (len - offset - I2NP_HEADER_SIZE);
|
||||||
SetChks (0);
|
SetChks (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ToNTCP2 ()
|
void ToNTCP2 ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -356,7 +356,7 @@ namespace data
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityEx::CreateVerifier () const
|
void IdentityEx::CreateVerifier () const
|
||||||
{
|
{
|
||||||
if (m_Verifier) return; // don't create again
|
if (m_Verifier) return; // don't create again
|
||||||
|
@ -369,15 +369,15 @@ namespace data
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// for P521
|
// for P521
|
||||||
uint8_t * signingKey = new uint8_t[keyLen];
|
uint8_t * signingKey = new uint8_t[keyLen];
|
||||||
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
memcpy (signingKey, m_StandardIdentity.signingKey, 128);
|
||||||
size_t excessLen = keyLen - 128;
|
size_t excessLen = keyLen - 128;
|
||||||
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
memcpy (signingKey + 128, m_ExtendedBuffer + 4, excessLen); // right after signing and crypto key types
|
||||||
verifier->SetPublicKey (signingKey);
|
verifier->SetPublicKey (signingKey);
|
||||||
delete[] signingKey;
|
delete[] signingKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UpdateVerifier (verifier);
|
UpdateVerifier (verifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
|
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
|
||||||
|
@ -390,7 +390,7 @@ namespace data
|
||||||
else
|
else
|
||||||
del = true;
|
del = true;
|
||||||
}
|
}
|
||||||
if (del)
|
if (del)
|
||||||
delete verifier;
|
delete verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,7 +426,7 @@ namespace data
|
||||||
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType);
|
LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)keyType);
|
||||||
};
|
};
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (const uint8_t * key) const
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (const uint8_t * key) const
|
||||||
{
|
{
|
||||||
|
@ -460,9 +460,9 @@ namespace data
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PrivateKeys::GetFullLen () const
|
size_t PrivateKeys::GetFullLen () const
|
||||||
{
|
{
|
||||||
size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen ();
|
size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen ();
|
||||||
if (IsOfflineSignature ())
|
if (IsOfflineSignature ())
|
||||||
ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen;
|
ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen;
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -483,7 +483,7 @@ namespace data
|
||||||
// check if signing private key is all zeros
|
// check if signing private key is all zeros
|
||||||
bool allzeros = true;
|
bool allzeros = true;
|
||||||
for (size_t i = 0; i < signingPrivateKeySize; i++)
|
for (size_t i = 0; i < signingPrivateKeySize; i++)
|
||||||
if (m_SigningPrivateKey[i])
|
if (m_SigningPrivateKey[i])
|
||||||
{
|
{
|
||||||
allzeros = false;
|
allzeros = false;
|
||||||
break;
|
break;
|
||||||
|
@ -500,7 +500,7 @@ namespace data
|
||||||
if (keyLen + ret > len) return 0;
|
if (keyLen + ret > len) return 0;
|
||||||
transientVerifier->SetPublicKey (buf + ret); ret += keyLen;
|
transientVerifier->SetPublicKey (buf + ret); ret += keyLen;
|
||||||
if (m_Public->GetSignatureLen () + ret > len) return 0;
|
if (m_Public->GetSignatureLen () + ret > len) return 0;
|
||||||
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
|
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Identity: offline signature verification failed");
|
LogPrint (eLogError, "Identity: offline signature verification failed");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -511,7 +511,7 @@ namespace data
|
||||||
size_t offlineInfoLen = buf + ret - offlineInfo;
|
size_t offlineInfoLen = buf + ret - offlineInfo;
|
||||||
m_OfflineSignature.resize (offlineInfoLen);
|
m_OfflineSignature.resize (offlineInfoLen);
|
||||||
memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen);
|
memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen);
|
||||||
// override signing private key
|
// override signing private key
|
||||||
m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen ();
|
m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen ();
|
||||||
if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0;
|
if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0;
|
||||||
memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen);
|
memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen);
|
||||||
|
@ -586,10 +586,10 @@ namespace data
|
||||||
else
|
else
|
||||||
CreateSigner (m_Public->GetSigningKeyType ());
|
CreateSigner (m_Public->GetSigningKeyType ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrivateKeys::CreateSigner (SigningKeyType keyType) const
|
void PrivateKeys::CreateSigner (SigningKeyType keyType) const
|
||||||
{
|
{
|
||||||
if (m_Signer) return;
|
if (m_Signer) return;
|
||||||
if (keyType == SIGNING_KEY_TYPE_DSA_SHA1)
|
if (keyType == SIGNING_KEY_TYPE_DSA_SHA1)
|
||||||
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey));
|
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey));
|
||||||
else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ())
|
else if (keyType == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519 && !IsOfflineSignature ())
|
||||||
|
@ -599,7 +599,7 @@ namespace data
|
||||||
// public key is not required
|
// public key is not required
|
||||||
auto signer = CreateSigner (keyType, m_SigningPrivateKey);
|
auto signer = CreateSigner (keyType, m_SigningPrivateKey);
|
||||||
if (signer) m_Signer.reset (signer);
|
if (signer) m_Signer.reset (signer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i2p::crypto::Signer * PrivateKeys::CreateSigner (SigningKeyType keyType, const uint8_t * priv)
|
i2p::crypto::Signer * PrivateKeys::CreateSigner (SigningKeyType keyType, const uint8_t * priv)
|
||||||
|
@ -630,8 +630,8 @@ namespace data
|
||||||
return new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, priv);
|
return new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, priv);
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
return new i2p::crypto::RedDSA25519Signer (priv);
|
return new i2p::crypto::RedDSA25519Signer (priv);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
|
LogPrint (eLogError, "Identity: Signing key type ", (int)keyType, " is not supported");
|
||||||
}
|
}
|
||||||
|
@ -719,8 +719,8 @@ namespace data
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
// no break here
|
// no break here
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
||||||
|
@ -733,7 +733,7 @@ namespace data
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub);
|
i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "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");
|
||||||
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
|
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
|
||||||
|
@ -765,7 +765,7 @@ namespace data
|
||||||
PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const
|
PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const
|
||||||
{
|
{
|
||||||
PrivateKeys keys (*this);
|
PrivateKeys keys (*this);
|
||||||
std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type));
|
std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type));
|
||||||
if (verifier)
|
if (verifier)
|
||||||
{
|
{
|
||||||
size_t pubKeyLen = verifier->GetPublicKeyLen ();
|
size_t pubKeyLen = verifier->GetPublicKeyLen ();
|
||||||
|
@ -775,7 +775,7 @@ namespace data
|
||||||
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
||||||
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
|
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
|
||||||
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
|
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
|
||||||
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
|
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
|
||||||
// recreate signer
|
// recreate signer
|
||||||
keys.m_Signer = nullptr;
|
keys.m_Signer = nullptr;
|
||||||
keys.CreateSigner (type);
|
keys.CreateSigner (type);
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace data
|
||||||
|
|
||||||
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
|
const uint16_t CRYPTO_KEY_TYPE_ELGAMAL = 0;
|
||||||
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1;
|
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC = 1;
|
||||||
const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET = 4;
|
const uint16_t CRYPTO_KEY_TYPE_ECIES_X25519_AEAD_RATCHET = 4;
|
||||||
const uint16_t CRYPTO_KEY_TYPE_ECIES_P256_SHA256_AES256CBC_TEST = 65280; // TODO: remove later
|
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 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
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace data
|
||||||
void RecalculateIdentHash(uint8_t * buff=nullptr);
|
void RecalculateIdentHash(uint8_t * buff=nullptr);
|
||||||
|
|
||||||
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
|
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
|
||||||
static std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (CryptoKeyType keyType, const uint8_t * key);
|
static std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> CreateEncryptor (CryptoKeyType keyType, const uint8_t * key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ namespace data
|
||||||
const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
|
const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; };
|
||||||
size_t GetSignatureLen () const; // might not match identity
|
size_t GetSignatureLen () const; // might not match identity
|
||||||
bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; };
|
bool IsOfflineSignature () const { return m_TransientSignatureLen > 0; };
|
||||||
uint8_t * GetPadding();
|
uint8_t * GetPadding();
|
||||||
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
|
void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); }
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
||||||
|
|
||||||
|
@ -163,12 +163,12 @@ namespace data
|
||||||
|
|
||||||
static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
|
static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
|
||||||
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
|
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
|
||||||
static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub);
|
static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub);
|
||||||
static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
|
static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
|
||||||
static i2p::crypto::Signer * CreateSigner (SigningKeyType keyType, const uint8_t * priv);
|
static i2p::crypto::Signer * CreateSigner (SigningKeyType keyType, const uint8_t * priv);
|
||||||
|
|
||||||
// offline keys
|
// offline keys
|
||||||
PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const;
|
PrivateKeys CreateOfflineKeys (SigningKeyType type, uint32_t expires) const;
|
||||||
const std::vector<uint8_t>& GetOfflineSignature () const { return m_OfflineSignature; };
|
const std::vector<uint8_t>& GetOfflineSignature () const { return m_OfflineSignature; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -204,7 +204,7 @@ namespace data
|
||||||
IdentHash CreateRoutingKey (const IdentHash& ident);
|
IdentHash CreateRoutingKey (const IdentHash& ident);
|
||||||
XORMetric operator^(const IdentHash& key1, const IdentHash& key2);
|
XORMetric operator^(const IdentHash& key1, const IdentHash& key2);
|
||||||
|
|
||||||
// destination for delivery instuctions
|
// destination for delivery instructions
|
||||||
class RoutingDestination
|
class RoutingDestination
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -235,5 +235,4 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -12,9 +12,8 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
|
|
||||||
LeaseSet::LeaseSet (bool storeLeases):
|
LeaseSet::LeaseSet (bool storeLeases):
|
||||||
m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr),
|
m_IsValid (false), m_StoreLeases (storeLeases), m_ExpirationTime (0), m_EncryptionKey (nullptr),
|
||||||
m_Buffer (nullptr), m_BufferLen (0)
|
m_Buffer (nullptr), m_BufferLen (0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -62,7 +61,7 @@ namespace data
|
||||||
{
|
{
|
||||||
if (!m_EncryptionKey) m_EncryptionKey = new uint8_t[256];
|
if (!m_EncryptionKey) m_EncryptionKey = new uint8_t[256];
|
||||||
memcpy (m_EncryptionKey, m_Buffer + size, 256);
|
memcpy (m_EncryptionKey, m_Buffer + size, 256);
|
||||||
}
|
}
|
||||||
size += 256; // encryption key
|
size += 256; // encryption key
|
||||||
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
|
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
|
||||||
uint8_t num = m_Buffer[size];
|
uint8_t num = m_Buffer[size];
|
||||||
|
@ -191,10 +190,10 @@ namespace data
|
||||||
return m_ExpirationTime - now <= dlt;
|
return m_ExpirationTime - now <= dlt;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
|
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeases (bool withThreshold) const
|
||||||
{
|
{
|
||||||
return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold);
|
return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const
|
const std::vector<std::shared_ptr<const Lease> > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const
|
||||||
{
|
{
|
||||||
|
@ -249,19 +248,19 @@ namespace data
|
||||||
if (len <= m_BufferLen) m_BufferLen = len;
|
if (len <= m_BufferLen) m_BufferLen = len;
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
|
LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
|
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
|
||||||
LeaseSet (storeLeases), m_StoreType (storeType), m_EncryptionType (preferredCrypto)
|
LeaseSet (storeLeases), m_StoreType (storeType), m_EncryptionType (preferredCrypto)
|
||||||
{
|
{
|
||||||
SetBuffer (buf, len);
|
SetBuffer (buf, len);
|
||||||
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (storeType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
ReadFromBufferEncrypted (buf, len, nullptr, nullptr);
|
ReadFromBufferEncrypted (buf, len, nullptr, nullptr);
|
||||||
else
|
else
|
||||||
ReadFromBuffer (buf, len);
|
ReadFromBuffer (buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key,
|
LeaseSet2::LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key,
|
||||||
const uint8_t * secret, CryptoKeyType preferredCrypto):
|
const uint8_t * secret, CryptoKeyType preferredCrypto):
|
||||||
LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2), m_EncryptionType (preferredCrypto)
|
LeaseSet (true), m_StoreType (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2), m_EncryptionType (preferredCrypto)
|
||||||
{
|
{
|
||||||
|
@ -269,10 +268,10 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
if (GetStoreType () != NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (GetStoreType () != NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
ReadFromBuffer (buf, len, false, verifySignature);
|
ReadFromBuffer (buf, len, false, verifySignature);
|
||||||
// TODO: implement encrypted
|
// TODO: implement encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,13 +280,13 @@ namespace data
|
||||||
uint64_t expiration;
|
uint64_t expiration;
|
||||||
return ExtractPublishedTimestamp (buf, len, expiration) > m_PublishedTimestamp;
|
return ExtractPublishedTimestamp (buf, len, expiration) > m_PublishedTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity, bool verifySignature)
|
void LeaseSet2::ReadFromBuffer (const uint8_t * buf, size_t len, bool readIdentity, bool verifySignature)
|
||||||
{
|
{
|
||||||
// standard LS2 header
|
// standard LS2 header
|
||||||
std::shared_ptr<const IdentityEx> identity;
|
std::shared_ptr<const IdentityEx> identity;
|
||||||
if (readIdentity)
|
if (readIdentity)
|
||||||
{
|
{
|
||||||
identity = std::make_shared<IdentityEx>(buf, len);
|
identity = std::make_shared<IdentityEx>(buf, len);
|
||||||
SetIdentity (identity);
|
SetIdentity (identity);
|
||||||
}
|
}
|
||||||
|
@ -304,7 +303,7 @@ namespace data
|
||||||
// transient key
|
// transient key
|
||||||
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
|
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
|
||||||
if (!m_TransientVerifier)
|
if (!m_TransientVerifier)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -314,7 +313,7 @@ namespace data
|
||||||
{
|
{
|
||||||
m_IsPublishedEncrypted = true;
|
m_IsPublishedEncrypted = true;
|
||||||
m_IsPublic = true;
|
m_IsPublic = true;
|
||||||
}
|
}
|
||||||
// type specific part
|
// type specific part
|
||||||
size_t s = 0;
|
size_t s = 0;
|
||||||
switch (m_StoreType)
|
switch (m_StoreType)
|
||||||
|
@ -331,11 +330,11 @@ namespace data
|
||||||
if (!s) return;
|
if (!s) return;
|
||||||
offset += s;
|
offset += s;
|
||||||
if (verifySignature || m_TransientVerifier)
|
if (verifySignature || m_TransientVerifier)
|
||||||
{
|
{
|
||||||
// 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 (identity, buf, len, offset);
|
VerifySignature (identity, buf, len, offset);
|
||||||
SetIsValid (verified);
|
SetIsValid (verified);
|
||||||
}
|
}
|
||||||
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen ();
|
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen ();
|
||||||
SetBufferLen (offset);
|
SetBufferLen (offset);
|
||||||
|
@ -346,10 +345,10 @@ namespace data
|
||||||
{
|
{
|
||||||
if (signatureOffset + verifier->GetSignatureLen () > len) return false;
|
if (signatureOffset + verifier->GetSignatureLen () > len) return false;
|
||||||
// we assume buf inside DatabaseStore message, so buf[-1] is valid memory
|
// we assume buf inside DatabaseStore message, so buf[-1] is valid memory
|
||||||
// change it for signature verification, and restore back
|
// change it for signature verification, and restore back
|
||||||
uint8_t c = buf[-1];
|
uint8_t c = buf[-1];
|
||||||
const_cast<uint8_t *>(buf)[-1] = m_StoreType;
|
const_cast<uint8_t *>(buf)[-1] = m_StoreType;
|
||||||
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
|
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
|
||||||
const_cast<uint8_t *>(buf)[-1] = c;
|
const_cast<uint8_t *>(buf)[-1] = c;
|
||||||
if (!verified)
|
if (!verified)
|
||||||
LogPrint (eLogWarning, "LeaseSet2: verification failed");
|
LogPrint (eLogWarning, "LeaseSet2: verification failed");
|
||||||
|
@ -360,7 +359,7 @@ namespace data
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// properties
|
// properties
|
||||||
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
||||||
offset += propertiesLen; // skip for now. TODO: implement properties
|
offset += propertiesLen; // skip for now. TODO: implement properties
|
||||||
if (offset + 1 >= len) return 0;
|
if (offset + 1 >= len) return 0;
|
||||||
// key sections
|
// key sections
|
||||||
|
@ -371,7 +370,7 @@ namespace data
|
||||||
{
|
{
|
||||||
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type
|
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type
|
||||||
if (offset + 2 >= len) return 0;
|
if (offset + 2 >= len) return 0;
|
||||||
uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2;
|
uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2;
|
||||||
if (offset + encryptionKeyLen >= len) return 0;
|
if (offset + encryptionKeyLen >= len) return 0;
|
||||||
if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only
|
if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only
|
||||||
{
|
{
|
||||||
|
@ -384,10 +383,10 @@ namespace data
|
||||||
if (keyType == preferredKeyType) preferredKeyFound = true;
|
if (keyType == preferredKeyType) preferredKeyFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
offset += encryptionKeyLen;
|
offset += encryptionKeyLen;
|
||||||
}
|
}
|
||||||
// leases
|
// leases
|
||||||
if (offset + 1 >= len) return 0;
|
if (offset + 1 >= len) return 0;
|
||||||
int numLeases = buf[offset]; offset++;
|
int numLeases = buf[offset]; offset++;
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
if (IsStoreLeases ())
|
if (IsStoreLeases ())
|
||||||
|
@ -413,9 +412,9 @@ namespace data
|
||||||
{
|
{
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
// properties
|
// properties
|
||||||
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
|
||||||
offset += propertiesLen; // skip for now. TODO: implement properties
|
offset += propertiesLen; // skip for now. TODO: implement properties
|
||||||
// entries
|
// entries
|
||||||
if (offset + 1 >= len) return 0;
|
if (offset + 1 >= len) return 0;
|
||||||
int numEntries = buf[offset]; offset++;
|
int numEntries = buf[offset]; offset++;
|
||||||
for (int i = 0; i < numEntries; i++)
|
for (int i = 0; i < numEntries; i++)
|
||||||
|
@ -423,12 +422,12 @@ namespace data
|
||||||
if (offset + 40 >= len) return 0;
|
if (offset + 40 >= len) return 0;
|
||||||
offset += 32; // hash
|
offset += 32; // hash
|
||||||
offset += 3; // flags
|
offset += 3; // flags
|
||||||
offset += 1; // cost
|
offset += 1; // cost
|
||||||
offset += 4; // expires
|
offset += 4; // expires
|
||||||
}
|
}
|
||||||
// revocations
|
// revocations
|
||||||
if (offset + 1 >= len) return 0;
|
if (offset + 1 >= len) return 0;
|
||||||
int numRevocations = buf[offset]; offset++;
|
int numRevocations = buf[offset]; offset++;
|
||||||
for (int i = 0; i < numRevocations; i++)
|
for (int i = 0; i < numRevocations; i++)
|
||||||
{
|
{
|
||||||
if (offset + 32 > len) return 0;
|
if (offset + 32 > len) return 0;
|
||||||
|
@ -446,7 +445,7 @@ namespace data
|
||||||
uint16_t blindedKeyType = bufbe16toh (stA1); offset += 2;
|
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;
|
||||||
const uint8_t * blindedPublicKey = buf + offset;
|
const uint8_t * blindedPublicKey = buf + offset;
|
||||||
blindedVerifier->SetPublicKey (blindedPublicKey); offset += blindedKeyLen;
|
blindedVerifier->SetPublicKey (blindedPublicKey); offset += blindedKeyLen;
|
||||||
|
@ -461,7 +460,7 @@ namespace data
|
||||||
{
|
{
|
||||||
// transient key
|
// transient key
|
||||||
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
|
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
|
||||||
if (!m_TransientVerifier)
|
if (!m_TransientVerifier)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
||||||
return;
|
return;
|
||||||
|
@ -470,16 +469,16 @@ namespace data
|
||||||
// outer ciphertext
|
// outer ciphertext
|
||||||
if (offset + 2 > len) return;
|
if (offset + 2 > len) return;
|
||||||
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2;
|
uint16_t lenOuterCiphertext = bufbe16toh (buf + offset); offset += 2;
|
||||||
const uint8_t * outerCiphertext = buf + offset;
|
const uint8_t * outerCiphertext = buf + offset;
|
||||||
offset += lenOuterCiphertext;
|
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
|
// handle ciphertext
|
||||||
if (verified && key && lenOuterCiphertext >= 32)
|
if (verified && key && lenOuterCiphertext >= 32)
|
||||||
{
|
{
|
||||||
SetIsValid (false); // we must verify it again in Layer 2
|
SetIsValid (false); // we must verify it again in Layer 2
|
||||||
if (blindedKeyType == key->GetBlindedSigType ())
|
if (blindedKeyType == key->GetBlindedSigType ())
|
||||||
{
|
{
|
||||||
// verify blinding
|
// verify blinding
|
||||||
|
@ -491,13 +490,13 @@ namespace data
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match");
|
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: Unexpected blinded key type ", blindedKeyType, " instead ", key->GetBlindedSigType ());
|
LogPrint (eLogError, "LeaseSet2: Unexpected blinded key type ", blindedKeyType, " instead ", key->GetBlindedSigType ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// outer key
|
// outer key
|
||||||
// outerInput = subcredential || publishedTimestamp
|
// outerInput = subcredential || publishedTimestamp
|
||||||
uint8_t subcredential[36];
|
uint8_t subcredential[36];
|
||||||
|
@ -518,10 +517,10 @@ namespace data
|
||||||
// innerSalt = innerCiphertext[0:32]
|
// innerSalt = innerCiphertext[0:32]
|
||||||
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
// keys = HKDF(innerSalt, innerInput, "ELS2_L2K", 44)
|
||||||
uint8_t innerInput[68];
|
uint8_t innerInput[68];
|
||||||
size_t authDataLen = ExtractClientAuthData (outerPlainText.data (), lenOuterPlaintext, secret, subcredential, innerInput);
|
size_t authDataLen = ExtractClientAuthData (outerPlainText.data (), lenOuterPlaintext, secret, subcredential, innerInput);
|
||||||
if (authDataLen > 0)
|
if (authDataLen > 0)
|
||||||
{
|
{
|
||||||
memcpy (innerInput + 32, subcredential, 36);
|
memcpy (innerInput + 32, subcredential, 36);
|
||||||
i2p::crypto::HKDF (outerPlainText.data () + 1 + authDataLen, innerInput, 68, "ELS2_L2K", keys);
|
i2p::crypto::HKDF (outerPlainText.data () + 1 + authDataLen, innerInput, 68, "ELS2_L2K", keys);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -537,20 +536,20 @@ namespace data
|
||||||
if (innerPlainText[0] == NETDB_STORE_TYPE_STANDARD_LEASESET2 || innerPlainText[0] == NETDB_STORE_TYPE_META_LEASESET2)
|
if (innerPlainText[0] == NETDB_STORE_TYPE_STANDARD_LEASESET2 || innerPlainText[0] == NETDB_STORE_TYPE_META_LEASESET2)
|
||||||
{
|
{
|
||||||
// override store type and buffer
|
// override store type and buffer
|
||||||
m_StoreType = innerPlainText[0];
|
m_StoreType = innerPlainText[0];
|
||||||
SetBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
SetBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
||||||
// parse and verify Layer 2
|
// parse and verify Layer 2
|
||||||
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
|
LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// we set actual length of encrypted buffer
|
// we set actual length of encrypted buffer
|
||||||
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : blindedVerifier->GetSignatureLen ();
|
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : blindedVerifier->GetSignatureLen ();
|
||||||
SetBufferLen (offset);
|
SetBufferLen (offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper for ExtractClientAuthData
|
// helper for ExtractClientAuthData
|
||||||
|
@ -563,12 +562,12 @@ namespace data
|
||||||
{
|
{
|
||||||
// clientKey_i = okm[0:31]
|
// clientKey_i = okm[0:31]
|
||||||
// clientIV_i = okm[32:43]
|
// clientIV_i = okm[32:43]
|
||||||
i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i
|
i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const
|
size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const
|
||||||
{
|
{
|
||||||
|
@ -581,7 +580,7 @@ namespace data
|
||||||
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
|
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
|
||||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
||||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||||
if (offset > len)
|
if (offset > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
|
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -595,19 +594,19 @@ namespace data
|
||||||
memcpy (authInput + 32, ck.GetPublicKey (), 32); // cpk_i
|
memcpy (authInput + 32, ck.GetPublicKey (), 32); // cpk_i
|
||||||
memcpy (authInput + 64, subcredential, 36);
|
memcpy (authInput + 64, subcredential, 36);
|
||||||
uint8_t okm[64]; // 52 actual data
|
uint8_t okm[64]; // 52 actual data
|
||||||
i2p::crypto::HKDF (ephemeralPublicKey, authInput, 100, "ELS2_XCA", okm);
|
i2p::crypto::HKDF (ephemeralPublicKey, authInput, 100, "ELS2_XCA", okm);
|
||||||
if (!GetAuthCookie (authClients, numClients, okm, authCookie))
|
if (!GetAuthCookie (authClients, numClients, okm, authCookie))
|
||||||
LogPrint (eLogError, "LeaseSet2: Client cookie DH not found");
|
LogPrint (eLogError, "LeaseSet2: Client cookie DH not found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: csk_i is not provided");
|
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: csk_i is not provided");
|
||||||
}
|
}
|
||||||
else if (flag & 0x02) // PSK, bit 1 is set to 1
|
else if (flag & 0x02) // PSK, bit 1 is set to 1
|
||||||
{
|
{
|
||||||
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
|
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
|
||||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
||||||
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
|
||||||
if (offset > len)
|
if (offset > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
|
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -619,7 +618,7 @@ namespace data
|
||||||
memcpy (authInput, secret, 32);
|
memcpy (authInput, secret, 32);
|
||||||
memcpy (authInput + 32, subcredential, 36);
|
memcpy (authInput + 32, subcredential, 36);
|
||||||
uint8_t okm[64]; // 52 actual data
|
uint8_t okm[64]; // 52 actual data
|
||||||
i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm);
|
i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm);
|
||||||
if (!GetAuthCookie (authClients, numClients, okm, authCookie))
|
if (!GetAuthCookie (authClients, numClients, okm, authCookie))
|
||||||
LogPrint (eLogError, "LeaseSet2: Client cookie PSK not found");
|
LogPrint (eLogError, "LeaseSet2: Client cookie PSK not found");
|
||||||
}
|
}
|
||||||
|
@ -627,7 +626,7 @@ namespace data
|
||||||
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
|
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag);
|
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag);
|
||||||
}
|
}
|
||||||
return offset - 1;
|
return offset - 1;
|
||||||
}
|
}
|
||||||
|
@ -636,7 +635,7 @@ namespace data
|
||||||
{
|
{
|
||||||
auto encryptor = m_Encryptor; // TODO: atomic
|
auto encryptor = m_Encryptor; // TODO: atomic
|
||||||
if (encryptor)
|
if (encryptor)
|
||||||
encryptor->Encrypt (data, encrypted, ctx, true);
|
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t LeaseSet2::ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const
|
uint64_t LeaseSet2::ExtractExpirationTimestamp (const uint8_t * buf, size_t len) const
|
||||||
|
@ -648,7 +647,7 @@ namespace data
|
||||||
|
|
||||||
uint64_t LeaseSet2::ExtractPublishedTimestamp (const uint8_t * buf, size_t len, uint64_t& expiration) const
|
uint64_t LeaseSet2::ExtractPublishedTimestamp (const uint8_t * buf, size_t len, uint64_t& expiration) const
|
||||||
{
|
{
|
||||||
if (len < 8) return 0;
|
if (len < 8) return 0;
|
||||||
if (m_StoreType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (m_StoreType == NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
{
|
{
|
||||||
// encrypted LS2
|
// encrypted LS2
|
||||||
|
@ -656,11 +655,11 @@ namespace data
|
||||||
uint16_t blindedKeyType = bufbe16toh (buf + offset); offset += 2;
|
uint16_t blindedKeyType = bufbe16toh (buf + offset); 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 0 ;
|
if (!blindedVerifier) return 0 ;
|
||||||
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
auto blindedKeyLen = blindedVerifier->GetPublicKeyLen ();
|
||||||
if (offset + blindedKeyLen + 6 >= len) return 0;
|
if (offset + blindedKeyLen + 6 >= len) return 0;
|
||||||
offset += blindedKeyLen;
|
offset += blindedKeyLen;
|
||||||
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4;
|
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4;
|
||||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2;
|
uint16_t expires = bufbe16toh (buf + offset); offset += 2;
|
||||||
expiration = (timestamp + expires)* 1000LL;
|
expiration = (timestamp + expires)* 1000LL;
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
@ -670,13 +669,13 @@ namespace data
|
||||||
if (!identity) return 0;
|
if (!identity) return 0;
|
||||||
size_t offset = identity->GetFullLen ();
|
size_t offset = identity->GetFullLen ();
|
||||||
if (offset + 6 >= len) return 0;
|
if (offset + 6 >= len) return 0;
|
||||||
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4;
|
uint32_t timestamp = bufbe32toh (buf + offset); offset += 4;
|
||||||
uint16_t expires = bufbe16toh (buf + offset); offset += 2;
|
uint16_t expires = bufbe16toh (buf + offset); offset += 2;
|
||||||
expiration = (timestamp + expires)* 1000LL;
|
expiration = (timestamp + expires)* 1000LL;
|
||||||
return timestamp;
|
return timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
||||||
m_ExpirationTime (0), m_Identity (identity)
|
m_ExpirationTime (0), m_Identity (identity)
|
||||||
{
|
{
|
||||||
|
@ -770,36 +769,35 @@ namespace data
|
||||||
return ident.Verify(ptr, leases - ptr, leases);
|
return ident.Verify(ptr, leases - ptr, leases);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
|
LocalLeaseSet2::LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
|
||||||
const KeySections& encryptionKeys,
|
const KeySections& encryptionKeys, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
|
||||||
std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
|
|
||||||
bool isPublic, bool isPublishedEncrypted):
|
bool isPublic, bool isPublishedEncrypted):
|
||||||
LocalLeaseSet (keys.GetPublic (), nullptr, 0)
|
LocalLeaseSet (keys.GetPublic (), nullptr, 0)
|
||||||
{
|
{
|
||||||
auto identity = keys.GetPublic ();
|
auto identity = keys.GetPublic ();
|
||||||
// assume standard LS2
|
// assume standard LS2
|
||||||
int num = tunnels.size ();
|
int num = tunnels.size ();
|
||||||
if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES;
|
if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES;
|
||||||
size_t keySectionsLen = 0;
|
size_t keySectionsLen = 0;
|
||||||
for (const auto& it: encryptionKeys)
|
for (const auto& it: encryptionKeys)
|
||||||
keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/;
|
keySectionsLen += 2/*key type*/ + 2/*key len*/ + it.keyLen/*key*/;
|
||||||
m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ +
|
m_BufferLen = identity->GetFullLen () + 4/*published*/ + 2/*expires*/ + 2/*flag*/ + 2/*properties len*/ +
|
||||||
1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen ();
|
1/*num keys*/ + keySectionsLen + 1/*num leases*/ + num*LEASE2_SIZE + keys.GetSignatureLen ();
|
||||||
uint16_t flags = 0;
|
uint16_t flags = 0;
|
||||||
if (keys.IsOfflineSignature ())
|
if (keys.IsOfflineSignature ())
|
||||||
{
|
{
|
||||||
flags |= LEASESET2_FLAG_OFFLINE_KEYS;
|
flags |= LEASESET2_FLAG_OFFLINE_KEYS;
|
||||||
m_BufferLen += keys.GetOfflineSignature ().size ();
|
m_BufferLen += keys.GetOfflineSignature ().size ();
|
||||||
}
|
}
|
||||||
if (isPublishedEncrypted)
|
if (isPublishedEncrypted)
|
||||||
{
|
{
|
||||||
flags |= LEASESET2_FLAG_PUBLISHED_ENCRYPTED;
|
flags |= LEASESET2_FLAG_PUBLISHED_ENCRYPTED;
|
||||||
isPublic = true;
|
isPublic = true;
|
||||||
}
|
}
|
||||||
if (!isPublic) flags |= LEASESET2_FLAG_UNPUBLISHED_LEASESET;
|
if (!isPublic) flags |= LEASESET2_FLAG_UNPUBLISHED_LEASESET;
|
||||||
|
|
||||||
m_Buffer = new uint8_t[m_BufferLen + 1];
|
m_Buffer = new uint8_t[m_BufferLen + 1];
|
||||||
m_Buffer[0] = storeType;
|
m_Buffer[0] = storeType;
|
||||||
// LS2 header
|
// LS2 header
|
||||||
auto offset = identity->ToBuffer (m_Buffer + 1, m_BufferLen) + 1;
|
auto offset = identity->ToBuffer (m_Buffer + 1, m_BufferLen) + 1;
|
||||||
auto timestamp = i2p::util::GetSecondsSinceEpoch ();
|
auto timestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
@ -814,14 +812,14 @@ namespace data
|
||||||
offset += offlineSignature.size ();
|
offset += offlineSignature.size ();
|
||||||
}
|
}
|
||||||
htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len
|
htobe16buf (m_Buffer + offset, 0); offset += 2; // properties len
|
||||||
// keys
|
// keys
|
||||||
m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key
|
m_Buffer[offset] = encryptionKeys.size (); offset++; // 1 key
|
||||||
for (const auto& it: encryptionKeys)
|
for (const auto& it: encryptionKeys)
|
||||||
{
|
{
|
||||||
htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type
|
htobe16buf (m_Buffer + offset, it.keyType); offset += 2; // key type
|
||||||
htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len
|
htobe16buf (m_Buffer + offset, it.keyLen); offset += 2; // key len
|
||||||
memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key
|
memcpy (m_Buffer + offset, it.encryptionPublicKey, it.keyLen); offset += it.keyLen; // key
|
||||||
}
|
}
|
||||||
// leases
|
// leases
|
||||||
uint32_t expirationTime = 0; // in seconds
|
uint32_t expirationTime = 0; // in seconds
|
||||||
m_Buffer[offset] = num; offset++; // num leases
|
m_Buffer[offset] = num; offset++; // num leases
|
||||||
|
@ -835,11 +833,11 @@ namespace data
|
||||||
if (ts > expirationTime) expirationTime = ts;
|
if (ts > expirationTime) expirationTime = ts;
|
||||||
htobe32buf (m_Buffer + offset, ts);
|
htobe32buf (m_Buffer + offset, ts);
|
||||||
offset += 4; // end date
|
offset += 4; // end date
|
||||||
}
|
}
|
||||||
// update expiration
|
// update expiration
|
||||||
SetExpirationTime (expirationTime*1000LL);
|
SetExpirationTime (expirationTime*1000LL);
|
||||||
auto expires = expirationTime - timestamp;
|
auto expires = expirationTime - timestamp;
|
||||||
htobe16buf (expiresBuf, expires > 0 ? expires : 0);
|
htobe16buf (expiresBuf, expires > 0 ? expires : 0);
|
||||||
// sign
|
// sign
|
||||||
keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type
|
keys.Sign (m_Buffer, offset, m_Buffer + offset); // LS + leading store type
|
||||||
}
|
}
|
||||||
|
@ -853,7 +851,7 @@ namespace data
|
||||||
m_Buffer[0] = storeType;
|
m_Buffer[0] = storeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr<const LocalLeaseSet2> ls, const i2p::data::PrivateKeys& keys,
|
LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr<const LocalLeaseSet2> ls, const i2p::data::PrivateKeys& keys,
|
||||||
int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys):
|
int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys):
|
||||||
LocalLeaseSet2 (ls->GetIdentity ()), m_InnerLeaseSet (ls)
|
LocalLeaseSet2 (ls->GetIdentity ()), m_InnerLeaseSet (ls)
|
||||||
{
|
{
|
||||||
|
@ -863,16 +861,16 @@ namespace data
|
||||||
{
|
{
|
||||||
if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH) layer1Flags |= 0x01; // DH, authentication scheme 0, auth bit 1
|
if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH) layer1Flags |= 0x01; // DH, authentication scheme 0, auth bit 1
|
||||||
else if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_PSK) layer1Flags |= 0x03; // PSK, authentication scheme 1, auth bit 1
|
else if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_PSK) layer1Flags |= 0x03; // PSK, authentication scheme 1, auth bit 1
|
||||||
if (layer1Flags)
|
if (layer1Flags)
|
||||||
lenOuterPlaintext += 32 + 2 + authKeys->size ()*40; // auth data len
|
lenOuterPlaintext += 32 + 2 + authKeys->size ()*40; // auth data len
|
||||||
}
|
}
|
||||||
size_t lenOuterCiphertext = lenOuterPlaintext + 32;
|
size_t lenOuterCiphertext = lenOuterPlaintext + 32;
|
||||||
|
|
||||||
m_BufferLen = 2/*blinded sig type*/ + 32/*blinded pub key*/ + 4/*published*/ + 2/*expires*/ + 2/*flags*/ + 2/*lenOuterCiphertext*/ + lenOuterCiphertext + 64/*signature*/;
|
m_BufferLen = 2/*blinded sig type*/ + 32/*blinded pub key*/ + 4/*published*/ + 2/*expires*/ + 2/*flags*/ + 2/*lenOuterCiphertext*/ + lenOuterCiphertext + 64/*signature*/;
|
||||||
m_Buffer = new uint8_t[m_BufferLen + 1];
|
m_Buffer = new uint8_t[m_BufferLen + 1];
|
||||||
m_Buffer[0] = NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
m_Buffer[0] = NETDB_STORE_TYPE_ENCRYPTED_LEASESET2;
|
||||||
BlindedPublicKey blindedKey (ls->GetIdentity ());
|
BlindedPublicKey blindedKey (ls->GetIdentity ());
|
||||||
auto timestamp = i2p::util::GetSecondsSinceEpoch ();
|
auto timestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
char date[9];
|
char date[9];
|
||||||
i2p::util::GetDateString (timestamp, date);
|
i2p::util::GetDateString (timestamp, date);
|
||||||
uint8_t blindedPriv[64], blindedPub[128]; // 64 and 128 max
|
uint8_t blindedPriv[64], blindedPub[128]; // 64 and 128 max
|
||||||
|
@ -883,25 +881,25 @@ namespace data
|
||||||
memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key
|
memcpy (m_Buffer + offset, blindedPub, publicKeyLen); offset += publicKeyLen; // Blinded Public Key
|
||||||
htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds)
|
htobe32buf (m_Buffer + offset, timestamp); offset += 4; // published timestamp (seconds)
|
||||||
auto nextMidnight = (timestamp/86400LL + 1)*86400LL; // 86400 = 24*3600 seconds
|
auto nextMidnight = (timestamp/86400LL + 1)*86400LL; // 86400 = 24*3600 seconds
|
||||||
auto expirationTime = ls->GetExpirationTime ()/1000LL;
|
auto expirationTime = ls->GetExpirationTime ()/1000LL;
|
||||||
if (expirationTime > nextMidnight) expirationTime = nextMidnight;
|
if (expirationTime > nextMidnight) expirationTime = nextMidnight;
|
||||||
SetExpirationTime (expirationTime*1000LL);
|
SetExpirationTime (expirationTime*1000LL);
|
||||||
htobe16buf (m_Buffer + offset, expirationTime > timestamp ? expirationTime - timestamp : 0); offset += 2; // expires
|
htobe16buf (m_Buffer + offset, expirationTime > timestamp ? expirationTime - timestamp : 0); offset += 2; // expires
|
||||||
uint16_t flags = 0;
|
uint16_t flags = 0;
|
||||||
htobe16buf (m_Buffer + offset, flags); offset += 2; // flags
|
htobe16buf (m_Buffer + offset, flags); offset += 2; // flags
|
||||||
htobe16buf (m_Buffer + offset, lenOuterCiphertext); offset += 2; // lenOuterCiphertext
|
htobe16buf (m_Buffer + offset, lenOuterCiphertext); offset += 2; // lenOuterCiphertext
|
||||||
// outerChipherText
|
// outerChipherText
|
||||||
// Layer 1
|
// Layer 1
|
||||||
uint8_t subcredential[36];
|
uint8_t subcredential[36];
|
||||||
blindedKey.GetSubcredential (blindedPub, 32, subcredential);
|
blindedKey.GetSubcredential (blindedPub, 32, subcredential);
|
||||||
htobe32buf (subcredential + 32, timestamp); // outerInput = subcredential || publishedTimestamp
|
htobe32buf (subcredential + 32, timestamp); // outerInput = subcredential || publishedTimestamp
|
||||||
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
// keys = HKDF(outerSalt, outerInput, "ELS2_L1K", 44)
|
||||||
uint8_t keys1[64]; // 44 bytes actual data
|
uint8_t keys1[64]; // 44 bytes actual data
|
||||||
RAND_bytes (m_Buffer + offset, 32); // outerSalt = CSRNG(32)
|
RAND_bytes (m_Buffer + offset, 32); // outerSalt = CSRNG(32)
|
||||||
i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L1K", keys1);
|
i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L1K", keys1);
|
||||||
offset += 32; // outerSalt
|
offset += 32; // outerSalt
|
||||||
uint8_t * outerPlainText = m_Buffer + offset;
|
uint8_t * outerPlainText = m_Buffer + offset;
|
||||||
m_Buffer[offset] = layer1Flags; offset++; // layer 1 flags
|
m_Buffer[offset] = layer1Flags; offset++; // layer 1 flags
|
||||||
// auth data
|
// auth data
|
||||||
uint8_t innerInput[68]; // authCookie || subcredential || publishedTimestamp
|
uint8_t innerInput[68]; // authCookie || subcredential || publishedTimestamp
|
||||||
if (layer1Flags)
|
if (layer1Flags)
|
||||||
|
@ -909,20 +907,20 @@ namespace data
|
||||||
RAND_bytes (innerInput, 32); // authCookie
|
RAND_bytes (innerInput, 32); // authCookie
|
||||||
CreateClientAuthData (subcredential, authType, authKeys, innerInput, m_Buffer + offset);
|
CreateClientAuthData (subcredential, authType, authKeys, innerInput, m_Buffer + offset);
|
||||||
offset += 32 + 2 + authKeys->size ()*40; // auth clients
|
offset += 32 + 2 + authKeys->size ()*40; // auth clients
|
||||||
}
|
}
|
||||||
// Layer 2
|
// Layer 2
|
||||||
// keys = HKDF(outerSalt, outerInput, "ELS2_L2K", 44)
|
// keys = HKDF(outerSalt, outerInput, "ELS2_L2K", 44)
|
||||||
uint8_t keys2[64]; // 44 bytes actual data
|
uint8_t keys2[64]; // 44 bytes actual data
|
||||||
RAND_bytes (m_Buffer + offset, 32); // innerSalt = CSRNG(32)
|
RAND_bytes (m_Buffer + offset, 32); // innerSalt = CSRNG(32)
|
||||||
if (layer1Flags)
|
if (layer1Flags)
|
||||||
{
|
{
|
||||||
memcpy (innerInput + 32, subcredential, 36); // + subcredential || publishedTimestamp
|
memcpy (innerInput + 32, subcredential, 36); // + subcredential || publishedTimestamp
|
||||||
i2p::crypto::HKDF (m_Buffer + offset, innerInput, 68, "ELS2_L2K", keys2);
|
i2p::crypto::HKDF (m_Buffer + offset, innerInput, 68, "ELS2_L2K", keys2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L2K", keys2); // no authCookie
|
i2p::crypto::HKDF (m_Buffer + offset, subcredential, 36, "ELS2_L2K", keys2); // no authCookie
|
||||||
offset += 32; // innerSalt
|
offset += 32; // innerSalt
|
||||||
m_Buffer[offset] = ls->GetStoreType ();
|
m_Buffer[offset] = ls->GetStoreType ();
|
||||||
memcpy (m_Buffer + offset + 1, ls->GetBuffer (), ls->GetBufferLen ());
|
memcpy (m_Buffer + offset + 1, ls->GetBuffer (), ls->GetBufferLen ());
|
||||||
i2p::crypto::ChaCha20 (m_Buffer + offset, lenInnerPlaintext, keys2, keys2 + 32, m_Buffer + offset); // encrypt Layer 2
|
i2p::crypto::ChaCha20 (m_Buffer + offset, lenInnerPlaintext, keys2, keys2 + 32, m_Buffer + offset); // encrypt Layer 2
|
||||||
offset += lenInnerPlaintext;
|
offset += lenInnerPlaintext;
|
||||||
|
@ -930,14 +928,14 @@ namespace data
|
||||||
// signature
|
// signature
|
||||||
blindedSigner->Sign (m_Buffer, offset, m_Buffer + offset);
|
blindedSigner->Sign (m_Buffer, offset, m_Buffer + offset);
|
||||||
// store hash
|
// store hash
|
||||||
m_StoreHash = blindedKey.GetStoreHash (date);
|
m_StoreHash = blindedKey.GetStoreHash (date);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
|
LocalEncryptedLeaseSet2::LocalEncryptedLeaseSet2 (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
|
||||||
LocalLeaseSet2 (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2, identity, buf, len)
|
LocalLeaseSet2 (NETDB_STORE_TYPE_ENCRYPTED_LEASESET2, identity, buf, len)
|
||||||
{
|
{
|
||||||
// fill inner LeaseSet2
|
// fill inner LeaseSet2
|
||||||
auto blindedKey = std::make_shared<BlindedPublicKey>(identity);
|
auto blindedKey = std::make_shared<BlindedPublicKey>(identity);
|
||||||
i2p::data::LeaseSet2 ls (buf, len, blindedKey); // inner layer
|
i2p::data::LeaseSet2 ls (buf, len, blindedKey); // inner layer
|
||||||
if (ls.IsValid ())
|
if (ls.IsValid ())
|
||||||
{
|
{
|
||||||
|
@ -945,10 +943,10 @@ namespace data
|
||||||
m_StoreHash = blindedKey->GetStoreHash ();
|
m_StoreHash = blindedKey->GetStoreHash ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer");
|
LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const
|
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const
|
||||||
{
|
{
|
||||||
if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH)
|
if (authType == ENCRYPTED_LEASESET_AUTH_TYPE_DH)
|
||||||
{
|
{
|
||||||
|
@ -963,9 +961,9 @@ namespace data
|
||||||
ek.Agree (it, authInput); // sharedSecret = DH(esk, cpk_i)
|
ek.Agree (it, authInput); // sharedSecret = DH(esk, cpk_i)
|
||||||
memcpy (authInput + 32, it, 32);
|
memcpy (authInput + 32, it, 32);
|
||||||
uint8_t okm[64]; // 52 actual data
|
uint8_t okm[64]; // 52 actual data
|
||||||
i2p::crypto::HKDF (ek.GetPublicKey (), authInput, 100, "ELS2_XCA", okm);
|
i2p::crypto::HKDF (ek.GetPublicKey (), authInput, 100, "ELS2_XCA", okm);
|
||||||
memcpy (authData, okm + 44, 8); authData += 8; // clientID_i
|
memcpy (authData, okm + 44, 8); authData += 8; // clientID_i
|
||||||
i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i
|
i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // assume PSK
|
else // assume PSK
|
||||||
|
@ -980,10 +978,10 @@ namespace data
|
||||||
{
|
{
|
||||||
memcpy (authInput, it, 32);
|
memcpy (authInput, it, 32);
|
||||||
uint8_t okm[64]; // 52 actual data
|
uint8_t okm[64]; // 52 actual data
|
||||||
i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm);
|
i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm);
|
||||||
memcpy (authData, okm + 44, 8); authData += 8; // clientID_i
|
memcpy (authData, okm + 44, 8); authData += 8; // clientID_i
|
||||||
i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i
|
i2p::crypto::ChaCha20 (authCookie, 32, okm, okm + 32, authData); authData += 32; // clientCookie_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,11 +48,11 @@ namespace data
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<bool(const Lease & l)> LeaseInspectFunc;
|
typedef std::function<bool(const Lease & l)> LeaseInspectFunc;
|
||||||
|
|
||||||
const size_t MAX_LS_BUFFER_SIZE = 3072;
|
const size_t MAX_LS_BUFFER_SIZE = 3072;
|
||||||
const size_t LEASE_SIZE = 44; // 32 + 4 + 8
|
const size_t LEASE_SIZE = 44; // 32 + 4 + 8
|
||||||
const size_t LEASE2_SIZE = 40; // 32 + 4 + 4
|
const size_t LEASE2_SIZE = 40; // 32 + 4 + 4
|
||||||
const uint8_t MAX_NUM_LEASES = 16;
|
const uint8_t MAX_NUM_LEASES = 16;
|
||||||
|
|
||||||
const uint8_t NETDB_STORE_TYPE_LEASESET = 1;
|
const uint8_t NETDB_STORE_TYPE_LEASESET = 1;
|
||||||
|
@ -70,7 +70,7 @@ namespace data
|
||||||
size_t GetBufferLen () const { return m_BufferLen; };
|
size_t GetBufferLen () const { return m_BufferLen; };
|
||||||
bool IsValid () const { return m_IsValid; };
|
bool IsValid () const { return m_IsValid; };
|
||||||
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
|
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeases (bool withThreshold = true) const;
|
||||||
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const;
|
const std::vector<std::shared_ptr<const Lease> > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const;
|
||||||
bool HasExpiredLeases () const;
|
bool HasExpiredLeases () const;
|
||||||
bool IsExpired () const;
|
bool IsExpired () const;
|
||||||
bool IsEmpty () const { return m_Leases.empty (); };
|
bool IsEmpty () const { return m_Leases.empty (); };
|
||||||
|
@ -80,7 +80,7 @@ namespace data
|
||||||
{ 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 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; };
|
||||||
virtual bool IsPublishedEncrypted () const { return false; };
|
virtual bool IsPublishedEncrypted () const { return false; };
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
|
@ -97,7 +97,7 @@ namespace data
|
||||||
// called from LeaseSet2
|
// called from LeaseSet2
|
||||||
LeaseSet (bool storeLeases);
|
LeaseSet (bool storeLeases);
|
||||||
void SetBuffer (const uint8_t * buf, size_t len);
|
void SetBuffer (const uint8_t * buf, size_t len);
|
||||||
void SetBufferLen (size_t len);
|
void SetBufferLen (size_t len);
|
||||||
void SetIdentity (std::shared_ptr<const IdentityEx> identity) { m_Identity = identity; };
|
void SetIdentity (std::shared_ptr<const IdentityEx> identity) { m_Identity = identity; };
|
||||||
void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; };
|
void SetExpirationTime (uint64_t t) { m_ExpirationTime = t; };
|
||||||
void SetIsValid (bool isValid) { m_IsValid = isValid; };
|
void SetIsValid (bool isValid) { m_IsValid = isValid; };
|
||||||
|
@ -130,7 +130,7 @@ namespace data
|
||||||
const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7;
|
const uint8_t NETDB_STORE_TYPE_META_LEASESET2 = 7;
|
||||||
|
|
||||||
const uint16_t LEASESET2_FLAG_OFFLINE_KEYS = 0x0001;
|
const uint16_t LEASESET2_FLAG_OFFLINE_KEYS = 0x0001;
|
||||||
const uint16_t LEASESET2_FLAG_UNPUBLISHED_LEASESET = 0x0002;
|
const uint16_t LEASESET2_FLAG_UNPUBLISHED_LEASESET = 0x0002;
|
||||||
const uint16_t LEASESET2_FLAG_PUBLISHED_ENCRYPTED = 0x0004;
|
const uint16_t LEASESET2_FLAG_PUBLISHED_ENCRYPTED = 0x0004;
|
||||||
|
|
||||||
class LeaseSet2: public LeaseSet
|
class LeaseSet2: public LeaseSet
|
||||||
|
@ -167,7 +167,7 @@ namespace data
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_StoreType;
|
uint8_t m_StoreType;
|
||||||
uint32_t m_PublishedTimestamp = 0;
|
uint32_t m_PublishedTimestamp = 0;
|
||||||
bool m_IsPublic = true, m_IsPublishedEncrypted = false;
|
bool m_IsPublic = true, m_IsPublishedEncrypted = false;
|
||||||
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
std::shared_ptr<i2p::crypto::Verifier> m_TransientVerifier;
|
||||||
|
@ -175,7 +175,7 @@ namespace data
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> m_Encryptor; // for standardLS2
|
||||||
};
|
};
|
||||||
|
|
||||||
// also called from Streaming.cpp
|
// also called from Streaming.cpp
|
||||||
template<typename Verifier>
|
template<typename Verifier>
|
||||||
std::shared_ptr<i2p::crypto::Verifier> ProcessOfflineSignature (const Verifier& verifier, const uint8_t * buf, size_t len, size_t& offset)
|
std::shared_ptr<i2p::crypto::Verifier> ProcessOfflineSignature (const Verifier& verifier, const uint8_t * buf, size_t len, size_t& offset)
|
||||||
{
|
{
|
||||||
|
@ -191,7 +191,7 @@ namespace data
|
||||||
transientVerifier->SetPublicKey (buf + offset); offset += keyLen;
|
transientVerifier->SetPublicKey (buf + offset); offset += keyLen;
|
||||||
if (offset + verifier->GetSignatureLen () >= len) return nullptr;
|
if (offset + verifier->GetSignatureLen () >= len) return nullptr;
|
||||||
if (!verifier->Verify (signedData, keyLen + 6, buf + offset)) return nullptr;
|
if (!verifier->Verify (signedData, keyLen + 6, buf + offset)) return nullptr;
|
||||||
offset += verifier->GetSignatureLen ();
|
offset += verifier->GetSignatureLen ();
|
||||||
return transientVerifier;
|
return transientVerifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,17 +238,18 @@ namespace data
|
||||||
{
|
{
|
||||||
uint16_t keyType, keyLen;
|
uint16_t keyType, keyLen;
|
||||||
const uint8_t * encryptionPublicKey;
|
const uint8_t * encryptionPublicKey;
|
||||||
};
|
};
|
||||||
typedef std::vector<KeySection> KeySections;
|
typedef std::vector<KeySection> KeySections;
|
||||||
|
|
||||||
LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
|
LocalLeaseSet2 (uint8_t storeType, const i2p::data::PrivateKeys& keys,
|
||||||
const KeySections& encryptionKeys,
|
const KeySections& encryptionKeys,
|
||||||
std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
|
std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels,
|
||||||
bool isPublic, bool isPublishedEncrypted = false);
|
bool isPublic, bool isPublishedEncrypted = false);
|
||||||
LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
|
|
||||||
|
LocalLeaseSet2 (uint8_t storeType, std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
|
||||||
|
|
||||||
virtual ~LocalLeaseSet2 () { delete[] m_Buffer; };
|
virtual ~LocalLeaseSet2 () { delete[] m_Buffer; };
|
||||||
|
|
||||||
uint8_t * GetBuffer () const { return m_Buffer + 1; };
|
uint8_t * GetBuffer () const { return m_Buffer + 1; };
|
||||||
size_t GetBufferLen () const { return m_BufferLen; };
|
size_t GetBufferLen () const { return m_BufferLen; };
|
||||||
|
|
||||||
|
@ -269,13 +270,13 @@ namespace data
|
||||||
const int ENCRYPTED_LEASESET_AUTH_TYPE_DH = 1;
|
const int ENCRYPTED_LEASESET_AUTH_TYPE_DH = 1;
|
||||||
const int ENCRYPTED_LEASESET_AUTH_TYPE_PSK = 2;
|
const int ENCRYPTED_LEASESET_AUTH_TYPE_PSK = 2;
|
||||||
|
|
||||||
typedef i2p::data::Tag<32> AuthPublicKey;
|
typedef i2p::data::Tag<32> AuthPublicKey;
|
||||||
|
|
||||||
class LocalEncryptedLeaseSet2: public LocalLeaseSet2
|
class LocalEncryptedLeaseSet2: public LocalLeaseSet2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
LocalEncryptedLeaseSet2 (std::shared_ptr<const LocalLeaseSet2> ls, const i2p::data::PrivateKeys& keys, int authType = ENCRYPTED_LEASESET_AUTH_TYPE_NONE, std::shared_ptr<std::vector<AuthPublicKey> > authKeys = nullptr);
|
LocalEncryptedLeaseSet2 (std::shared_ptr<const LocalLeaseSet2> ls, const i2p::data::PrivateKeys& keys, int authType = ENCRYPTED_LEASESET_AUTH_TYPE_NONE, std::shared_ptr<std::vector<AuthPublicKey> > authKeys = nullptr);
|
||||||
|
|
||||||
LocalEncryptedLeaseSet2 (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
|
LocalEncryptedLeaseSet2 (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len); // from I2CP
|
||||||
|
|
||||||
|
|
|
@ -29,35 +29,35 @@ struct BigEndian;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct LittleEndian
|
struct LittleEndian
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
unsigned char bytes[sizeof(T)];
|
unsigned char bytes[sizeof(T)];
|
||||||
T raw_value;
|
T raw_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
LittleEndian(T t = T())
|
LittleEndian(T t = T())
|
||||||
{
|
{
|
||||||
operator =(t);
|
operator =(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian(const LittleEndian<T> & t)
|
LittleEndian(const LittleEndian<T> & t)
|
||||||
{
|
{
|
||||||
raw_value = t.raw_value;
|
raw_value = t.raw_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian(const BigEndian<T> & t)
|
LittleEndian(const BigEndian<T> & t)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
bytes[i] = t.bytes[sizeof(T)-1-i];
|
bytes[i] = t.bytes[sizeof(T)-1-i];
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const T() const
|
operator const T() const
|
||||||
{
|
{
|
||||||
T t = T();
|
T t = T();
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
t |= T(bytes[i]) << (i << 3);
|
t |= T(bytes[i]) << (i << 3);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator = (const T t)
|
const T operator = (const T t)
|
||||||
{
|
{
|
||||||
|
@ -66,68 +66,68 @@ struct LittleEndian
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// operators
|
// operators
|
||||||
|
|
||||||
const T operator += (const T t)
|
const T operator += (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this + t);
|
return (*this = *this + t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator -= (const T t)
|
const T operator -= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this - t);
|
return (*this = *this - t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator *= (const T t)
|
const T operator *= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this * t);
|
return (*this = *this * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator /= (const T t)
|
const T operator /= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this / t);
|
return (*this = *this / t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator %= (const T t)
|
const T operator %= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this % t);
|
return (*this = *this % t);
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian<T> operator ++ (int)
|
LittleEndian<T> operator ++ (int)
|
||||||
{
|
{
|
||||||
LittleEndian<T> tmp(*this);
|
LittleEndian<T> tmp(*this);
|
||||||
operator ++ ();
|
operator ++ ();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian<T> & operator ++ ()
|
LittleEndian<T> & operator ++ ()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
{
|
{
|
||||||
++bytes[i];
|
++bytes[i];
|
||||||
if (bytes[i] != 0)
|
if (bytes[i] != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian<T> operator -- (int)
|
LittleEndian<T> operator -- (int)
|
||||||
{
|
{
|
||||||
LittleEndian<T> tmp(*this);
|
LittleEndian<T> tmp(*this);
|
||||||
operator -- ();
|
operator -- ();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
LittleEndian<T> & operator -- ()
|
LittleEndian<T> & operator -- ()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
{
|
{
|
||||||
--bytes[i];
|
--bytes[i];
|
||||||
if (bytes[i] != (T)(-1))
|
if (bytes[i] != (T)(-1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
@ -137,105 +137,105 @@ struct LittleEndian
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct BigEndian
|
struct BigEndian
|
||||||
{
|
{
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
unsigned char bytes[sizeof(T)];
|
unsigned char bytes[sizeof(T)];
|
||||||
T raw_value;
|
T raw_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
BigEndian(T t = T())
|
BigEndian(T t = T())
|
||||||
{
|
{
|
||||||
operator =(t);
|
operator =(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian(const BigEndian<T> & t)
|
BigEndian(const BigEndian<T> & t)
|
||||||
{
|
{
|
||||||
raw_value = t.raw_value;
|
raw_value = t.raw_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian(const LittleEndian<T> & t)
|
BigEndian(const LittleEndian<T> & t)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
bytes[i] = t.bytes[sizeof(T)-1-i];
|
bytes[i] = t.bytes[sizeof(T)-1-i];
|
||||||
}
|
}
|
||||||
|
|
||||||
operator const T() const
|
operator const T() const
|
||||||
{
|
{
|
||||||
T t = T();
|
T t = T();
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
|
t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator = (const T t)
|
const T operator = (const T t)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
bytes[sizeof(T) - 1 - i] = t >> (i << 3);
|
bytes[sizeof(T) - 1 - i] = t >> (i << 3);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
// operators
|
// operators
|
||||||
|
|
||||||
const T operator += (const T t)
|
const T operator += (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this + t);
|
return (*this = *this + t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator -= (const T t)
|
const T operator -= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this - t);
|
return (*this = *this - t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator *= (const T t)
|
const T operator *= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this * t);
|
return (*this = *this * t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator /= (const T t)
|
const T operator /= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this / t);
|
return (*this = *this / t);
|
||||||
}
|
}
|
||||||
|
|
||||||
const T operator %= (const T t)
|
const T operator %= (const T t)
|
||||||
{
|
{
|
||||||
return (*this = *this % t);
|
return (*this = *this % t);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian<T> operator ++ (int)
|
BigEndian<T> operator ++ (int)
|
||||||
{
|
{
|
||||||
BigEndian<T> tmp(*this);
|
BigEndian<T> tmp(*this);
|
||||||
operator ++ ();
|
operator ++ ();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian<T> & operator ++ ()
|
BigEndian<T> & operator ++ ()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
{
|
{
|
||||||
++bytes[sizeof(T) - 1 - i];
|
++bytes[sizeof(T) - 1 - i];
|
||||||
if (bytes[sizeof(T) - 1 - i] != 0)
|
if (bytes[sizeof(T) - 1 - i] != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian<T> operator -- (int)
|
BigEndian<T> operator -- (int)
|
||||||
{
|
{
|
||||||
BigEndian<T> tmp(*this);
|
BigEndian<T> tmp(*this);
|
||||||
operator -- ();
|
operator -- ();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigEndian<T> & operator -- ()
|
BigEndian<T> & operator -- ()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < sizeof(T); i++)
|
for (unsigned i = 0; i < sizeof(T); i++)
|
||||||
{
|
{
|
||||||
--bytes[sizeof(T) - 1 - i];
|
--bytes[sizeof(T) - 1 - i];
|
||||||
if (bytes[sizeof(T) - 1 - i] != (T)(-1))
|
if (bytes[sizeof(T) - 1 - i] != (T)(-1))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
|
@ -110,18 +110,18 @@ namespace log {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string str_tolower(std::string s) {
|
std::string str_tolower(std::string s) {
|
||||||
std::transform(s.begin(), s.end(), s.begin(),
|
std::transform(s.begin(), s.end(), s.begin(),
|
||||||
// static_cast<int(*)(int)>(std::tolower) // wrong
|
// static_cast<int(*)(int)>(std::tolower) // wrong
|
||||||
// [](int c){ return std::tolower(c); } // wrong
|
// [](int c){ return std::tolower(c); } // wrong
|
||||||
// [](char c){ return std::tolower(c); } // wrong
|
// [](char c){ return std::tolower(c); } // wrong
|
||||||
[](unsigned char c){ return std::tolower(c); } // correct
|
[](unsigned char c){ return std::tolower(c); } // correct
|
||||||
);
|
);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SetLogLevel (const std::string& level_) {
|
void Log::SetLogLevel (const std::string& level_) {
|
||||||
std::string level=str_tolower(level_);
|
std::string level=str_tolower(level_);
|
||||||
if (level == "none") { m_MinLevel = eLogNone; }
|
if (level == "none") { m_MinLevel = eLogNone; }
|
||||||
else if (level == "error") { m_MinLevel = eLogError; }
|
else if (level == "error") { m_MinLevel = eLogError; }
|
||||||
else if (level == "warn") { m_MinLevel = eLogWarning; }
|
else if (level == "warn") { m_MinLevel = eLogWarning; }
|
||||||
|
@ -240,7 +240,7 @@ namespace log {
|
||||||
static ThrowFunction g_ThrowFunction;
|
static ThrowFunction g_ThrowFunction;
|
||||||
ThrowFunction GetThrowFunction () { return g_ThrowFunction; }
|
ThrowFunction GetThrowFunction () { return g_ThrowFunction; }
|
||||||
void SetThrowFunction (ThrowFunction f) { g_ThrowFunction = f; }
|
void SetThrowFunction (ThrowFunction f) { g_ThrowFunction = f; }
|
||||||
|
|
||||||
} // log
|
} // log
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -155,9 +155,9 @@ namespace log {
|
||||||
|
|
||||||
typedef std::function<void (const std::string&)> ThrowFunction;
|
typedef std::function<void (const std::string&)> ThrowFunction;
|
||||||
ThrowFunction GetThrowFunction ();
|
ThrowFunction GetThrowFunction ();
|
||||||
void SetThrowFunction (ThrowFunction f);
|
void SetThrowFunction (ThrowFunction f);
|
||||||
} // log
|
} // log
|
||||||
}
|
} // i2p
|
||||||
|
|
||||||
/** internal usage only -- folding args array to single string */
|
/** internal usage only -- folding args array to single string */
|
||||||
template<typename TValue>
|
template<typename TValue>
|
||||||
|
@ -203,7 +203,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Throw fatal error message with the list of arguments
|
* @brief Throw fatal error message with the list of arguments
|
||||||
* @param args Array of message parts
|
* @param args Array of message parts
|
||||||
*/
|
*/
|
||||||
template<typename... TArgs>
|
template<typename... TArgs>
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace transport
|
||||||
|
|
||||||
void NTCP2Establisher::KDF2Bob ()
|
void NTCP2Establisher::KDF2Bob ()
|
||||||
{
|
{
|
||||||
KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
|
KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Establisher::KDF3Alice ()
|
void NTCP2Establisher::KDF3Alice ()
|
||||||
|
@ -707,7 +707,7 @@ namespace transport
|
||||||
auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already
|
auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already
|
||||||
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
|
||||||
if (m_Server.AddNTCP2Session (shared_from_this (), true))
|
if (m_Server.AddNTCP2Session (shared_from_this (), true))
|
||||||
{
|
{
|
||||||
Established ();
|
Established ();
|
||||||
ReceiveLength ();
|
ReceiveLength ();
|
||||||
}
|
}
|
||||||
|
@ -1200,7 +1200,7 @@ namespace transport
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
|
LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port);
|
||||||
auto conn = std::make_shared<NTCP2Session>(*this);
|
auto conn = std::make_shared<NTCP2Session>(*this);
|
||||||
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
|
m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
@ -1218,8 +1218,8 @@ namespace transport
|
||||||
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
|
LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port);
|
||||||
auto conn = std::make_shared<NTCP2Session> (*this);
|
auto conn = std::make_shared<NTCP2Session> (*this);
|
||||||
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1));
|
m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
|
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
|
||||||
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
||||||
|
@ -1485,7 +1485,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
|
auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
|
||||||
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2),
|
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2),
|
||||||
[this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred)
|
[this, readbuff, timer, conn, host, port, addrtype](const boost::system::error_code & ec, std::size_t transferred)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -1531,8 +1531,8 @@ namespace transport
|
||||||
std::ostream out(&writebuff);
|
std::ostream out(&writebuff);
|
||||||
out << req.to_string();
|
out << req.to_string();
|
||||||
|
|
||||||
boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(),
|
boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(),
|
||||||
[](const boost::system::error_code & ec, std::size_t transferred)
|
[](const boost::system::error_code & ec, std::size_t transferred)
|
||||||
{
|
{
|
||||||
(void) transferred;
|
(void) transferred;
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@ -1540,8 +1540,8 @@ namespace transport
|
||||||
});
|
});
|
||||||
|
|
||||||
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
|
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
|
||||||
boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n",
|
boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n",
|
||||||
[this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred)
|
[this, readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,7 +126,6 @@ namespace transport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr);
|
||||||
~NTCP2Session ();
|
~NTCP2Session ();
|
||||||
void Terminate ();
|
void Terminate ();
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
std::shared_ptr<NTCPSession> session;
|
std::shared_ptr<NTCPSession> session;
|
||||||
};
|
};
|
||||||
|
|
||||||
NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
NTCPSession::NTCPSession (NTCPServer& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter):
|
||||||
TransportSession (in_RemoteRouter, NTCP_ESTABLISH_TIMEOUT),
|
TransportSession (in_RemoteRouter, NTCP_ESTABLISH_TIMEOUT),
|
||||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||||
|
@ -468,7 +468,7 @@ namespace transport
|
||||||
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
|
LogPrint (eLogError, "NTCP: Phase 4 read error: ", ecode.message (), ". Check your clock");
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
// this router doesn't like us
|
// this router doesn't like us
|
||||||
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true);
|
i2p::data::netdb.SetUnreachable (GetRemoteIdentity ()->GetIdentHash (), true);
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
@ -736,13 +736,11 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NTCPSession::SendTimeSyncMessage ()
|
void NTCPSession::SendTimeSyncMessage ()
|
||||||
{
|
{
|
||||||
Send (nullptr);
|
Send (nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
void NTCPSession::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||||
{
|
{
|
||||||
m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs));
|
m_Server.GetService ().post (std::bind (&NTCPSession::PostI2NPMessages, shared_from_this (), msgs));
|
||||||
|
@ -821,8 +819,8 @@ namespace transport
|
||||||
{
|
{
|
||||||
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
m_NTCPAcceptor = new boost::asio::ip::tcp::acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), address->port));
|
||||||
LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port);
|
LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port);
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
/** fail to bind ip4 */
|
/** fail to bind ip4 */
|
||||||
LogPrint(eLogError, "NTCP: Failed to bind to v4 port ", address->port, ": ", ex.what());
|
LogPrint(eLogError, "NTCP: Failed to bind to v4 port ", address->port, ": ", ex.what());
|
||||||
|
@ -848,8 +846,8 @@ namespace transport
|
||||||
LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port);
|
LogPrint (eLogInfo, "NTCP: Start listening v6 TCP port ", address->port);
|
||||||
auto conn = std::make_shared<NTCPSession> (*this);
|
auto conn = std::make_shared<NTCPSession> (*this);
|
||||||
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this, conn, std::placeholders::_1));
|
m_NTCPV6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCPServer::HandleAcceptV6, this, conn, std::placeholders::_1));
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP: failed to bind to v6 port ", address->port, ": ", ex.what());
|
LogPrint(eLogError, "NTCP: failed to bind to v6 port ", address->port, ": ", ex.what());
|
||||||
ThrowFatal (eLogError, "Unable to start IPv6 NTCP transport at port ", address->port, ": ", ex.what ());
|
ThrowFatal (eLogError, "Unable to start IPv6 NTCP transport at port ", address->port, ": ", ex.what ());
|
||||||
|
@ -904,7 +902,6 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NTCPServer::Run ()
|
void NTCPServer::Run ()
|
||||||
{
|
{
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
|
|
|
@ -216,10 +216,10 @@ namespace data
|
||||||
LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
|
LogPrint (eLogDebug, "NetDb: RouterInfo floodfill status updated: ", ident.ToBase64());
|
||||||
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
std::unique_lock<std::mutex> l(m_FloodfillsMutex);
|
||||||
if (wasFloodfill)
|
if (wasFloodfill)
|
||||||
m_Floodfills.remove (r);
|
m_Floodfills.remove (r);
|
||||||
else
|
else
|
||||||
m_Floodfills.push_back (r);
|
m_Floodfills.push_back (r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -390,7 +390,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Reseeder->Bootstrap ();
|
m_Reseeder->Bootstrap ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
||||||
|
@ -532,12 +532,12 @@ namespace data
|
||||||
auto total = m_RouterInfos.size ();
|
auto total = m_RouterInfos.size ();
|
||||||
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL;
|
||||||
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
auto uptime = i2p::context.GetUptime ();
|
auto uptime = i2p::context.GetUptime ();
|
||||||
// routers don't expire if less than 90 or uptime is less than 1 hour
|
// routers don't expire if less than 90 or uptime is less than 1 hour
|
||||||
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
|
bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes
|
||||||
if (checkForExpiration && uptime > 3600) // 1 hour
|
if (checkForExpiration && uptime > 3600) // 1 hour
|
||||||
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
|
expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL :
|
||||||
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
|
NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total;
|
||||||
|
|
||||||
for (auto& it: m_RouterInfos)
|
for (auto& it: m_RouterInfos)
|
||||||
{
|
{
|
||||||
|
@ -555,7 +555,7 @@ namespace data
|
||||||
// find & mark expired routers
|
// find & mark expired routers
|
||||||
if (it.second->UsesIntroducer ())
|
if (it.second->UsesIntroducer ())
|
||||||
{
|
{
|
||||||
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
|
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
|
||||||
// RouterInfo expires after 1 hour if uses introducer
|
// RouterInfo expires after 1 hour if uses introducer
|
||||||
it.second->SetUnreachable (true);
|
it.second->SetUnreachable (true);
|
||||||
}
|
}
|
||||||
|
@ -873,7 +873,7 @@ namespace data
|
||||||
std::shared_ptr<I2NPMessage> replyMsg;
|
std::shared_ptr<I2NPMessage> replyMsg;
|
||||||
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
|
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
|
||||||
std::set<IdentHash> excludedRouters;
|
std::set<IdentHash> excludedRouters;
|
||||||
for (int i = 0; i < numExcluded; i++)
|
for (int i = 0; i < numExcluded; i++)
|
||||||
{
|
{
|
||||||
|
@ -894,7 +894,7 @@ namespace data
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
||||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
||||||
{
|
{
|
||||||
auto router = FindRouter (ident);
|
auto router = FindRouter (ident);
|
||||||
|
@ -907,7 +907,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);
|
||||||
|
@ -957,12 +957,12 @@ namespace data
|
||||||
replyMsg = i2p::garlic::WrapECIESX25519AEADRatchetMessage (replyMsg, sessionKey, tag);
|
replyMsg = i2p::garlic::WrapECIESX25519AEADRatchetMessage (replyMsg, sessionKey, tag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
|
const i2p::garlic::SessionTag sessionTag(excluded + 33); // take first tag
|
||||||
i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag);
|
i2p::garlic::ElGamalAESSession garlic (sessionKey, sessionTag);
|
||||||
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
||||||
}
|
}
|
||||||
if (!replyMsg)
|
if (!replyMsg)
|
||||||
LogPrint (eLogError, "NetDb: failed to wrap message");
|
LogPrint (eLogError, "NetDb: failed to wrap message");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1103,7 +1103,7 @@ namespace data
|
||||||
{
|
{
|
||||||
return !router->IsHidden () && router->IsSSUV6 ();
|
return !router->IsHidden () && router->IsSSUV6 ();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomIntroducer () const
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomIntroducer () const
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,12 +28,12 @@ namespace i2p
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
const int NETDB_MIN_ROUTERS = 90;
|
const int NETDB_MIN_ROUTERS = 90;
|
||||||
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds
|
const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60 * 60; // 1 hour, in seconds
|
||||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60;
|
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
||||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90*60; // 1.5 hours
|
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
||||||
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27*60*60; // 27 hours
|
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
|
||||||
const int NETDB_PUBLISH_INTERVAL = 60*40;
|
const int NETDB_PUBLISH_INTERVAL = 60 * 40;
|
||||||
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0,9,36); // 0.9.36
|
const int NETDB_MIN_HIGHBANDWIDTH_VERSION = MAKE_VERSION_NUMBER(0, 9, 36); // 0.9.36
|
||||||
|
|
||||||
/** function for visiting a leaseset stored in a floodfill */
|
/** function for visiting a leaseset stored in a floodfill */
|
||||||
typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor;
|
typedef std::function<void(const IdentHash, std::shared_ptr<LeaseSet>)> LeaseSetVisitor;
|
||||||
|
@ -63,13 +63,13 @@ namespace data
|
||||||
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
std::shared_ptr<RouterProfile> FindRouterProfile (const IdentHash& ident) const;
|
||||||
|
|
||||||
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||||
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr);
|
||||||
|
|
||||||
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseStoreMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseSearchReplyMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
|
void HandleDatabaseLookupMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
|
void HandleNTCP2RouterInfoMsg (std::shared_ptr<const I2NPMessage> m);
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter () const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||||
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith) const;
|
||||||
|
@ -80,13 +80,13 @@ namespace data
|
||||||
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
||||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||||
|
|
||||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
|
||||||
/** set hidden mode, aka don't publish our RI to netdb and don't explore */
|
/** set hidden mode, aka don't publish our RI to netdb and don't explore */
|
||||||
void SetHidden(bool hide);
|
void SetHidden(bool hide);
|
||||||
|
|
||||||
void Reseed ();
|
void Reseed ();
|
||||||
Families& GetFamilies () { return m_Families; };
|
Families& GetFamilies () { return m_Families; };
|
||||||
|
@ -119,12 +119,13 @@ namespace data
|
||||||
void ManageLeaseSets ();
|
void ManageLeaseSets ();
|
||||||
void ManageRequests ();
|
void ManageRequests ();
|
||||||
|
|
||||||
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20);
|
void ReseedFromFloodfill(const RouterInfo & ri, int numRouters = 40, int numFloodfills = 20);
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
|
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len, bool& updated);
|
||||||
std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
|
std::shared_ptr<const RouterInfo> AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len, bool& updated);
|
||||||
template<typename Filter>
|
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
template<typename Filter>
|
||||||
|
std::shared_ptr<const RouterInfo> GetRandomRouter (Filter filter) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -150,12 +151,12 @@ namespace data
|
||||||
|
|
||||||
bool m_PersistProfiles;
|
bool m_PersistProfiles;
|
||||||
|
|
||||||
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
/** router info we are bootstrapping from or nullptr if we are not currently doing that*/
|
||||||
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
std::shared_ptr<RouterInfo> m_FloodfillBootstrap;
|
||||||
|
|
||||||
|
|
||||||
/** true if in hidden mode */
|
/** true if in hidden mode */
|
||||||
bool m_HiddenMode;
|
bool m_HiddenMode;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetDb netdb;
|
extern NetDb netdb;
|
||||||
|
|
|
@ -14,8 +14,8 @@ namespace data
|
||||||
std::shared_ptr<I2NPMessage> msg;
|
std::shared_ptr<I2NPMessage> msg;
|
||||||
if(replyTunnel)
|
if(replyTunnel)
|
||||||
msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
|
msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination,
|
||||||
replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
|
replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory,
|
||||||
&m_ExcludedPeers);
|
&m_ExcludedPeers);
|
||||||
else
|
else
|
||||||
msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
|
msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers);
|
||||||
if(router)
|
if(router)
|
||||||
|
@ -158,4 +158,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,4 +66,3 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,11 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
|
|
||||||
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz)
|
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz)
|
||||||
{
|
{
|
||||||
Poly1305 p(key);
|
Poly1305 p(key);
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/**
|
||||||
This code is licensed under the MCGSI Public License
|
* This code is licensed under the MCGSI Public License
|
||||||
Copyright 2018 Jeff Becker
|
* Copyright 2018 Jeff Becker
|
||||||
|
*
|
||||||
Kovri go write your own code
|
* Kovri go write your own code
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef LIBI2PD_POLY1305_H
|
#ifndef LIBI2PD_POLY1305_H
|
||||||
#define LIBI2PD_POLY1305_H
|
#define LIBI2PD_POLY1305_H
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
|
||||||
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
#if !OPENSSL_AEAD_CHACHA20_POLY1305
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
|
@ -24,7 +24,6 @@ namespace crypto
|
||||||
|
|
||||||
namespace poly1305
|
namespace poly1305
|
||||||
{
|
{
|
||||||
|
|
||||||
struct LongBlock
|
struct LongBlock
|
||||||
{
|
{
|
||||||
unsigned long data[17];
|
unsigned long data[17];
|
||||||
|
@ -252,8 +251,8 @@ namespace crypto
|
||||||
poly1305::LongBlock m_HR;
|
poly1305::LongBlock m_HR;
|
||||||
uint8_t m_Final;
|
uint8_t m_Final;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
|
void Poly1305HMAC(uint64_t * out, const uint64_t * key, const uint8_t * buf, std::size_t sz);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,73 +32,76 @@ namespace data
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief tries to bootstrap into I2P network (from local files and servers, with respect of options)
|
/**
|
||||||
*/
|
@brief tries to bootstrap into I2P network (from local files and servers, with respect of options)
|
||||||
void Reseeder::Bootstrap ()
|
*/
|
||||||
{
|
void Reseeder::Bootstrap ()
|
||||||
std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName);
|
{
|
||||||
std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName);
|
std::string su3FileName; i2p::config::GetOption("reseed.file", su3FileName);
|
||||||
|
std::string zipFileName; i2p::config::GetOption("reseed.zipfile", zipFileName);
|
||||||
|
|
||||||
if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
|
if (su3FileName.length() > 0) // bootstrap from SU3 file or URL
|
||||||
{
|
{
|
||||||
int num;
|
int num;
|
||||||
if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://")
|
if (su3FileName.length() > 8 && su3FileName.substr(0, 8) == "https://")
|
||||||
{
|
{
|
||||||
num = ReseedFromSU3Url (su3FileName); // from https URL
|
num = ReseedFromSU3Url (su3FileName); // from https URL
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
num = ProcessSU3File (su3FileName.c_str ());
|
num = ProcessSU3File (su3FileName.c_str ());
|
||||||
}
|
}
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName);
|
LogPrint (eLogWarning, "Reseed: failed to reseed from ", su3FileName);
|
||||||
}
|
}
|
||||||
else if (zipFileName.length() > 0) // bootstrap from ZIP file
|
else if (zipFileName.length() > 0) // bootstrap from ZIP file
|
||||||
{
|
{
|
||||||
int num = ProcessZIPFile (zipFileName.c_str ());
|
int num = ProcessZIPFile (zipFileName.c_str ());
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName);
|
LogPrint (eLogWarning, "Reseed: failed to reseed from ", zipFileName);
|
||||||
}
|
}
|
||||||
else // bootstrap from reseed servers
|
else // bootstrap from reseed servers
|
||||||
{
|
{
|
||||||
int num = ReseedFromServers ();
|
int num = ReseedFromServers ();
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
LogPrint (eLogWarning, "Reseed: failed to reseed from servers");
|
LogPrint (eLogWarning, "Reseed: failed to reseed from servers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief bootstrap from random server, retry 10 times
|
/**
|
||||||
* @return number of entries added to netDb
|
* @brief bootstrap from random server, retry 10 times
|
||||||
*/
|
* @return number of entries added to netDb
|
||||||
|
*/
|
||||||
int Reseeder::ReseedFromServers ()
|
int Reseeder::ReseedFromServers ()
|
||||||
{
|
{
|
||||||
std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
|
std::string reseedURLs; i2p::config::GetOption("reseed.urls", reseedURLs);
|
||||||
std::vector<std::string> httpsReseedHostList;
|
std::vector<std::string> httpsReseedHostList;
|
||||||
boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
|
boost::split(httpsReseedHostList, reseedURLs, boost::is_any_of(","), boost::token_compress_on);
|
||||||
|
|
||||||
if (reseedURLs.length () == 0)
|
if (reseedURLs.length () == 0)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Reseed: No reseed servers specified");
|
LogPrint (eLogWarning, "Reseed: No reseed servers specified");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int reseedRetries = 0;
|
int reseedRetries = 0;
|
||||||
while (reseedRetries < 10)
|
while (reseedRetries < 10)
|
||||||
{
|
{
|
||||||
auto ind = rand () % httpsReseedHostList.size ();
|
auto ind = rand () % httpsReseedHostList.size ();
|
||||||
std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
|
std::string reseedUrl = httpsReseedHostList[ind] + "i2pseeds.su3";
|
||||||
auto num = ReseedFromSU3Url (reseedUrl);
|
auto num = ReseedFromSU3Url (reseedUrl);
|
||||||
if (num > 0) return num; // success
|
if (num > 0) return num; // success
|
||||||
reseedRetries++;
|
reseedRetries++;
|
||||||
}
|
}
|
||||||
LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts");
|
LogPrint (eLogWarning, "Reseed: failed to reseed from servers after 10 attempts");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief bootstrap from HTTPS URL with SU3 file
|
/**
|
||||||
* @param url
|
* @brief bootstrap from HTTPS URL with SU3 file
|
||||||
* @return number of entries added to netDb
|
* @param url
|
||||||
*/
|
* @return number of entries added to netDb
|
||||||
|
*/
|
||||||
int Reseeder::ReseedFromSU3Url (const std::string& url)
|
int Reseeder::ReseedFromSU3Url (const std::string& url)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
|
LogPrint (eLogInfo, "Reseed: Downloading SU3 from ", url);
|
||||||
|
@ -702,4 +705,3 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace data
|
||||||
|
|
||||||
Reseeder();
|
Reseeder();
|
||||||
~Reseeder();
|
~Reseeder();
|
||||||
void Bootstrap ();
|
void Bootstrap ();
|
||||||
int ReseedFromServers ();
|
int ReseedFromServers ();
|
||||||
int ReseedFromSU3Url (const std::string& url);
|
int ReseedFromSU3Url (const std::string& url);
|
||||||
int ProcessSU3File (const char * filename);
|
int ProcessSU3File (const char * filename);
|
||||||
|
|
|
@ -338,10 +338,10 @@ namespace i2p
|
||||||
{
|
{
|
||||||
case low : /* not set */; break;
|
case low : /* not set */; break;
|
||||||
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
|
case extra : caps |= i2p::data::RouterInfo::eExtraBandwidth; break; // 'P'
|
||||||
case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth;
|
case unlim : caps |= i2p::data::RouterInfo::eExtraBandwidth;
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
// no break here, extra + high means 'X'
|
// no break here, extra + high means 'X'
|
||||||
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
|
case high : caps |= i2p::data::RouterInfo::eHighBandwidth; break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
const char ROUTER_INFO[] = "router.info";
|
const char ROUTER_INFO[] = "router.info";
|
||||||
const char ROUTER_KEYS[] = "router.keys";
|
const char ROUTER_KEYS[] = "router.keys";
|
||||||
const char NTCP2_KEYS[] = "ntcp2.keys";
|
const char NTCP2_KEYS[] = "ntcp2.keys";
|
||||||
const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes
|
const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes
|
||||||
|
|
||||||
enum RouterStatus
|
enum RouterStatus
|
||||||
|
@ -36,12 +36,12 @@ namespace i2p
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct NTCP2PrivateKeys
|
struct NTCP2PrivateKeys
|
||||||
{
|
{
|
||||||
uint8_t staticPublicKey[32];
|
uint8_t staticPublicKey[32];
|
||||||
uint8_t staticPrivateKey[32];
|
uint8_t staticPrivateKey[32];
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ namespace i2p
|
||||||
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
|
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
|
||||||
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
|
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
|
||||||
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
|
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
|
||||||
i2p::crypto::X25519Keys& GetStaticKeys ();
|
i2p::crypto::X25519Keys& GetStaticKeys ();
|
||||||
|
|
||||||
uint32_t GetUptime () const; // in seconds
|
uint32_t GetUptime () const; // in seconds
|
||||||
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
|
||||||
|
@ -77,7 +77,7 @@ namespace i2p
|
||||||
void SetNetID (int netID) { m_NetID = netID; };
|
void SetNetID (int netID) { m_NetID = netID; };
|
||||||
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
||||||
|
|
||||||
void UpdatePort (int port); // called from Daemon
|
void UpdatePort (int port); // called from Daemon
|
||||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||||
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
void PublishNTCP2Address (int port, bool publish = true, bool v4only = false);
|
||||||
void UpdateNTCP2Address (bool enable);
|
void UpdateNTCP2Address (bool enable);
|
||||||
|
@ -124,7 +124,7 @@ namespace i2p
|
||||||
|
|
||||||
// implements GarlicDestination
|
// implements GarlicDestination
|
||||||
void HandleI2NPMessage (const uint8_t * buf, size_t len);
|
void HandleI2NPMessage (const uint8_t * buf, size_t len);
|
||||||
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented
|
bool HandleCloveI2NPMessage (I2NPMessageType typeID, const uint8_t * payload, size_t len) { return false; }; // not implemented
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ namespace i2p
|
||||||
i2p::data::PrivateKeys m_Keys;
|
i2p::data::PrivateKeys m_Keys;
|
||||||
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
|
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
|
||||||
uint64_t m_LastUpdateTime; // in seconds
|
uint64_t m_LastUpdateTime; // in seconds
|
||||||
bool m_AcceptsTunnels, m_IsFloodfill;
|
bool m_AcceptsTunnels, m_IsFloodfill;
|
||||||
std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
|
std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
|
||||||
uint64_t m_BandwidthLimit; // allowed bandwidth
|
uint64_t m_BandwidthLimit; // allowed bandwidth
|
||||||
int m_ShareRatio;
|
int m_ShareRatio;
|
||||||
|
|
|
@ -35,12 +35,12 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
RouterInfo::RouterInfo (const uint8_t * buf, int len):
|
RouterInfo::RouterInfo (const uint8_t * buf, int len):
|
||||||
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0),
|
m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0),
|
||||||
m_Caps (0), m_Version (0)
|
m_Caps (0), m_Version (0)
|
||||||
{
|
{
|
||||||
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
m_Addresses = boost::make_shared<Addresses>(); // create empty list
|
||||||
if (len <= MAX_RI_BUFFER_SIZE)
|
if (len <= MAX_RI_BUFFER_SIZE)
|
||||||
{
|
{
|
||||||
m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE];
|
m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE];
|
||||||
memcpy (m_Buffer, buf, len);
|
memcpy (m_Buffer, buf, len);
|
||||||
m_BufferLen = len;
|
m_BufferLen = len;
|
||||||
|
@ -173,7 +173,6 @@ namespace data
|
||||||
LogPrint (eLogError, "RouterInfo: malformed message");
|
LogPrint (eLogError, "RouterInfo: malformed message");
|
||||||
m_IsUnreachable = true;
|
m_IsUnreachable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::ReadFromStream (std::istream& s)
|
void RouterInfo::ReadFromStream (std::istream& s)
|
||||||
|
@ -192,7 +191,7 @@ namespace data
|
||||||
s.read ((char *)&address->cost, sizeof (address->cost));
|
s.read ((char *)&address->cost, sizeof (address->cost));
|
||||||
s.read ((char *)&address->date, sizeof (address->date));
|
s.read ((char *)&address->date, sizeof (address->date));
|
||||||
bool isNTCP2Only = false;
|
bool isNTCP2Only = false;
|
||||||
char transportStyle[6];
|
char transportStyle[6];
|
||||||
auto transportStyleLen = ReadString (transportStyle, 6, s) - 1;
|
auto transportStyleLen = ReadString (transportStyle, 6, s) - 1;
|
||||||
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2
|
||||||
{
|
{
|
||||||
|
@ -231,13 +230,13 @@ namespace data
|
||||||
address->host.to_string (ecode);
|
address->host.to_string (ecode);
|
||||||
if (!ecode)
|
if (!ecode)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// add supported protocol
|
// add supported protocol
|
||||||
if (address->host.is_v4 ())
|
if (address->host.is_v4 ())
|
||||||
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
|
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4;
|
||||||
else
|
else
|
||||||
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
|
supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp (key, "port"))
|
else if (!strcmp (key, "port"))
|
||||||
|
@ -262,15 +261,15 @@ namespace data
|
||||||
{
|
{
|
||||||
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
||||||
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
||||||
Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32);
|
Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32);
|
||||||
}
|
}
|
||||||
else if (!strcmp (key, "i")) // ntcp2 iv
|
else if (!strcmp (key, "i")) // ntcp2 iv
|
||||||
{
|
{
|
||||||
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
if (!address->ntcp2) address->ntcp2.reset (new NTCP2Ext ());
|
||||||
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
supportedTransports |= (address->host.is_v4 ()) ? eNTCP2V4 : eNTCP2V6;
|
||||||
Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16);
|
Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16);
|
||||||
address->ntcp2->isPublished = true; // presence if "i" means "published"
|
address->ntcp2->isPublished = true; // presence if "i" means "published"
|
||||||
}
|
}
|
||||||
else if (key[0] == 'i')
|
else if (key[0] == 'i')
|
||||||
{
|
{
|
||||||
// introducers
|
// introducers
|
||||||
|
@ -278,7 +277,7 @@ namespace data
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
|
LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
introducers = true;
|
introducers = true;
|
||||||
size_t l = strlen(key);
|
size_t l = strlen(key);
|
||||||
unsigned char index = key[l-1] - '0'; // TODO:
|
unsigned char index = key[l-1] - '0'; // TODO:
|
||||||
|
@ -309,7 +308,7 @@ namespace data
|
||||||
}
|
}
|
||||||
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented
|
||||||
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
if (isNTCP2Only && address->ntcp2) address->ntcp2->isNTCP2Only = true;
|
||||||
if (supportedTransports)
|
if (supportedTransports)
|
||||||
{
|
{
|
||||||
addresses->push_back(address);
|
addresses->push_back(address);
|
||||||
m_SupportedTransports |= supportedTransports;
|
m_SupportedTransports |= supportedTransports;
|
||||||
|
@ -349,13 +348,13 @@ namespace data
|
||||||
while (*ch)
|
while (*ch)
|
||||||
{
|
{
|
||||||
if (*ch >= '0' && *ch <= '9')
|
if (*ch >= '0' && *ch <= '9')
|
||||||
{
|
{
|
||||||
m_Version *= 10;
|
m_Version *= 10;
|
||||||
m_Version += (*ch - '0');
|
m_Version += (*ch - '0');
|
||||||
}
|
}
|
||||||
ch++;
|
ch++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check netId
|
// check netId
|
||||||
else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ())
|
else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ())
|
||||||
{
|
{
|
||||||
|
@ -384,9 +383,10 @@ namespace data
|
||||||
SetUnreachable (true);
|
SetUnreachable (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RouterInfo::IsFamily(const std::string & fam) const {
|
bool RouterInfo::IsFamily(const std::string & fam) const
|
||||||
return m_Family == fam;
|
{
|
||||||
}
|
return m_Family == fam;
|
||||||
|
}
|
||||||
|
|
||||||
void RouterInfo::ExtractCaps (const char * value)
|
void RouterInfo::ExtractCaps (const char * value)
|
||||||
{
|
{
|
||||||
|
@ -580,7 +580,7 @@ namespace data
|
||||||
properties << '=';
|
properties << '=';
|
||||||
WriteString (boost::lexical_cast<std::string>(address.port), properties);
|
WriteString (boost::lexical_cast<std::string>(address.port), properties);
|
||||||
properties << ';';
|
properties << ';';
|
||||||
}
|
}
|
||||||
if (address.IsNTCP2 ())
|
if (address.IsNTCP2 ())
|
||||||
{
|
{
|
||||||
// publish s and v for NTCP2
|
// publish s and v for NTCP2
|
||||||
|
@ -588,7 +588,7 @@ namespace data
|
||||||
WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';';
|
WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';';
|
||||||
WriteString ("v", properties); properties << '=';
|
WriteString ("v", properties); properties << '=';
|
||||||
WriteString ("2", properties); properties << ';';
|
WriteString ("2", properties); properties << ';';
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t size = htobe16 (properties.str ().size ());
|
uint16_t size = htobe16 (properties.str ().size ());
|
||||||
s.write ((char *)&size, sizeof (size));
|
s.write ((char *)&size, sizeof (size));
|
||||||
|
@ -742,7 +742,7 @@ namespace data
|
||||||
addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
|
addr->ntcp2->isNTCP2Only = true; // NTCP2 only address
|
||||||
if (port) addr->ntcp2->isPublished = true;
|
if (port) addr->ntcp2->isPublished = true;
|
||||||
memcpy (addr->ntcp2->staticKey, staticKey, 32);
|
memcpy (addr->ntcp2->staticKey, staticKey, 32);
|
||||||
memcpy (addr->ntcp2->iv, iv, 16);
|
memcpy (addr->ntcp2->iv, iv, 16);
|
||||||
m_Addresses->push_back(std::move(addr));
|
m_Addresses->push_back(std::move(addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -854,7 +854,7 @@ namespace data
|
||||||
m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6;
|
m_SupportedTransports |= eNTCPV6 | eSSUV6 | eNTCP2V6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::EnableV4 ()
|
void RouterInfo::EnableV4 ()
|
||||||
{
|
{
|
||||||
if (!IsV4 ())
|
if (!IsV4 ())
|
||||||
m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
|
m_SupportedTransports |= eNTCPV4 | eSSUV4 | eNTCP2V4;
|
||||||
|
@ -877,7 +877,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterInfo::DisableV4 ()
|
void RouterInfo::DisableV4 ()
|
||||||
{
|
{
|
||||||
if (IsV4 ())
|
if (IsV4 ())
|
||||||
{
|
{
|
||||||
|
@ -926,7 +926,7 @@ namespace data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Filter>
|
template<typename Filter>
|
||||||
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
|
||||||
{
|
{
|
||||||
// TODO: make it more generic using comparator
|
// TODO: make it more generic using comparator
|
||||||
|
@ -937,7 +937,7 @@ namespace data
|
||||||
#endif
|
#endif
|
||||||
for (const auto& address : *addresses)
|
for (const auto& address : *addresses)
|
||||||
if (filter (address)) return address;
|
if (filter (address)) return address;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,8 +203,8 @@ namespace data
|
||||||
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; };
|
||||||
bool IsNewer (const uint8_t * buf, size_t len) const;
|
bool IsNewer (const uint8_t * buf, size_t len) const;
|
||||||
|
|
||||||
/** return true if we are in a router family and the signature is valid */
|
/** return true if we are in a router family and the signature is valid */
|
||||||
bool IsFamily(const std::string & fam) const;
|
bool IsFamily(const std::string & fam) const;
|
||||||
|
|
||||||
// implements RoutingDestination
|
// implements RoutingDestination
|
||||||
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
|
std::shared_ptr<const IdentityEx> GetIdentity () const { return m_RouterIdentity; };
|
||||||
|
|
|
@ -45,15 +45,15 @@ namespace transport
|
||||||
|
|
||||||
void SSUServer::OpenSocket ()
|
void SSUServer::OpenSocket ()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_Socket.open (boost::asio::ip::udp::v4());
|
m_Socket.open (boost::asio::ip::udp::v4());
|
||||||
m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE));
|
m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE));
|
||||||
m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE));
|
m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE));
|
||||||
m_Socket.bind (m_Endpoint);
|
m_Socket.bind (m_Endpoint);
|
||||||
LogPrint (eLogInfo, "SSU: Start listening v4 port ", m_Endpoint.port());
|
LogPrint (eLogInfo, "SSU: Start listening v4 port ", m_Endpoint.port());
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SSU: failed to bind to v4 port ", m_Endpoint.port(), ": ", ex.what());
|
LogPrint (eLogError, "SSU: failed to bind to v4 port ", m_Endpoint.port(), ": ", ex.what());
|
||||||
ThrowFatal ("Unable to start IPv4 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
|
ThrowFatal ("Unable to start IPv4 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
|
||||||
|
@ -62,7 +62,7 @@ namespace transport
|
||||||
|
|
||||||
void SSUServer::OpenSocketV6 ()
|
void SSUServer::OpenSocketV6 ()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_SocketV6.open (boost::asio::ip::udp::v6());
|
m_SocketV6.open (boost::asio::ip::udp::v6());
|
||||||
m_SocketV6.set_option (boost::asio::ip::v6_only (true));
|
m_SocketV6.set_option (boost::asio::ip::v6_only (true));
|
||||||
|
@ -70,8 +70,8 @@ namespace transport
|
||||||
m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE));
|
m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE));
|
||||||
m_SocketV6.bind (m_EndpointV6);
|
m_SocketV6.bind (m_EndpointV6);
|
||||||
LogPrint (eLogInfo, "SSU: Start listening v6 port ", m_EndpointV6.port());
|
LogPrint (eLogInfo, "SSU: Start listening v6 port ", m_EndpointV6.port());
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "SSU: failed to bind to v6 port ", m_EndpointV6.port(), ": ", ex.what());
|
LogPrint (eLogError, "SSU: failed to bind to v6 port ", m_EndpointV6.port(), ": ", ex.what());
|
||||||
ThrowFatal ("Unable to start IPv6 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
|
ThrowFatal ("Unable to start IPv6 SSU transport at port ", m_Endpoint.port(), ": ", ex.what ());
|
||||||
|
@ -184,7 +184,7 @@ namespace transport
|
||||||
m_Socket.close ();
|
m_Socket.close ();
|
||||||
OpenSocket ();
|
OpenSocket ();
|
||||||
Receive ();
|
Receive ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -359,10 +359,10 @@ namespace transport
|
||||||
{
|
{
|
||||||
if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous
|
if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous
|
||||||
{
|
{
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
session->FlushData ();
|
session->FlushData ();
|
||||||
session = nullptr;
|
session = nullptr;
|
||||||
}
|
}
|
||||||
auto it = sessions->find (packet->from);
|
auto it = sessions->find (packet->from);
|
||||||
if (it != sessions->end ())
|
if (it != sessions->end ())
|
||||||
|
@ -826,4 +826,3 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace transport
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SSUServer (int port);
|
SSUServer (int port);
|
||||||
SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor
|
SSUServer (const boost::asio::ip::address & addr, int port); // ipv6 only constructor
|
||||||
~SSUServer ();
|
~SSUServer ();
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
@ -135,4 +135,3 @@ namespace transport
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -496,7 +496,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
// decay
|
// decay
|
||||||
if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES ||
|
if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES ||
|
||||||
i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
|
i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL)
|
||||||
m_ReceivedMessages.clear ();
|
m_ReceivedMessages.clear ();
|
||||||
|
|
||||||
ScheduleIncompleteMessagesCleanup ();
|
ScheduleIncompleteMessagesCleanup ();
|
||||||
|
@ -504,4 +504,3 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,4 +128,3 @@ namespace transport
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -336,7 +336,7 @@ namespace transport
|
||||||
m_SignedData->Insert (payload, 4); // insert Alice's signed on time
|
m_SignedData->Insert (payload, 4); // insert Alice's signed on time
|
||||||
payload += 4; // signed-on time
|
payload += 4; // signed-on time
|
||||||
size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen ();
|
size_t paddingSize = (payload - buf) + m_RemoteIdentity->GetSignatureLen ();
|
||||||
paddingSize &= 0x0F; // %16
|
paddingSize &= 0x0F; // %16
|
||||||
if (paddingSize > 0) paddingSize = 16 - paddingSize;
|
if (paddingSize > 0) paddingSize = 16 - paddingSize;
|
||||||
payload += paddingSize;
|
payload += paddingSize;
|
||||||
// verify signature
|
// verify signature
|
||||||
|
@ -934,7 +934,7 @@ namespace transport
|
||||||
for (const auto& it: msgs)
|
for (const auto& it: msgs)
|
||||||
if (it)
|
if (it)
|
||||||
{
|
{
|
||||||
if (it->GetLength () <= SSU_MAX_I2NP_MESSAGE_SIZE)
|
if (it->GetLength () <= SSU_MAX_I2NP_MESSAGE_SIZE)
|
||||||
m_Data.Send (it);
|
m_Data.Send (it);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "SSU: I2NP message of size ", it->GetLength (), " can't be sent. Dropped");
|
LogPrint (eLogError, "SSU: I2NP message of size ", it->GetLength (), " can't be sent. Dropped");
|
||||||
|
@ -1206,4 +1206,3 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace transport
|
||||||
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
|
||||||
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
|
||||||
const int SSU_CLOCK_SKEW = 60; // in seconds
|
const int SSU_CLOCK_SKEW = 60; // in seconds
|
||||||
const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768;
|
const size_t SSU_MAX_I2NP_MESSAGE_SIZE = 32768;
|
||||||
|
|
||||||
// payload types (4 bits)
|
// payload types (4 bits)
|
||||||
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
|
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;
|
||||||
|
@ -81,12 +81,12 @@ namespace transport
|
||||||
void Done ();
|
void Done ();
|
||||||
void Failed ();
|
void Failed ();
|
||||||
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; };
|
||||||
|
|
||||||
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
|
bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); };
|
||||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
void SendPeerTest (); // Alice
|
void SendPeerTest (); // Alice
|
||||||
|
|
||||||
SessionState GetState () const { return m_State; };
|
SessionState GetState () const { return m_State; };
|
||||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||||
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; };
|
||||||
|
|
||||||
|
@ -158,10 +158,7 @@ namespace transport
|
||||||
std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only
|
std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only
|
||||||
std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie
|
std::map<uint32_t, std::shared_ptr<const i2p::data::RouterInfo> > m_RelayRequests; // nonce->Charlie
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
#if OPENSSL_EDDSA
|
#if OPENSSL_EDDSA
|
||||||
EDDSA25519Verifier::EDDSA25519Verifier ():
|
EDDSA25519Verifier::EDDSA25519Verifier ():
|
||||||
m_Pkey (nullptr)
|
m_Pkey (nullptr)
|
||||||
{
|
{
|
||||||
m_MDCtx = EVP_MD_CTX_create ();
|
m_MDCtx = EVP_MD_CTX_create ();
|
||||||
}
|
}
|
||||||
|
|
||||||
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
||||||
|
@ -23,21 +23,21 @@ namespace crypto
|
||||||
{
|
{
|
||||||
m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
|
m_Pkey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, signingKey, 32);
|
||||||
EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
EVP_DigestVerifyInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||||
{
|
{
|
||||||
return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len);
|
return EVP_DigestVerify (m_MDCtx, signature, 64, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
EDDSA25519Verifier::EDDSA25519Verifier ()
|
EDDSA25519Verifier::EDDSA25519Verifier ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
EDDSA25519Verifier::~EDDSA25519Verifier ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey)
|
void EDDSA25519Verifier::SetPublicKey (const uint8_t * signingKey)
|
||||||
{
|
{
|
||||||
|
@ -45,8 +45,8 @@ namespace crypto
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx);
|
m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
bool EDDSA25519Verifier::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
|
||||||
{
|
{
|
||||||
uint8_t digest[64];
|
uint8_t digest[64];
|
||||||
|
@ -83,19 +83,19 @@ namespace crypto
|
||||||
|
|
||||||
EDDSA25519SignerCompat::~EDDSA25519SignerCompat ()
|
EDDSA25519SignerCompat::~EDDSA25519SignerCompat ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void EDDSA25519SignerCompat::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
void EDDSA25519SignerCompat::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if OPENSSL_EDDSA
|
#if OPENSSL_EDDSA
|
||||||
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
|
EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey):
|
||||||
m_Fallback (nullptr)
|
m_Fallback (nullptr)
|
||||||
{
|
{
|
||||||
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
|
m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, signingPrivateKey, 32);
|
||||||
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 (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
if (signingPublicKey && memcmp (publicKey, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH))
|
||||||
|
@ -105,10 +105,10 @@ namespace crypto
|
||||||
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
|
m_Fallback = new EDDSA25519SignerCompat (signingPrivateKey, signingPublicKey);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_MDCtx = EVP_MD_CTX_create ();
|
m_MDCtx = EVP_MD_CTX_create ();
|
||||||
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
EVP_DigestSignInit (m_MDCtx, NULL, NULL, NULL, m_Pkey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EDDSA25519Signer::~EDDSA25519Signer ()
|
EDDSA25519Signer::~EDDSA25519Signer ()
|
||||||
|
@ -118,22 +118,20 @@ namespace crypto
|
||||||
{
|
{
|
||||||
EVP_MD_CTX_destroy (m_MDCtx);
|
EVP_MD_CTX_destroy (m_MDCtx);
|
||||||
EVP_PKEY_free (m_Pkey);
|
EVP_PKEY_free (m_Pkey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
|
if (m_Fallback) return m_Fallback->Sign (buf, len, signature);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t l = 64;
|
size_t l = 64;
|
||||||
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
|
||||||
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
|
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
|
||||||
memcpy (signature, sig, 64);
|
memcpy (signature, sig, 64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,9 +46,9 @@ namespace crypto
|
||||||
{
|
{
|
||||||
m_PublicKey = CreateDSA ();
|
m_PublicKey = CreateDSA ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPublicKey (const uint8_t * signingKey)
|
void SetPublicKey (const uint8_t * signingKey)
|
||||||
{
|
{
|
||||||
DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL);
|
DSA_set0_key (m_PublicKey, BN_bin2bn (signingKey, DSA_PUBLIC_KEY_LENGTH, NULL), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,9 +163,9 @@ namespace crypto
|
||||||
{
|
{
|
||||||
m_PublicKey = EC_KEY_new_by_curve_name (curve);
|
m_PublicKey = EC_KEY_new_by_curve_name (curve);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPublicKey (const uint8_t * signingKey)
|
void SetPublicKey (const uint8_t * signingKey)
|
||||||
{
|
{
|
||||||
BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL);
|
BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL);
|
||||||
BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL);
|
BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL);
|
||||||
EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y);
|
EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y);
|
||||||
|
@ -287,7 +287,7 @@ namespace crypto
|
||||||
EDDSA25519Verifier ();
|
EDDSA25519Verifier ();
|
||||||
void SetPublicKey (const uint8_t * signingKey);
|
void SetPublicKey (const uint8_t * signingKey);
|
||||||
~EDDSA25519Verifier ();
|
~EDDSA25519Verifier ();
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; };
|
size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; };
|
||||||
|
@ -298,10 +298,10 @@ namespace crypto
|
||||||
#if OPENSSL_EDDSA
|
#if OPENSSL_EDDSA
|
||||||
EVP_PKEY * m_Pkey;
|
EVP_PKEY * m_Pkey;
|
||||||
EVP_MD_CTX * m_MDCtx;
|
EVP_MD_CTX * m_MDCtx;
|
||||||
#else
|
#else
|
||||||
EDDSAPoint m_PublicKey;
|
EDDSAPoint m_PublicKey;
|
||||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
class EDDSA25519SignerCompat: public Signer
|
class EDDSA25519SignerCompat: public Signer
|
||||||
|
@ -311,17 +311,17 @@ namespace crypto
|
||||||
EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
||||||
// we pass signingPublicKey to check if it matches private key
|
// we pass signingPublicKey to check if it matches private key
|
||||||
~EDDSA25519SignerCompat ();
|
~EDDSA25519SignerCompat ();
|
||||||
|
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
||||||
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_ExpandedPrivateKey[64];
|
uint8_t m_ExpandedPrivateKey[64];
|
||||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if OPENSSL_EDDSA
|
#if OPENSSL_EDDSA
|
||||||
class EDDSA25519Signer: public Signer
|
class EDDSA25519Signer: public Signer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -329,23 +329,23 @@ namespace crypto
|
||||||
EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
|
||||||
// we pass signingPublicKey to check if it matches private key
|
// we pass signingPublicKey to check if it matches private key
|
||||||
~EDDSA25519Signer ();
|
~EDDSA25519Signer ();
|
||||||
|
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EVP_PKEY * m_Pkey;
|
EVP_PKEY * m_Pkey;
|
||||||
EVP_MD_CTX * m_MDCtx;
|
EVP_MD_CTX * m_MDCtx;
|
||||||
EDDSA25519SignerCompat * m_Fallback;
|
EDDSA25519SignerCompat * m_Fallback;
|
||||||
};
|
};
|
||||||
#else
|
#else
|
||||||
|
|
||||||
typedef EDDSA25519SignerCompat EDDSA25519Signer;
|
typedef EDDSA25519SignerCompat EDDSA25519Signer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
|
inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
|
||||||
{
|
{
|
||||||
#if OPENSSL_EDDSA
|
#if OPENSSL_EDDSA
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL);
|
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL);
|
||||||
EVP_PKEY_keygen_init (pctx);
|
EVP_PKEY_keygen_init (pctx);
|
||||||
|
@ -355,12 +355,12 @@ namespace crypto
|
||||||
EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len);
|
EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len);
|
||||||
len = EDDSA25519_PRIVATE_KEY_LENGTH;
|
len = EDDSA25519_PRIVATE_KEY_LENGTH;
|
||||||
EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len);
|
EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len);
|
||||||
EVP_PKEY_free (pkey);
|
EVP_PKEY_free (pkey);
|
||||||
#else
|
#else
|
||||||
RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH);
|
RAND_bytes (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH);
|
||||||
EDDSA25519Signer signer (signingPrivateKey);
|
EDDSA25519Signer signer (signingPrivateKey);
|
||||||
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -399,18 +399,18 @@ namespace crypto
|
||||||
GOSTR3410Verifier (GOSTR3410ParamSet paramSet):
|
GOSTR3410Verifier (GOSTR3410ParamSet paramSet):
|
||||||
m_ParamSet (paramSet), m_PublicKey (nullptr)
|
m_ParamSet (paramSet), m_PublicKey (nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPublicKey (const uint8_t * signingKey)
|
void SetPublicKey (const uint8_t * signingKey)
|
||||||
{
|
{
|
||||||
BIGNUM * x = BN_bin2bn (signingKey, GetPublicKeyLen ()/2, NULL);
|
BIGNUM * x = BN_bin2bn (signingKey, GetPublicKeyLen ()/2, NULL);
|
||||||
BIGNUM * y = BN_bin2bn (signingKey + GetPublicKeyLen ()/2, GetPublicKeyLen ()/2, NULL);
|
BIGNUM * y = BN_bin2bn (signingKey + GetPublicKeyLen ()/2, GetPublicKeyLen ()/2, NULL);
|
||||||
m_PublicKey = GetGOSTR3410Curve (m_ParamSet)->CreatePoint (x, y);
|
m_PublicKey = GetGOSTR3410Curve (m_ParamSet)->CreatePoint (x, y);
|
||||||
BN_free (x); BN_free (y);
|
BN_free (x); BN_free (y);
|
||||||
}
|
}
|
||||||
~GOSTR3410Verifier ()
|
~GOSTR3410Verifier ()
|
||||||
{
|
{
|
||||||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -501,18 +501,18 @@ namespace crypto
|
||||||
auto publicKey = GetEd25519 ()->GeneratePublicKey (m_PrivateKey, ctx);
|
auto publicKey = GetEd25519 ()->GeneratePublicKey (m_PrivateKey, ctx);
|
||||||
GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx);
|
GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx);
|
||||||
BN_CTX_free (ctx);
|
BN_CTX_free (ctx);
|
||||||
}
|
}
|
||||||
~RedDSA25519Signer () {};
|
~RedDSA25519Signer () {};
|
||||||
|
|
||||||
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH];
|
uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH];
|
||||||
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
};
|
};
|
||||||
|
@ -521,10 +521,9 @@ namespace crypto
|
||||||
{
|
{
|
||||||
GetEd25519 ()->CreateRedDSAPrivateKey (signingPrivateKey);
|
GetEd25519 ()->CreateRedDSAPrivateKey (signingPrivateKey);
|
||||||
RedDSA25519Signer signer (signingPrivateKey);
|
RedDSA25519Signer signer (signingPrivateKey);
|
||||||
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/**
|
/**
|
||||||
This code is licensed under the MCGSI Public License
|
* This code is licensed under the MCGSI Public License
|
||||||
Copyright 2018 Jeff Becker
|
* Copyright 2018 Jeff Becker
|
||||||
|
*
|
||||||
Kovri go write your own code
|
* Kovri go write your own code
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#ifndef SIPHASH_H
|
#ifndef SIPHASH_H
|
||||||
#define SIPHASH_H
|
#define SIPHASH_H
|
||||||
|
@ -14,140 +14,140 @@
|
||||||
#if !OPENSSL_SIPHASH
|
#if !OPENSSL_SIPHASH
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
namespace crypto
|
namespace crypto
|
||||||
{
|
{
|
||||||
namespace siphash
|
namespace siphash
|
||||||
{
|
{
|
||||||
constexpr int crounds = 2;
|
constexpr int crounds = 2;
|
||||||
constexpr int drounds = 4;
|
constexpr int drounds = 4;
|
||||||
|
|
||||||
inline uint64_t rotl(const uint64_t & x, int b)
|
inline uint64_t rotl(const uint64_t & x, int b)
|
||||||
{
|
{
|
||||||
uint64_t ret = x << b;
|
uint64_t ret = x << b;
|
||||||
ret |= x >> (64 - b);
|
ret |= x >> (64 - b);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void u32to8le(const uint32_t & v, uint8_t * p)
|
inline void u32to8le(const uint32_t & v, uint8_t * p)
|
||||||
{
|
{
|
||||||
p[0] = (uint8_t) v;
|
p[0] = (uint8_t) v;
|
||||||
p[1] = (uint8_t) (v >> 8);
|
p[1] = (uint8_t) (v >> 8);
|
||||||
p[2] = (uint8_t) (v >> 16);
|
p[2] = (uint8_t) (v >> 16);
|
||||||
p[3] = (uint8_t) (v >> 24);
|
p[3] = (uint8_t) (v >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void u64to8le(const uint64_t & v, uint8_t * p)
|
inline void u64to8le(const uint64_t & v, uint8_t * p)
|
||||||
{
|
{
|
||||||
p[0] = v & 0xff;
|
p[0] = v & 0xff;
|
||||||
p[1] = (v >> 8) & 0xff;
|
p[1] = (v >> 8) & 0xff;
|
||||||
p[2] = (v >> 16) & 0xff;
|
p[2] = (v >> 16) & 0xff;
|
||||||
p[3] = (v >> 24) & 0xff;
|
p[3] = (v >> 24) & 0xff;
|
||||||
p[4] = (v >> 32) & 0xff;
|
p[4] = (v >> 32) & 0xff;
|
||||||
p[5] = (v >> 40) & 0xff;
|
p[5] = (v >> 40) & 0xff;
|
||||||
p[6] = (v >> 48) & 0xff;
|
p[6] = (v >> 48) & 0xff;
|
||||||
p[7] = (v >> 56) & 0xff;
|
p[7] = (v >> 56) & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint64_t u8to64le(const uint8_t * p)
|
inline uint64_t u8to64le(const uint8_t * p)
|
||||||
{
|
{
|
||||||
uint64_t i = 0;
|
uint64_t i = 0;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
while(idx < 8)
|
while(idx < 8)
|
||||||
{
|
{
|
||||||
i |= ((uint64_t) p[idx]) << (idx * 8);
|
i |= ((uint64_t) p[idx]) << (idx * 8);
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
|
|
||||||
{
|
|
||||||
_v0 += _v1;
|
|
||||||
_v1 = rotl(_v1, 13);
|
|
||||||
_v1 ^= _v0;
|
|
||||||
_v0 = rotl(_v0, 32);
|
|
||||||
_v2 += _v3;
|
|
||||||
_v3 = rotl(_v3, 16);
|
|
||||||
_v3 ^= _v2;
|
|
||||||
_v0 += _v3;
|
|
||||||
_v3 = rotl(_v3, 21);
|
|
||||||
_v3 ^= _v0;
|
|
||||||
_v2 += _v1;
|
|
||||||
_v1 = rotl(_v1, 17);
|
|
||||||
_v1 ^= _v2;
|
|
||||||
_v2 = rotl(_v2, 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** hashsz must be 8 or 16 */
|
|
||||||
template<std::size_t hashsz>
|
|
||||||
inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
|
|
||||||
{
|
|
||||||
uint64_t v0 = 0x736f6d6570736575ULL;
|
|
||||||
uint64_t v1 = 0x646f72616e646f6dULL;
|
|
||||||
uint64_t v2 = 0x6c7967656e657261ULL;
|
|
||||||
uint64_t v3 = 0x7465646279746573ULL;
|
|
||||||
const uint64_t k0 = siphash::u8to64le(key);
|
|
||||||
const uint64_t k1 = siphash::u8to64le(key + 8);
|
|
||||||
uint64_t msg;
|
|
||||||
int i;
|
|
||||||
const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
|
|
||||||
auto left = bufsz & 7;
|
|
||||||
uint64_t b = ((uint64_t)bufsz) << 56;
|
|
||||||
v3 ^= k1;
|
|
||||||
v2 ^= k0;
|
|
||||||
v1 ^= k1;
|
|
||||||
v0 ^= k0;
|
|
||||||
|
|
||||||
if(hashsz == 16) v1 ^= 0xee;
|
inline void round(uint64_t & _v0, uint64_t & _v1, uint64_t & _v2, uint64_t & _v3)
|
||||||
|
{
|
||||||
|
_v0 += _v1;
|
||||||
|
_v1 = rotl(_v1, 13);
|
||||||
|
_v1 ^= _v0;
|
||||||
|
_v0 = rotl(_v0, 32);
|
||||||
|
_v2 += _v3;
|
||||||
|
_v3 = rotl(_v3, 16);
|
||||||
|
_v3 ^= _v2;
|
||||||
|
_v0 += _v3;
|
||||||
|
_v3 = rotl(_v3, 21);
|
||||||
|
_v3 ^= _v0;
|
||||||
|
_v2 += _v1;
|
||||||
|
_v1 = rotl(_v1, 17);
|
||||||
|
_v1 ^= _v2;
|
||||||
|
_v2 = rotl(_v2, 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while(buf != end)
|
/** hashsz must be 8 or 16 */
|
||||||
{
|
template<std::size_t hashsz>
|
||||||
msg = siphash::u8to64le(buf);
|
inline void Siphash(uint8_t * h, const uint8_t * buf, std::size_t bufsz, const uint8_t * key)
|
||||||
v3 ^= msg;
|
{
|
||||||
for(i = 0; i < siphash::crounds; ++i)
|
uint64_t v0 = 0x736f6d6570736575ULL;
|
||||||
siphash::round(v0, v1, v2, v3);
|
uint64_t v1 = 0x646f72616e646f6dULL;
|
||||||
|
uint64_t v2 = 0x6c7967656e657261ULL;
|
||||||
v0 ^= msg;
|
uint64_t v3 = 0x7465646279746573ULL;
|
||||||
buf += 8;
|
const uint64_t k0 = siphash::u8to64le(key);
|
||||||
}
|
const uint64_t k1 = siphash::u8to64le(key + 8);
|
||||||
|
uint64_t msg;
|
||||||
|
int i;
|
||||||
|
const uint8_t * end = buf + bufsz - (bufsz % sizeof(uint64_t));
|
||||||
|
auto left = bufsz & 7;
|
||||||
|
uint64_t b = ((uint64_t)bufsz) << 56;
|
||||||
|
v3 ^= k1;
|
||||||
|
v2 ^= k0;
|
||||||
|
v1 ^= k1;
|
||||||
|
v0 ^= k0;
|
||||||
|
|
||||||
while(left)
|
if(hashsz == 16) v1 ^= 0xee;
|
||||||
{
|
|
||||||
--left;
|
|
||||||
b |= ((uint64_t)(buf[left])) << (left * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
v3 ^= b;
|
while(buf != end)
|
||||||
|
{
|
||||||
|
msg = siphash::u8to64le(buf);
|
||||||
|
v3 ^= msg;
|
||||||
|
for(i = 0; i < siphash::crounds; ++i)
|
||||||
|
siphash::round(v0, v1, v2, v3);
|
||||||
|
|
||||||
for(i = 0; i < siphash::crounds; ++i)
|
v0 ^= msg;
|
||||||
siphash::round(v0, v1, v2, v3);
|
buf += 8;
|
||||||
|
}
|
||||||
|
|
||||||
v0 ^= b;
|
while(left)
|
||||||
|
{
|
||||||
|
--left;
|
||||||
|
b |= ((uint64_t)(buf[left])) << (left * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
v3 ^= b;
|
||||||
|
|
||||||
|
for(i = 0; i < siphash::crounds; ++i)
|
||||||
|
siphash::round(v0, v1, v2, v3);
|
||||||
|
|
||||||
|
v0 ^= b;
|
||||||
|
|
||||||
|
|
||||||
if(hashsz == 16)
|
if(hashsz == 16)
|
||||||
v2 ^= 0xee;
|
v2 ^= 0xee;
|
||||||
else
|
else
|
||||||
v2 ^= 0xff;
|
v2 ^= 0xff;
|
||||||
|
|
||||||
for(i = 0; i < siphash::drounds; ++i)
|
for(i = 0; i < siphash::drounds; ++i)
|
||||||
siphash::round(v0, v1, v2, v3);
|
siphash::round(v0, v1, v2, v3);
|
||||||
|
|
||||||
b = v0 ^ v1 ^ v2 ^ v3;
|
b = v0 ^ v1 ^ v2 ^ v3;
|
||||||
|
|
||||||
siphash::u64to8le(b, h);
|
siphash::u64to8le(b, h);
|
||||||
|
|
||||||
if(hashsz == 8) return;
|
if(hashsz == 8) return;
|
||||||
|
|
||||||
v1 ^= 0xdd;
|
v1 ^= 0xdd;
|
||||||
|
|
||||||
for (i = 0; i < siphash::drounds; ++i)
|
for (i = 0; i < siphash::drounds; ++i)
|
||||||
siphash::round(v0, v1, v2, v3);
|
siphash::round(v0, v1, v2, v3);
|
||||||
|
|
||||||
b = v0 ^ v1 ^ v2 ^ v3;
|
b = v0 ^ v1 ^ v2 ^ v3;
|
||||||
siphash::u64to8le(b, h + 8);
|
siphash::u64to8le(b, h + 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace stream
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// partially
|
// partially
|
||||||
rem = len - offset;
|
rem = len - offset;
|
||||||
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset);
|
memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset);
|
||||||
nextBuffer->offset += (len - offset);
|
nextBuffer->offset += (len - offset);
|
||||||
offset = len; // break
|
offset = len; // break
|
||||||
|
@ -60,7 +60,7 @@ namespace stream
|
||||||
m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
|
m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
|
||||||
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
||||||
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_ResendTimer (m_Service),
|
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_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_WindowSize (MIN_WINDOW_SIZE), m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO),
|
||||||
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
||||||
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
||||||
|
@ -73,7 +73,7 @@ namespace stream
|
||||||
m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
|
m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1),
|
||||||
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
m_Status (eStreamStatusNew), m_IsAckSendScheduled (false), m_LocalDestination (local),
|
||||||
m_ReceiveTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
|
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_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_WindowSize (MIN_WINDOW_SIZE),
|
||||||
m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
m_RTT (INITIAL_RTT), m_RTO (INITIAL_RTO), m_AckDelay (local.GetOwner ()->GetStreamingAckDelay ()),
|
||||||
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
m_LastWindowSizeIncreaseTime (0), m_NumResendAttempts (0), m_MTU (STREAMING_MTU)
|
||||||
{
|
{
|
||||||
|
@ -228,7 +228,7 @@ namespace stream
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->offset = packet->GetPayload () - packet->buf;
|
packet->offset = packet->GetPayload () - packet->buf;
|
||||||
if (packet->GetLength () > 0)
|
if (packet->GetLength () > 0)
|
||||||
{
|
{
|
||||||
|
@ -258,7 +258,7 @@ namespace stream
|
||||||
bool Stream::ProcessOptions (uint16_t flags, Packet * packet)
|
bool Stream::ProcessOptions (uint16_t flags, Packet * packet)
|
||||||
{
|
{
|
||||||
const uint8_t * optionData = packet->GetOptionData ();
|
const uint8_t * optionData = packet->GetOptionData ();
|
||||||
size_t optionSize = packet->GetOptionSize ();
|
size_t optionSize = packet->GetOptionSize ();
|
||||||
if (flags & PACKET_FLAG_DELAY_REQUESTED)
|
if (flags & PACKET_FLAG_DELAY_REQUESTED)
|
||||||
optionData += 2;
|
optionData += 2;
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ namespace stream
|
||||||
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize);
|
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize);
|
||||||
if (m_RemoteIdentity->IsRSA ())
|
if (m_RemoteIdentity->IsRSA ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded");
|
LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
optionData += m_RemoteIdentity->GetFullLen ();
|
optionData += m_RemoteIdentity->GetFullLen ();
|
||||||
|
@ -306,11 +306,11 @@ namespace stream
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset);
|
m_TransientVerifier = i2p::data::ProcessOfflineSignature (m_RemoteIdentity, optionData, optionSize - (optionData - packet->GetOptionData ()), offset);
|
||||||
optionData += offset;
|
optionData += offset;
|
||||||
if (!m_TransientVerifier)
|
if (!m_TransientVerifier)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Streaming: offline signature failed");
|
LogPrint (eLogError, "Streaming: offline signature failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +322,7 @@ namespace stream
|
||||||
{
|
{
|
||||||
memcpy (signature, optionData, signatureLen);
|
memcpy (signature, optionData, signatureLen);
|
||||||
memset (const_cast<uint8_t *>(optionData), 0, signatureLen);
|
memset (const_cast<uint8_t *>(optionData), 0, signatureLen);
|
||||||
bool verified = m_TransientVerifier ?
|
bool verified = m_TransientVerifier ?
|
||||||
m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) :
|
m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) :
|
||||||
m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature);
|
m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature);
|
||||||
if (!verified)
|
if (!verified)
|
||||||
|
@ -340,7 +340,7 @@ namespace stream
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::ProcessAck (Packet * packet)
|
void Stream::ProcessAck (Packet * packet)
|
||||||
|
@ -435,7 +435,7 @@ namespace stream
|
||||||
m_SendBuffer.Add (buf, len, handler);
|
m_SendBuffer.Add (buf, len, handler);
|
||||||
}
|
}
|
||||||
else if (handler)
|
else if (handler)
|
||||||
handler(boost::system::error_code ());
|
handler(boost::system::error_code ());
|
||||||
m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
|
m_Service.post (std::bind (&Stream::SendBuffer, shared_from_this ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,14 +471,14 @@ namespace stream
|
||||||
size++; // resend delay
|
size++; // resend delay
|
||||||
if (m_Status == eStreamStatusNew)
|
if (m_Status == eStreamStatusNew)
|
||||||
{
|
{
|
||||||
// initial packet
|
// initial packet
|
||||||
m_Status = eStreamStatusOpen;
|
m_Status = eStreamStatusOpen;
|
||||||
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
|
if (!m_RemoteLeaseSet) m_RemoteLeaseSet = m_LocalDestination.GetOwner ()->FindLeaseSet (m_RemoteIdentity->GetIdentHash ());;
|
||||||
if (m_RemoteLeaseSet)
|
if (m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
|
m_RoutingSession = m_LocalDestination.GetOwner ()->GetRoutingSession (m_RemoteLeaseSet, true);
|
||||||
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
|
m_MTU = m_RoutingSession->IsRatchets () ? STREAMING_MTU_RATCHETS : STREAMING_MTU;
|
||||||
}
|
}
|
||||||
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
|
uint16_t flags = PACKET_FLAG_SYNCHRONIZE | PACKET_FLAG_FROM_INCLUDED |
|
||||||
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
|
PACKET_FLAG_SIGNATURE_INCLUDED | PACKET_FLAG_MAX_PACKET_SIZE_INCLUDED;
|
||||||
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
if (isNoAck) flags |= PACKET_FLAG_NO_ACK;
|
||||||
|
@ -488,7 +488,7 @@ namespace stream
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
|
size_t identityLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetFullLen ();
|
||||||
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
|
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
|
||||||
uint8_t * optionsSize = packet + size; // set options size later
|
uint8_t * optionsSize = packet + size; // set options size later
|
||||||
size += 2; // options size
|
size += 2; // options size
|
||||||
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
|
m_LocalDestination.GetOwner ()->GetIdentity ()->ToBuffer (packet + size, identityLen);
|
||||||
size += identityLen; // from
|
size += identityLen; // from
|
||||||
|
@ -654,7 +654,7 @@ namespace stream
|
||||||
size += 4; // receiveStreamID
|
size += 4; // receiveStreamID
|
||||||
htobe32buf (packet + size, m_SequenceNumber++);
|
htobe32buf (packet + size, m_SequenceNumber++);
|
||||||
size += 4; // sequenceNum
|
size += 4; // sequenceNum
|
||||||
htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
|
htobe32buf (packet + size, m_LastReceivedSequenceNumber >= 0 ? m_LastReceivedSequenceNumber : 0);
|
||||||
size += 4; // ack Through
|
size += 4; // ack Through
|
||||||
packet[size] = 0;
|
packet[size] = 0;
|
||||||
size++; // NACK count
|
size++; // NACK count
|
||||||
|
@ -748,7 +748,7 @@ namespace stream
|
||||||
|
|
||||||
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet
|
if (!m_CurrentRemoteLease || !m_CurrentRemoteLease->endDate || // excluded from LeaseSet
|
||||||
ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD)
|
ts >= m_CurrentRemoteLease->endDate - i2p::data::LEASE_ENDDATE_THRESHOLD)
|
||||||
UpdateCurrentRemoteLease (true);
|
UpdateCurrentRemoteLease (true);
|
||||||
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD)
|
if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD)
|
||||||
{
|
{
|
||||||
|
@ -785,7 +785,7 @@ namespace stream
|
||||||
if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT)
|
if (ts > m_RoutingSession->GetLeaseSetSubmissionTime () + i2p::garlic::LEASET_CONFIRMATION_TIMEOUT)
|
||||||
{
|
{
|
||||||
// LeaseSet was not confirmed, should try other tunnels
|
// LeaseSet was not confirmed, should try other tunnels
|
||||||
LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit");
|
LogPrint (eLogWarning, "Streaming: LeaseSet was not confirmed in ", i2p::garlic::LEASET_CONFIRMATION_TIMEOUT, " milliseconds. Trying to resubmit");
|
||||||
m_RoutingSession->SetSharedRoutingPath (nullptr);
|
m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||||
m_CurrentOutboundTunnel = nullptr;
|
m_CurrentOutboundTunnel = nullptr;
|
||||||
m_CurrentRemoteLease = nullptr;
|
m_CurrentRemoteLease = nullptr;
|
||||||
|
@ -848,9 +848,9 @@ namespace stream
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time
|
m_RTO = INITIAL_RTO; // drop RTO to initial upon tunnels pair change first time
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
// no break here
|
// no break here
|
||||||
case 4:
|
case 4:
|
||||||
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
if (m_RoutingSession) m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||||
|
@ -911,7 +911,7 @@ namespace stream
|
||||||
// LeaseSet updated
|
// LeaseSet updated
|
||||||
m_RemoteIdentity = m_RemoteLeaseSet->GetIdentity ();
|
m_RemoteIdentity = m_RemoteLeaseSet->GetIdentity ();
|
||||||
m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier ();
|
m_TransientVerifier = m_RemoteLeaseSet->GetTransientVerifier ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_RemoteLeaseSet)
|
if (m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
|
@ -926,7 +926,7 @@ namespace stream
|
||||||
m_LocalDestination.GetOwner ()->RequestDestinationWithEncryptedLeaseSet (
|
m_LocalDestination.GetOwner ()->RequestDestinationWithEncryptedLeaseSet (
|
||||||
std::make_shared<i2p::data::BlindedPublicKey>(m_RemoteIdentity));
|
std::make_shared<i2p::data::BlindedPublicKey>(m_RemoteIdentity));
|
||||||
else
|
else
|
||||||
m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ());
|
m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ());
|
||||||
leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // then with threshold
|
leases = m_RemoteLeaseSet->GetNonExpiredLeases (true); // then with threshold
|
||||||
}
|
}
|
||||||
if (!leases.empty ())
|
if (!leases.empty ())
|
||||||
|
@ -994,7 +994,7 @@ namespace stream
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
std::unique_lock<std::mutex> l(m_StreamsMutex);
|
||||||
for (auto it: m_Streams)
|
for (auto it: m_Streams)
|
||||||
it.second->Terminate (false); // we delete here
|
it.second->Terminate (false); // we delete here
|
||||||
m_Streams.clear ();
|
m_Streams.clear ();
|
||||||
m_IncomingStreams.clear ();
|
m_IncomingStreams.clear ();
|
||||||
}
|
}
|
||||||
|
@ -1136,8 +1136,8 @@ namespace stream
|
||||||
return false;
|
return false;
|
||||||
DeleteStream (it->second);
|
DeleteStream (it->second);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamingDestination::SetAcceptor (const Acceptor& acceptor)
|
void StreamingDestination::SetAcceptor (const Acceptor& acceptor)
|
||||||
{
|
{
|
||||||
m_Acceptor = acceptor; // we must set it immediately for IsAcceptorSet
|
m_Acceptor = acceptor; // we must set it immediately for IsAcceptorSet
|
||||||
|
@ -1164,7 +1164,7 @@ namespace stream
|
||||||
m_Owner->GetService ().post([acceptor, this](void)
|
m_Owner->GetService ().post([acceptor, this](void)
|
||||||
{
|
{
|
||||||
if (!m_PendingIncomingStreams.empty ())
|
if (!m_PendingIncomingStreams.empty ())
|
||||||
{
|
{
|
||||||
acceptor (m_PendingIncomingStreams.front ());
|
acceptor (m_PendingIncomingStreams.front ());
|
||||||
m_PendingIncomingStreams.pop_front ();
|
m_PendingIncomingStreams.pop_front ();
|
||||||
if (m_PendingIncomingStreams.empty ())
|
if (m_PendingIncomingStreams.empty ())
|
||||||
|
|
142
libi2pd/Tag.h
142
libi2pd/Tag.h
|
@ -16,93 +16,91 @@
|
||||||
|
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace data {
|
namespace data {
|
||||||
|
template<size_t sz>
|
||||||
template<size_t sz>
|
class Tag
|
||||||
class Tag
|
|
||||||
{
|
|
||||||
BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Tag () = default;
|
|
||||||
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
|
|
||||||
|
|
||||||
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
|
|
||||||
bool operator!= (const Tag& other) const { return !(*this == other); }
|
|
||||||
bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
|
|
||||||
|
|
||||||
uint8_t * operator()() { return m_Buf; }
|
|
||||||
const uint8_t * operator()() const { return m_Buf; }
|
|
||||||
|
|
||||||
operator uint8_t * () { return m_Buf; }
|
|
||||||
operator const uint8_t * () const { return m_Buf; }
|
|
||||||
|
|
||||||
const uint8_t * data() const { return m_Buf; }
|
|
||||||
const uint64_t * GetLL () const { return ll; }
|
|
||||||
|
|
||||||
bool IsZero () const
|
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < sz/8; ++i)
|
BOOST_STATIC_ASSERT_MSG(sz % 8 == 0, "Tag size must be multiple of 8 bytes");
|
||||||
if (ll[i]) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fill(uint8_t c)
|
public:
|
||||||
{
|
|
||||||
memset(m_Buf, c, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Randomize()
|
Tag () = default;
|
||||||
{
|
Tag (const uint8_t * buf) { memcpy (m_Buf, buf, sz); }
|
||||||
RAND_bytes(m_Buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToBase64 () const
|
bool operator== (const Tag& other) const { return !memcmp (m_Buf, other.m_Buf, sz); }
|
||||||
{
|
bool operator!= (const Tag& other) const { return !(*this == other); }
|
||||||
char str[sz*2];
|
bool operator< (const Tag& other) const { return memcmp (m_Buf, other.m_Buf, sz) < 0; }
|
||||||
size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
|
|
||||||
return std::string (str, str + l);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ToBase32 () const
|
uint8_t * operator()() { return m_Buf; }
|
||||||
{
|
const uint8_t * operator()() const { return m_Buf; }
|
||||||
char str[sz*2];
|
|
||||||
size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
|
|
||||||
return std::string (str, str + l);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FromBase32 (const std::string& s)
|
operator uint8_t * () { return m_Buf; }
|
||||||
{
|
operator const uint8_t * () const { return m_Buf; }
|
||||||
return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t FromBase64 (const std::string& s)
|
const uint8_t * data() const { return m_Buf; }
|
||||||
{
|
const uint64_t * GetLL () const { return ll; }
|
||||||
return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
bool IsZero () const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < sz/8; ++i)
|
||||||
|
if (ll[i]) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
union // 8 bytes aligned
|
void Fill(uint8_t c)
|
||||||
{
|
{
|
||||||
uint8_t m_Buf[sz];
|
memset(m_Buf, c, sz);
|
||||||
uint64_t ll[sz/8];
|
}
|
||||||
|
|
||||||
|
void Randomize()
|
||||||
|
{
|
||||||
|
RAND_bytes(m_Buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToBase64 () const
|
||||||
|
{
|
||||||
|
char str[sz*2];
|
||||||
|
size_t l = i2p::data::ByteStreamToBase64 (m_Buf, sz, str, sz*2);
|
||||||
|
return std::string (str, str + l);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ToBase32 () const
|
||||||
|
{
|
||||||
|
char str[sz*2];
|
||||||
|
size_t l = i2p::data::ByteStreamToBase32 (m_Buf, sz, str, sz*2);
|
||||||
|
return std::string (str, str + l);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FromBase32 (const std::string& s)
|
||||||
|
{
|
||||||
|
return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FromBase64 (const std::string& s)
|
||||||
|
{
|
||||||
|
return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
union // 8 bytes aligned
|
||||||
|
{
|
||||||
|
uint8_t m_Buf[sz];
|
||||||
|
uint64_t ll[sz/8];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
} // data
|
} // data
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
// hash for std::unordered_map
|
// hash for std::unordered_map
|
||||||
template<size_t sz> struct hash<i2p::data::Tag<sz> >
|
template<size_t sz> struct hash<i2p::data::Tag<sz> >
|
||||||
{
|
{
|
||||||
size_t operator()(const i2p::data::Tag<sz>& s) const
|
size_t operator()(const i2p::data::Tag<sz>& s) const
|
||||||
{
|
{
|
||||||
return s.GetLL ()[0];
|
return s.GetLL ()[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* TAG_H__ */
|
#endif /* TAG_H__ */
|
||||||
|
|
|
@ -24,26 +24,26 @@ namespace util
|
||||||
static uint64_t GetLocalMillisecondsSinceEpoch ()
|
static uint64_t GetLocalMillisecondsSinceEpoch ()
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
return std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
std::chrono::system_clock::now().time_since_epoch()).count ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t GetLocalHoursSinceEpoch ()
|
static uint32_t GetLocalHoursSinceEpoch ()
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::hours>(
|
return std::chrono::duration_cast<std::chrono::hours>(
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count ();
|
std::chrono::system_clock::now().time_since_epoch()).count ();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t GetLocalSecondsSinceEpoch ()
|
static uint64_t GetLocalSecondsSinceEpoch ()
|
||||||
{
|
{
|
||||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
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)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Timestamp: NTP request to ", address);
|
LogPrint (eLogInfo, "Timestamp: NTP request to ", address);
|
||||||
boost::asio::io_service service;
|
boost::asio::io_service service;
|
||||||
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
|
boost::asio::ip::udp::resolver::query query (boost::asio::ip::udp::v4 (), address, "ntp");
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
@ -148,11 +148,11 @@ namespace util
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPTimeSync::Sync ()
|
void NTPTimeSync::Sync ()
|
||||||
{
|
{
|
||||||
if (m_NTPServersList.size () > 0)
|
if (m_NTPServersList.size () > 0)
|
||||||
SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]);
|
SyncTimeWithNTP (m_NTPServersList[rand () % m_NTPServersList.size ()]);
|
||||||
else
|
else
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
|
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
{
|
{
|
||||||
|
@ -200,4 +200,3 @@ namespace util
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,8 +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
|
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
|
||||||
void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
|
void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
|
||||||
|
|
||||||
class NTPTimeSync
|
class NTPTimeSync
|
||||||
{
|
{
|
||||||
|
@ -26,17 +26,17 @@ namespace util
|
||||||
~NTPTimeSync ();
|
~NTPTimeSync ();
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
void Sync ();
|
void Sync ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
boost::asio::deadline_timer m_Timer;
|
boost::asio::deadline_timer m_Timer;
|
||||||
int m_SyncInterval;
|
int m_SyncInterval;
|
||||||
|
@ -46,4 +46,3 @@ namespace util
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace i2p
|
||||||
namespace tunnel
|
namespace tunnel
|
||||||
{
|
{
|
||||||
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
|
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID,
|
||||||
const uint8_t * nextIdent, uint32_t nextTunnelID,
|
const uint8_t * nextIdent, uint32_t nextTunnelID,
|
||||||
const uint8_t * layerKey,const uint8_t * ivKey):
|
const uint8_t * layerKey,const uint8_t * ivKey):
|
||||||
TunnelBase (receiveTunnelID, nextTunnelID, nextIdent)
|
TunnelBase (receiveTunnelID, nextTunnelID, nextIdent)
|
||||||
{
|
{
|
||||||
|
@ -88,7 +88,7 @@ namespace tunnel
|
||||||
|
|
||||||
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
|
std::shared_ptr<TransitTunnel> CreateTransitTunnel (uint32_t receiveTunnelID,
|
||||||
const uint8_t * nextIdent, uint32_t nextTunnelID,
|
const uint8_t * nextIdent, uint32_t nextTunnelID,
|
||||||
const uint8_t * layerKey,const uint8_t * ivKey,
|
const uint8_t * layerKey,const uint8_t * ivKey,
|
||||||
bool isGateway, bool isEndpoint)
|
bool isGateway, bool isEndpoint)
|
||||||
{
|
{
|
||||||
if (isEndpoint)
|
if (isEndpoint)
|
||||||
|
|
|
@ -68,15 +68,15 @@ namespace transport
|
||||||
|
|
||||||
std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }
|
std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; }
|
||||||
|
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity ()
|
std::shared_ptr<const i2p::data::IdentityEx> GetRemoteIdentity ()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
||||||
return m_RemoteIdentity;
|
return m_RemoteIdentity;
|
||||||
}
|
}
|
||||||
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident)
|
void SetRemoteIdentity (std::shared_ptr<const i2p::data::IdentityEx> ident)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
std::lock_guard<std::mutex> l(m_RemoteIdentityMutex);
|
||||||
m_RemoteIdentity = ident;
|
m_RemoteIdentity = ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
size_t GetNumSentBytes () const { return m_NumSentBytes; };
|
||||||
|
|
|
@ -220,10 +220,10 @@ namespace transport
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_NTCP2Server = new NTCP2Server ();
|
m_NTCP2Server = new NTCP2Server ();
|
||||||
m_NTCP2Server->Start ();
|
m_NTCP2Server->Start ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create acceptors
|
// create acceptors
|
||||||
|
@ -390,7 +390,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
auto r = netdb.FindRouter (ident);
|
auto r = netdb.FindRouter (ident);
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
|
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
|
||||||
i2p::util::GetSecondsSinceEpoch (), {} })).first;
|
i2p::util::GetSecondsSinceEpoch (), {} })).first;
|
||||||
}
|
}
|
||||||
|
@ -553,13 +553,13 @@ namespace transport
|
||||||
{
|
{
|
||||||
auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4
|
auto router = i2p::data::netdb.GetRandomPeerTestRouter (isv4); // v4 only if v4
|
||||||
if (router)
|
if (router)
|
||||||
m_SSUServer->CreateSession (router, true, isv4); // peer test
|
m_SSUServer->CreateSession (router, true, isv4); // peer test
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if not peer test capable routers found pick any
|
// if not peer test capable routers found pick any
|
||||||
router = i2p::data::netdb.GetRandomRouter ();
|
router = i2p::data::netdb.GetRandomRouter ();
|
||||||
if (router && router->IsSSU ())
|
if (router && router->IsSSU ())
|
||||||
m_SSUServer->CreateSession (router); // no peer test
|
m_SSUServer->CreateSession (router); // no peer test
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i2p::context.SupportsV6 ())
|
if (i2p::context.SupportsV6 ())
|
||||||
|
@ -574,7 +574,7 @@ namespace transport
|
||||||
if (addr)
|
if (addr)
|
||||||
m_SSUServer->GetServiceV6 ().post ([this, router, addr]
|
m_SSUServer->GetServiceV6 ().post ([this, router, addr]
|
||||||
{
|
{
|
||||||
m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false);
|
m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,7 +713,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
profile->TunnelNonReplied();
|
profile->TunnelNonReplied();
|
||||||
}
|
}
|
||||||
std::unique_lock<std::mutex> l(m_PeersMutex);
|
std::unique_lock<std::mutex> l(m_PeersMutex);
|
||||||
it = m_Peers.erase (it);
|
it = m_Peers.erase (it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -103,7 +103,7 @@ namespace transport
|
||||||
uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; };
|
uint64_t GetTotalReceivedBytes () const { return m_TotalReceivedBytes; };
|
||||||
uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; }
|
uint64_t GetTotalTransitTransmittedBytes () const { return m_TotalTransitTransmittedBytes; }
|
||||||
void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; };
|
void UpdateTotalTransitTransmittedBytes (uint32_t add) { m_TotalTransitTransmittedBytes += add; };
|
||||||
uint32_t GetInBandwidth () const { return m_InBandwidth; };
|
uint32_t GetInBandwidth () const { return m_InBandwidth; };
|
||||||
uint32_t GetOutBandwidth () const { return m_OutBandwidth; };
|
uint32_t GetOutBandwidth () const { return m_OutBandwidth; };
|
||||||
uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; };
|
uint32_t GetTransitBandwidth () const { return m_TransitBandwidth; };
|
||||||
bool IsBandwidthExceeded () const;
|
bool IsBandwidthExceeded () const;
|
||||||
|
@ -111,16 +111,16 @@ namespace transport
|
||||||
size_t GetNumPeers () const { return m_Peers.size (); };
|
size_t GetNumPeers () const { return m_Peers.size (); };
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const;
|
std::shared_ptr<const i2p::data::RouterInfo> GetRandomPeer () const;
|
||||||
|
|
||||||
/** get a trusted first hop for restricted routes */
|
/** get a trusted first hop for restricted routes */
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
|
std::shared_ptr<const i2p::data::RouterInfo> GetRestrictedPeer() const;
|
||||||
/** do we want to use restricted routes? */
|
/** do we want to use restricted routes? */
|
||||||
bool RoutesRestricted() const;
|
bool RoutesRestricted() const;
|
||||||
/** restrict routes to use only these router families for first hops */
|
/** restrict routes to use only these router families for first hops */
|
||||||
void RestrictRoutesToFamilies(std::set<std::string> families);
|
void RestrictRoutesToFamilies(std::set<std::string> families);
|
||||||
/** restrict routes to use only these routers for first hops */
|
/** restrict routes to use only these routers for first hops */
|
||||||
void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
|
void RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers);
|
||||||
|
|
||||||
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
|
bool IsRestrictedPeer(const i2p::data::IdentHash & ident) const;
|
||||||
|
|
||||||
void PeerTest ();
|
void PeerTest ();
|
||||||
|
|
||||||
|
|
|
@ -64,8 +64,7 @@ namespace tunnel
|
||||||
m.hash = i2p::data::IdentHash (fragment);
|
m.hash = i2p::data::IdentHash (fragment);
|
||||||
fragment += 32; // to hash
|
fragment += 32; // to hash
|
||||||
break;
|
break;
|
||||||
default:
|
default: ;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFragmented = flag & 0x08;
|
bool isFragmented = flag & 0x08;
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace tunnel
|
||||||
// create fragments
|
// create fragments
|
||||||
const std::shared_ptr<I2NPMessage> & msg = block.data;
|
const std::shared_ptr<I2NPMessage> & msg = block.data;
|
||||||
size_t fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
size_t fullMsgLen = diLen + msg->GetLength () + 2; // delivery instructions + payload + 2 bytes length
|
||||||
|
|
||||||
if (!messageCreated && fullMsgLen > m_RemainingSize) // check if we should complete previous message
|
if (!messageCreated && fullMsgLen > m_RemainingSize) // check if we should complete previous message
|
||||||
{
|
{
|
||||||
size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE;
|
||||||
|
@ -172,7 +172,7 @@ namespace tunnel
|
||||||
SHA256(payload, size+16, hash);
|
SHA256(payload, size+16, hash);
|
||||||
memcpy (buf+20, hash, 4); // checksum
|
memcpy (buf+20, hash, 4); // checksum
|
||||||
payload[-1] = 0; // zero
|
payload[-1] = 0; // zero
|
||||||
ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1
|
ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1
|
||||||
if (paddingSize > 0)
|
if (paddingSize > 0)
|
||||||
{
|
{
|
||||||
// non-zero padding
|
// non-zero padding
|
||||||
|
@ -219,4 +219,3 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace tunnel
|
namespace tunnel
|
||||||
{
|
{
|
||||||
|
|
||||||
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
|
TunnelPool::TunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels):
|
||||||
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
|
m_NumInboundHops (numInboundHops), m_NumOutboundHops (numOutboundHops),
|
||||||
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true),
|
m_NumInboundTunnels (numInboundTunnels), m_NumOutboundTunnels (numOutboundTunnels), m_IsActive (true),
|
||||||
|
@ -67,7 +66,8 @@ namespace tunnel
|
||||||
m_Tests.clear ();
|
m_Tests.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) {
|
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant)
|
||||||
|
{
|
||||||
if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
|
if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
|
||||||
{
|
{
|
||||||
m_NumInboundHops = inHops;
|
m_NumInboundHops = inHops;
|
||||||
|
@ -78,7 +78,7 @@ namespace tunnel
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel)
|
void TunnelPool::TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel)
|
||||||
{
|
{
|
||||||
if (!m_IsActive) return;
|
if (!m_IsActive) return;
|
||||||
|
@ -180,8 +180,8 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
if (it->IsEstablished () && it != excluded)
|
if (it->IsEstablished () && it != excluded)
|
||||||
{
|
{
|
||||||
tunnel = it;
|
tunnel = it;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i > ind && tunnel) break;
|
if (i > ind && tunnel) break;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ namespace tunnel
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
|
std::lock_guard<std::mutex> lock(m_CustomPeerSelectorMutex);
|
||||||
if (m_CustomPeerSelector)
|
if (m_CustomPeerSelector)
|
||||||
return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
|
return m_CustomPeerSelector->SelectPeers(peers, numHops, isInbound);
|
||||||
}
|
}
|
||||||
// explicit peers in use
|
// explicit peers in use
|
||||||
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
if (m_ExplicitPeers) return SelectExplicitPeers (peers, isInbound);
|
||||||
|
|
|
@ -75,23 +75,23 @@ namespace tunnel
|
||||||
|
|
||||||
/** i2cp reconfigure */
|
/** i2cp reconfigure */
|
||||||
bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant);
|
bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant);
|
||||||
|
|
||||||
void SetCustomPeerSelector(ITunnelPeerSelector * selector);
|
void SetCustomPeerSelector(ITunnelPeerSelector * selector);
|
||||||
void UnsetCustomPeerSelector();
|
void UnsetCustomPeerSelector();
|
||||||
bool HasCustomPeerSelector();
|
bool HasCustomPeerSelector();
|
||||||
|
|
||||||
/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
|
/** @brief make this tunnel pool yield tunnels that fit latency range [min, max] */
|
||||||
void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
|
void RequireLatency(uint64_t min, uint64_t max) { m_MinLatency = min; m_MaxLatency = max; }
|
||||||
|
|
||||||
/** @brief return true if this tunnel pool has a latency requirement */
|
/** @brief return true if this tunnel pool has a latency requirement */
|
||||||
bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
|
bool HasLatencyRequirement() const { return m_MinLatency > 0 && m_MaxLatency > 0; }
|
||||||
|
|
||||||
/** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */
|
/** @brief get the lowest latency tunnel in this tunnel pool regardless of latency requirements */
|
||||||
std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude=nullptr) const;
|
std::shared_ptr<InboundTunnel> GetLowestLatencyInboundTunnel(std::shared_ptr<InboundTunnel> exclude = nullptr) const;
|
||||||
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude=nullptr) const;
|
std::shared_ptr<OutboundTunnel> GetLowestLatencyOutboundTunnel(std::shared_ptr<OutboundTunnel> exclude = nullptr) const;
|
||||||
|
|
||||||
// for overriding tunnel peer selection
|
// for overriding tunnel peer selection
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
std::shared_ptr<const i2p::data::RouterInfo> SelectNextHop (std::shared_ptr<const i2p::data::RouterInfo> prevHop) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -118,8 +118,8 @@ namespace tunnel
|
||||||
std::mutex m_CustomPeerSelectorMutex;
|
std::mutex m_CustomPeerSelectorMutex;
|
||||||
ITunnelPeerSelector * m_CustomPeerSelector;
|
ITunnelPeerSelector * m_CustomPeerSelector;
|
||||||
|
|
||||||
uint64_t m_MinLatency=0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
|
uint64_t m_MinLatency = 0; // if > 0 this tunnel pool will try building tunnels with minimum latency by ms
|
||||||
uint64_t m_MaxLatency=0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
|
uint64_t m_MaxLatency = 0; // if > 0 this tunnel pool will try building tunnels with maximum latency by ms
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ namespace api
|
||||||
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
||||||
i2p::crypto::InitCrypto (precomputation);
|
i2p::crypto::InitCrypto (precomputation);
|
||||||
|
|
||||||
int netID; i2p::config::GetOption("netid", netID);
|
int netID; i2p::config::GetOption("netid", netID);
|
||||||
i2p::context.SetNetID (netID);
|
i2p::context.SetNetID (netID);
|
||||||
|
|
||||||
i2p::context.Init ();
|
i2p::context.Init ();
|
||||||
}
|
}
|
||||||
|
@ -133,4 +133,3 @@ namespace api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,4 +35,3 @@ namespace api
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -64,9 +64,9 @@ namespace util
|
||||||
{
|
{
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
m_Thread.reset (new std::thread (std::bind (& RunnableService::Run, this)));
|
m_Thread.reset (new std::thread (std::bind (& RunnableService::Run, this)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnableService::StopIOService ()
|
void RunnableService::StopIOService ()
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
|
@ -79,7 +79,7 @@ namespace util
|
||||||
m_Thread = nullptr;
|
m_Thread = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunnableService::Run ()
|
void RunnableService::Run ()
|
||||||
{
|
{
|
||||||
|
@ -94,28 +94,28 @@ namespace util
|
||||||
LogPrint (eLogError, m_Name, ": runtime exception: ", ex.what ());
|
LogPrint (eLogError, m_Name, ": runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace net
|
namespace net
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
bool IsWindowsXPorLater()
|
bool IsWindowsXPorLater()
|
||||||
{
|
{
|
||||||
static bool isRequested = false;
|
static bool isRequested = false;
|
||||||
static bool isXP = false;
|
static bool isXP = false;
|
||||||
if (!isRequested)
|
if (!isRequested)
|
||||||
{
|
{
|
||||||
// request
|
// request
|
||||||
OSVERSIONINFO osvi;
|
OSVERSIONINFO osvi;
|
||||||
|
|
||||||
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
||||||
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||||
GetVersionEx(&osvi);
|
GetVersionEx(&osvi);
|
||||||
|
|
||||||
isXP = osvi.dwMajorVersion <= 5;
|
isXP = osvi.dwMajorVersion <= 5;
|
||||||
isRequested = true;
|
isRequested = true;
|
||||||
}
|
}
|
||||||
return isXP;
|
return isXP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
|
int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
|
||||||
|
@ -246,22 +246,24 @@ namespace net
|
||||||
std::string localAddressUniversal = localAddress.to_string();
|
std::string localAddressUniversal = localAddress.to_string();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef int (* IPN)(int af, const char *src, void *dst);
|
typedef int (* IPN)(int af, const char *src, void *dst);
|
||||||
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
|
IPN inetpton = (IPN)GetProcAddress (GetModuleHandle ("ws2_32.dll"), "InetPton");
|
||||||
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
|
if (!inetpton) inetpton = inet_pton_xp; // use own implementation if not found
|
||||||
|
|
||||||
if(localAddress.is_v4())
|
if(localAddress.is_v4())
|
||||||
{
|
{
|
||||||
sockaddr_in inputAddress;
|
sockaddr_in inputAddress;
|
||||||
inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
|
inetpton(AF_INET, localAddressUniversal.c_str(), &(inputAddress.sin_addr));
|
||||||
return GetMTUWindowsIpv4(inputAddress, fallback);
|
return GetMTUWindowsIpv4(inputAddress, fallback);
|
||||||
}
|
}
|
||||||
else if(localAddress.is_v6())
|
else if(localAddress.is_v6())
|
||||||
{
|
{
|
||||||
sockaddr_in6 inputAddress;
|
sockaddr_in6 inputAddress;
|
||||||
inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
|
inetpton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr));
|
||||||
return GetMTUWindowsIpv6(inputAddress, fallback);
|
return GetMTUWindowsIpv6(inputAddress, fallback);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
|
LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported");
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
@ -355,7 +357,7 @@ namespace net
|
||||||
if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
|
if (cur_ifname == ifname && cur->ifa_addr && cur->ifa_addr->sa_family == af)
|
||||||
{
|
{
|
||||||
// match
|
// match
|
||||||
char addr[INET6_ADDRSTRLEN];
|
char addr[INET6_ADDRSTRLEN];
|
||||||
memset (addr, 0, INET6_ADDRSTRLEN);
|
memset (addr, 0, INET6_ADDRSTRLEN);
|
||||||
if(af == AF_INET)
|
if(af == AF_INET)
|
||||||
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
|
inet_ntop(af, &((sockaddr_in *)cur->ifa_addr)->sin_addr, addr, INET6_ADDRSTRLEN);
|
||||||
|
@ -379,7 +381,6 @@ namespace net
|
||||||
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
|
LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname);
|
||||||
}
|
}
|
||||||
return boost::asio::ip::address::from_string(fallback);
|
return boost::asio::ip::address::from_string(fallback);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,34 +132,34 @@ namespace util
|
||||||
|
|
||||||
boost::asio::io_service& GetIOService () { return m_Service; }
|
boost::asio::io_service& GetIOService () { return m_Service; }
|
||||||
bool IsRunning () const { return m_IsRunning; };
|
bool IsRunning () const { return m_IsRunning; };
|
||||||
|
|
||||||
void StartIOService ();
|
void StartIOService ();
|
||||||
void StopIOService ();
|
void StopIOService ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Run ();
|
void Run ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_Name;
|
std::string m_Name;
|
||||||
volatile bool m_IsRunning;
|
volatile bool m_IsRunning;
|
||||||
std::unique_ptr<std::thread> m_Thread;
|
std::unique_ptr<std::thread> m_Thread;
|
||||||
boost::asio::io_service m_Service;
|
boost::asio::io_service m_Service;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunnableServiceWithWork: public RunnableService
|
class RunnableServiceWithWork: public RunnableService
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
RunnableServiceWithWork (const std::string& name):
|
RunnableServiceWithWork (const std::string& name):
|
||||||
RunnableService (name), m_Work (GetIOService ()) {}
|
RunnableService (name), m_Work (GetIOService ()) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
boost::asio::io_service::work m_Work;
|
boost::asio::io_service::work m_Work;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace net
|
namespace net
|
||||||
{
|
{
|
||||||
int GetMTU (const boost::asio::ip::address& localAddress);
|
int GetMTU (const boost::asio::ip::address& localAddress);
|
||||||
|
|
|
@ -31,7 +31,7 @@ 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);
|
i2p::config::GetOption("persist.addressbook", m_IsPersist);
|
||||||
}
|
}
|
||||||
|
@ -77,10 +77,10 @@ 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)
|
if (!m_IsPersist)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "Addressbook: Persistence is disabled");
|
LogPrint(eLogDebug, "Addressbook: Persistence is disabled");
|
||||||
return nullptr;
|
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);
|
||||||
|
@ -121,7 +121,7 @@ namespace client
|
||||||
|
|
||||||
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
|
void AddressBookFilesystemStorage::RemoveAddress (const i2p::data::IdentHash& ident)
|
||||||
{
|
{
|
||||||
if (!m_IsPersist) return;
|
if (!m_IsPersist) return;
|
||||||
storage.Remove( ident.ToBase32() );
|
storage.Remove( ident.ToBase32() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& it: addresses)
|
for (const auto& it: addresses)
|
||||||
{
|
{
|
||||||
f << it.first << ",";
|
f << it.first << ",";
|
||||||
if (it.second->IsIdentHash ())
|
if (it.second->IsIdentHash ())
|
||||||
f << it.second->identHash.ToBase32 ();
|
f << it.second->identHash.ToBase32 ();
|
||||||
|
@ -251,12 +251,12 @@ namespace client
|
||||||
if (blindedPublicKey->IsValid ())
|
if (blindedPublicKey->IsValid ())
|
||||||
addressType = eAddressBlindedPublicKey;
|
addressType = eAddressBlindedPublicKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Address::Address (const i2p::data::IdentHash& hash)
|
Address::Address (const i2p::data::IdentHash& hash)
|
||||||
{
|
{
|
||||||
addressType = eAddressIndentHash;
|
addressType = eAddressIndentHash;
|
||||||
identHash = hash;
|
identHash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
|
AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false),
|
||||||
|
@ -322,7 +322,7 @@ namespace client
|
||||||
{
|
{
|
||||||
auto pos = address.find(".b32.i2p");
|
auto pos = address.find(".b32.i2p");
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
auto addr = std::make_shared<const Address>(address.substr (0, pos));
|
auto addr = std::make_shared<const Address>(address.substr (0, pos));
|
||||||
return addr->IsValid () ? addr : nullptr;
|
return addr->IsValid () ? addr : nullptr;
|
||||||
}
|
}
|
||||||
|
@ -333,10 +333,10 @@ namespace client
|
||||||
{
|
{
|
||||||
auto addr = FindAddress (address);
|
auto addr = FindAddress (address);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
LookupAddress (address); // TODO:
|
LookupAddress (address); // TODO:
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if not .b32 we assume full base64 address
|
// if not .b32 we assume full base64 address
|
||||||
i2p::data::IdentityEx dest;
|
i2p::data::IdentityEx dest;
|
||||||
if (!dest.FromBase64 (address))
|
if (!dest.FromBase64 (address))
|
||||||
|
@ -359,10 +359,10 @@ namespace client
|
||||||
{
|
{
|
||||||
m_Addresses[address] = std::make_shared<Address>(jump.substr (0, pos));
|
m_Addresses[address] = std::make_shared<Address>(jump.substr (0, pos));
|
||||||
LogPrint (eLogInfo, "Addressbook: added ", address," -> ", jump);
|
LogPrint (eLogInfo, "Addressbook: added ", address," -> ", jump);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// assume base64
|
// assume base64
|
||||||
auto ident = std::make_shared<i2p::data::IdentityEx>();
|
auto ident = std::make_shared<i2p::data::IdentityEx>();
|
||||||
if (ident->FromBase64 (jump))
|
if (ident->FromBase64 (jump))
|
||||||
{
|
{
|
||||||
|
@ -487,18 +487,18 @@ namespace client
|
||||||
LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead");
|
LogPrint (eLogWarning, "Addressbook: subscriptions.txt usage is deprecated, use config file instead");
|
||||||
}
|
}
|
||||||
else if (!i2p::config::IsDefault("addressbook.subscriptions"))
|
else if (!i2p::config::IsDefault("addressbook.subscriptions"))
|
||||||
{
|
{
|
||||||
// using config file items
|
// using config file items
|
||||||
std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
|
std::string subscriptionURLs; i2p::config::GetOption("addressbook.subscriptions", subscriptionURLs);
|
||||||
std::vector<std::string> subsList;
|
std::vector<std::string> subsList;
|
||||||
boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
|
boost::split(subsList, subscriptionURLs, boost::is_any_of(","), boost::token_compress_on);
|
||||||
|
|
||||||
for (size_t i = 0; i < subsList.size (); i++)
|
for (size_t i = 0; i < subsList.size (); i++)
|
||||||
{
|
{
|
||||||
m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
|
m_Subscriptions.push_back (std::make_shared<AddressBookSubscription> (*this, subsList[i]));
|
||||||
}
|
}
|
||||||
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
|
LogPrint (eLogInfo, "Addressbook: ", m_Subscriptions.size (), " subscriptions urls loaded");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Addressbook: subscriptions already loaded");
|
LogPrint (eLogError, "Addressbook: subscriptions already loaded");
|
||||||
|
@ -515,7 +515,7 @@ namespace client
|
||||||
if (dot != std::string::npos)
|
if (dot != std::string::npos)
|
||||||
{
|
{
|
||||||
auto domain = it.first.substr (dot + 1);
|
auto domain = it.first.substr (dot + 1);
|
||||||
auto it1 = m_Addresses.find (domain); // find domain in our addressbook
|
auto it1 = m_Addresses.find (domain); // find domain in our addressbook
|
||||||
if (it1 != m_Addresses.end () && it1->second->IsIdentHash ())
|
if (it1 != m_Addresses.end () && it1->second->IsIdentHash ())
|
||||||
{
|
{
|
||||||
auto dest = context.FindLocalDestination (it1->second->identHash);
|
auto dest = context.FindLocalDestination (it1->second->identHash);
|
||||||
|
@ -610,7 +610,7 @@ namespace client
|
||||||
{
|
{
|
||||||
// download it from default subscription
|
// download it from default subscription
|
||||||
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
|
LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription.");
|
||||||
std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
|
std::string defaultSubURL; i2p::config::GetOption("addressbook.defaulturl", defaultSubURL);
|
||||||
if (!m_DefaultSubscription)
|
if (!m_DefaultSubscription)
|
||||||
m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
|
m_DefaultSubscription = std::make_shared<AddressBookSubscription>(*this, defaultSubURL);
|
||||||
m_IsDownloading = true;
|
m_IsDownloading = true;
|
||||||
|
@ -743,13 +743,13 @@ namespace client
|
||||||
i2p::http::URL url;
|
i2p::http::URL url;
|
||||||
// must be run in separate thread
|
// must be run in separate thread
|
||||||
LogPrint (eLogInfo, "Addressbook: Downloading hosts database from ", m_Link);
|
LogPrint (eLogInfo, "Addressbook: Downloading hosts database from ", m_Link);
|
||||||
if (!url.parse(m_Link))
|
if (!url.parse(m_Link))
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Addressbook: failed to parse url: ", m_Link);
|
LogPrint(eLogError, "Addressbook: failed to parse url: ", m_Link);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto addr = m_Book.GetAddress (url.host);
|
auto addr = m_Book.GetAddress (url.host);
|
||||||
if (!addr || !addr->IsIdentHash ())
|
if (!addr || !addr->IsIdentHash ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Addressbook: Can't resolve ", url.host);
|
LogPrint (eLogError, "Addressbook: Can't resolve ", url.host);
|
||||||
return false;
|
return false;
|
||||||
|
@ -802,7 +802,7 @@ namespace client
|
||||||
/* convert url to relative */
|
/* convert url to relative */
|
||||||
url.schema = "";
|
url.schema = "";
|
||||||
url.host = "";
|
url.host = "";
|
||||||
req.uri = url.to_string();
|
req.uri = url.to_string();
|
||||||
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
auto stream = i2p::client::context.GetSharedLocalDestination ()->CreateStream (leaseSet, dest_port);
|
||||||
std::string request = req.to_string();
|
std::string request = req.to_string();
|
||||||
stream->Send ((const uint8_t *) request.data(), request.length());
|
stream->Send ((const uint8_t *) request.data(), request.length());
|
||||||
|
@ -920,7 +920,7 @@ namespace client
|
||||||
{
|
{
|
||||||
auto datagram = m_LocalDestination->GetDatagramDestination ();
|
auto datagram = m_LocalDestination->GetDatagramDestination ();
|
||||||
if (datagram)
|
if (datagram)
|
||||||
datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT);
|
datagram->ResetReceiver (ADDRESS_RESOLVER_DATAGRAM_PORT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace client
|
||||||
i2p::data::IdentHash identHash;
|
i2p::data::IdentHash identHash;
|
||||||
std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;
|
std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;
|
||||||
|
|
||||||
Address (const std::string& b32);
|
Address (const std::string& b32);
|
||||||
Address (const i2p::data::IdentHash& hash);
|
Address (const i2p::data::IdentHash& hash);
|
||||||
bool IsIdentHash () const { return addressType == eAddressIndentHash; };
|
bool IsIdentHash () const { return addressType == eAddressIndentHash; };
|
||||||
bool IsValid () const { return addressType != eAddressInvalid; };
|
bool IsValid () const { return addressType != eAddressInvalid; };
|
||||||
};
|
};
|
||||||
|
@ -160,5 +160,3 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -50,10 +50,10 @@ namespace client
|
||||||
void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr<AddressReceiver> receiver)
|
void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr<AddressReceiver> receiver)
|
||||||
{
|
{
|
||||||
receiver->socket->async_read_some (boost::asio::buffer(
|
receiver->socket->async_read_some (boost::asio::buffer(
|
||||||
receiver->buffer + receiver->bufferOffset,
|
receiver->buffer + receiver->bufferOffset,
|
||||||
BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset),
|
BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset),
|
||||||
std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this,
|
std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this,
|
||||||
std::placeholders::_1, std::placeholders::_2, receiver));
|
std::placeholders::_1, std::placeholders::_2, receiver));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred,
|
||||||
|
@ -255,7 +255,7 @@ namespace client
|
||||||
std::bind(&BOBCommandSession::HandleReceivedLine, shared_from_this(),
|
std::bind(&BOBCommandSession::HandleReceivedLine, shared_from_this(),
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void BOBCommandSession::HandleReceivedLine(const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void BOBCommandSession::HandleReceivedLine(const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
if(ecode)
|
if(ecode)
|
||||||
|
@ -267,14 +267,14 @@ namespace client
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
std::istream is(&m_ReceiveBuffer);
|
std::istream is(&m_ReceiveBuffer);
|
||||||
std::getline(is, line);
|
std::getline(is, line);
|
||||||
|
|
||||||
std::string command, operand;
|
std::string command, operand;
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
iss >> command >> operand;
|
iss >> command >> operand;
|
||||||
|
|
||||||
// process command
|
// process command
|
||||||
auto& handlers = m_Owner.GetCommandHandlers();
|
auto& handlers = m_Owner.GetCommandHandlers();
|
||||||
auto it = handlers.find(command);
|
auto it = handlers.find(command);
|
||||||
|
@ -346,7 +346,7 @@ namespace client
|
||||||
std::ostream os(&m_SendBuffer);
|
std::ostream os(&m_SendBuffer);
|
||||||
os << data << std::endl;
|
os << data << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out)
|
void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out)
|
||||||
{
|
{
|
||||||
// helper lambdas
|
// helper lambdas
|
||||||
|
@ -355,7 +355,7 @@ namespace client
|
||||||
const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; };
|
const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; };
|
||||||
const auto destReady = [](const BOBDestination * const dest) { return dest->GetLocalDestination()->IsReady(); };
|
const auto destReady = [](const BOBDestination * const dest) { return dest->GetLocalDestination()->IsReady(); };
|
||||||
const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str
|
const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str
|
||||||
|
|
||||||
// tunnel info
|
// tunnel info
|
||||||
const std::string nickname = currentTunnel ? m_Nickname : dest->GetNickname();
|
const std::string nickname = currentTunnel ? m_Nickname : dest->GetNickname();
|
||||||
const bool quiet = currentTunnel ? m_IsQuiet : dest->GetQuiet();
|
const bool quiet = currentTunnel ? m_IsQuiet : dest->GetQuiet();
|
||||||
|
@ -367,7 +367,7 @@ namespace client
|
||||||
const bool starting = destExists(dest) && !destReady(dest);
|
const bool starting = destExists(dest) && !destReady(dest);
|
||||||
const bool running = destExists(dest) && destReady(dest);
|
const bool running = destExists(dest) && destReady(dest);
|
||||||
const bool stopping = false;
|
const bool stopping = false;
|
||||||
|
|
||||||
// build line
|
// build line
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "DATA "
|
ss << "DATA "
|
||||||
|
@ -433,11 +433,11 @@ namespace client
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_CurrentDestination)
|
if (!m_CurrentDestination)
|
||||||
{
|
{
|
||||||
m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command
|
m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options), // deleted in clear command
|
||||||
m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet);
|
m_Nickname, m_InHost, m_OutHost, m_InPort, m_OutPort, m_IsQuiet);
|
||||||
m_Owner.AddDestination (m_Nickname, m_CurrentDestination);
|
m_Owner.AddDestination (m_Nickname, m_CurrentDestination);
|
||||||
}
|
}
|
||||||
if (m_InPort)
|
if (m_InPort)
|
||||||
|
@ -613,25 +613,24 @@ namespace client
|
||||||
}
|
}
|
||||||
auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination ();
|
auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination ();
|
||||||
if (addr->IsIdentHash ())
|
if (addr->IsIdentHash ())
|
||||||
{
|
{
|
||||||
// we might have leaseset already
|
// we might have leaseset already
|
||||||
auto leaseSet = localDestination->FindLeaseSet (addr->identHash);
|
auto leaseSet = localDestination->FindLeaseSet (addr->identHash);
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ());
|
SendReplyOK (leaseSet->GetIdentity ()->ToBase64 ().c_str ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// trying to request
|
// trying to request
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
auto requstCallback =
|
auto requstCallback = [s](std::shared_ptr<i2p::data::LeaseSet> ls)
|
||||||
[s](std::shared_ptr<i2p::data::LeaseSet> ls)
|
{
|
||||||
{
|
if (ls)
|
||||||
if (ls)
|
s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ());
|
||||||
s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ());
|
else
|
||||||
else
|
s->SendReplyError ("LeaseSet Not found");
|
||||||
s->SendReplyError ("LeaseSet Not found");
|
};
|
||||||
};
|
|
||||||
if (addr->IsIdentHash ())
|
if (addr->IsIdentHash ())
|
||||||
localDestination->RequestDestination (addr->identHash, requstCallback);
|
localDestination->RequestDestination (addr->identHash, requstCallback);
|
||||||
else
|
else
|
||||||
|
@ -794,7 +793,7 @@ namespace client
|
||||||
|
|
||||||
BOBCommandChannel::~BOBCommandChannel ()
|
BOBCommandChannel::~BOBCommandChannel ()
|
||||||
{
|
{
|
||||||
if (IsRunning ())
|
if (IsRunning ())
|
||||||
Stop ();
|
Stop ();
|
||||||
for (const auto& it: m_Destinations)
|
for (const auto& it: m_Destinations)
|
||||||
delete it.second;
|
delete it.second;
|
||||||
|
@ -856,8 +855,7 @@ namespace client
|
||||||
session->SendVersion ();
|
session->SendVersion ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "BOB: accept error: ", ecode.message ());
|
LogPrint (eLogError, "BOB: accept error: ", ecode.message ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace client
|
||||||
const char BOB_COMMAND_OPTION[] = "option";
|
const char BOB_COMMAND_OPTION[] = "option";
|
||||||
const char BOB_COMMAND_STATUS[] = "status";
|
const char BOB_COMMAND_STATUS[] = "status";
|
||||||
const char BOB_COMMAND_HELP[] = "help";
|
const char BOB_COMMAND_HELP[] = "help";
|
||||||
|
|
||||||
const char BOB_HELP_ZAP[] = "zap - Shuts down BOB.";
|
const char BOB_HELP_ZAP[] = "zap - Shuts down BOB.";
|
||||||
const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB.";
|
const char BOB_HELP_QUIT[] = "quit - Quits this session with BOB.";
|
||||||
const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel.";
|
const char BOB_HELP_START[] = "start - Starts the current nicknamed tunnel.";
|
||||||
|
@ -75,15 +75,15 @@ namespace client
|
||||||
|
|
||||||
class BOBI2PInboundTunnel: public BOBI2PTunnel
|
class BOBI2PInboundTunnel: public BOBI2PTunnel
|
||||||
{
|
{
|
||||||
struct AddressReceiver
|
struct AddressReceiver
|
||||||
{
|
{
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> socket;
|
std::shared_ptr<boost::asio::ip::tcp::socket> socket;
|
||||||
char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
|
char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address
|
||||||
uint8_t * data; // pointer to buffer
|
uint8_t * data; // pointer to buffer
|
||||||
size_t dataLen, bufferOffset;
|
size_t dataLen, bufferOffset;
|
||||||
|
|
||||||
AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
|
AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace client
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
|
BOBI2POutboundTunnel (const std::string& outhost, int port, std::shared_ptr<ClientDestination> localDestination, bool quiet);
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
@ -162,7 +162,7 @@ namespace client
|
||||||
std::shared_ptr<ClientDestination> m_LocalDestination;
|
std::shared_ptr<ClientDestination> m_LocalDestination;
|
||||||
BOBI2POutboundTunnel * m_OutboundTunnel;
|
BOBI2POutboundTunnel * m_OutboundTunnel;
|
||||||
BOBI2PInboundTunnel * m_InboundTunnel;
|
BOBI2PInboundTunnel * m_InboundTunnel;
|
||||||
|
|
||||||
std::string m_Nickname;
|
std::string m_Nickname;
|
||||||
std::string m_InHost, m_OutHost;
|
std::string m_InHost, m_OutHost;
|
||||||
int m_InPort, m_OutPort;
|
int m_InPort, m_OutPort;
|
||||||
|
@ -215,14 +215,14 @@ namespace client
|
||||||
void SendReplyOK (const char * msg = nullptr);
|
void SendReplyOK (const char * msg = nullptr);
|
||||||
void SendReplyError (const char * msg);
|
void SendReplyError (const char * msg);
|
||||||
void SendRaw (const char * data);
|
void SendRaw (const char * data);
|
||||||
|
|
||||||
void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out);
|
void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
BOBCommandChannel& m_Owner;
|
BOBCommandChannel& m_Owner;
|
||||||
boost::asio::ip::tcp::socket m_Socket;
|
boost::asio::ip::tcp::socket m_Socket;
|
||||||
boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
|
boost::asio::streambuf m_ReceiveBuffer, m_SendBuffer;
|
||||||
bool m_IsOpen, m_IsQuiet, m_IsActive;
|
bool m_IsOpen, m_IsQuiet, m_IsActive;
|
||||||
std::string m_Nickname, m_InHost, m_OutHost;
|
std::string m_Nickname, m_InHost, m_OutHost;
|
||||||
int m_InPort, m_OutPort;
|
int m_InPort, m_OutPort;
|
||||||
|
@ -269,4 +269,3 @@ namespace client
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -52,18 +52,18 @@ namespace client
|
||||||
|
|
||||||
// SAM
|
// SAM
|
||||||
bool sam; i2p::config::GetOption("sam.enabled", sam);
|
bool sam; i2p::config::GetOption("sam.enabled", sam);
|
||||||
if (sam)
|
if (sam)
|
||||||
{
|
{
|
||||||
std::string samAddr; i2p::config::GetOption("sam.address", samAddr);
|
std::string samAddr; i2p::config::GetOption("sam.address", samAddr);
|
||||||
uint16_t samPort; i2p::config::GetOption("sam.port", samPort);
|
uint16_t samPort; i2p::config::GetOption("sam.port", samPort);
|
||||||
bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread);
|
bool singleThread; i2p::config::GetOption("sam.singlethread", singleThread);
|
||||||
LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort);
|
LogPrint(eLogInfo, "Clients: starting SAM bridge at ", samAddr, ":", samPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_SamBridge = new SAMBridge (samAddr, samPort, singleThread);
|
m_SamBridge = new SAMBridge (samAddr, samPort, singleThread);
|
||||||
m_SamBridge->Start ();
|
m_SamBridge->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what());
|
LogPrint(eLogError, "Clients: Exception in SAM bridge: ", e.what());
|
||||||
ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ());
|
ThrowFatal ("Unable to start SAM bridge at ", samAddr, ":", samPort, ": ", e.what ());
|
||||||
|
@ -76,12 +76,12 @@ namespace client
|
||||||
std::string bobAddr; i2p::config::GetOption("bob.address", bobAddr);
|
std::string bobAddr; i2p::config::GetOption("bob.address", bobAddr);
|
||||||
uint16_t bobPort; i2p::config::GetOption("bob.port", bobPort);
|
uint16_t bobPort; i2p::config::GetOption("bob.port", bobPort);
|
||||||
LogPrint(eLogInfo, "Clients: starting BOB command channel at ", bobAddr, ":", bobPort);
|
LogPrint(eLogInfo, "Clients: starting BOB command channel at ", bobAddr, ":", bobPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort);
|
m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort);
|
||||||
m_BOBCommandChannel->Start ();
|
m_BOBCommandChannel->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what());
|
LogPrint(eLogError, "Clients: Exception in BOB bridge: ", e.what());
|
||||||
ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ());
|
ThrowFatal ("Unable to start BOB bridge at ", bobAddr, ":", bobPort, ": ", e.what ());
|
||||||
|
@ -95,12 +95,12 @@ namespace client
|
||||||
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
std::string i2cpAddr; i2p::config::GetOption("i2cp.address", i2cpAddr);
|
||||||
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
uint16_t i2cpPort; i2p::config::GetOption("i2cp.port", i2cpPort);
|
||||||
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
LogPrint(eLogInfo, "Clients: starting I2CP at ", i2cpAddr, ":", i2cpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort);
|
||||||
m_I2CPServer->Start ();
|
m_I2CPServer->Start ();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what());
|
LogPrint(eLogError, "Clients: Exception in I2CP: ", e.what());
|
||||||
ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ());
|
ThrowFatal ("Unable to start I2CP at ", i2cpAddr, ":", i2cpPort, ": ", e.what ());
|
||||||
|
@ -407,13 +407,13 @@ namespace client
|
||||||
template<typename Section, typename Type>
|
template<typename Section, typename Type>
|
||||||
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
|
std::string ClientContext::GetI2CPOption (const Section& section, const std::string& name, const Type& value) const
|
||||||
{
|
{
|
||||||
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
|
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), std::to_string (value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const
|
std::string ClientContext::GetI2CPStringOption (const Section& section, const std::string& name, const std::string& value) const
|
||||||
{
|
{
|
||||||
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value);
|
return section.second.get (boost::property_tree::ptree::path_type (name, '/'), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
|
@ -423,13 +423,13 @@ namespace client
|
||||||
{
|
{
|
||||||
if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group))
|
if (it.first.length () >= group.length () && !it.first.compare (0, group.length (), group))
|
||||||
options[it.first] = it.second.get_value ("");
|
options[it.first] = it.second.get_value ("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Section>
|
template<typename Section>
|
||||||
void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
|
void ClientContext::ReadI2CPOptions (const Section& section, std::map<std::string, std::string>& options) const
|
||||||
{
|
{
|
||||||
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
|
options[I2CP_PARAM_INBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNEL_LENGTH, DEFAULT_INBOUND_TUNNEL_LENGTH);
|
||||||
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
options[I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, DEFAULT_OUTBOUND_TUNNEL_LENGTH);
|
||||||
options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY);
|
options[I2CP_PARAM_INBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, DEFAULT_INBOUND_TUNNELS_QUANTITY);
|
||||||
options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY);
|
options[I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY] = GetI2CPOption (section, I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, DEFAULT_OUTBOUND_TUNNELS_QUANTITY);
|
||||||
|
@ -528,10 +528,10 @@ namespace client
|
||||||
{
|
{
|
||||||
std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE);
|
std::string type = section.second.get<std::string> (I2P_TUNNELS_SECTION_TYPE);
|
||||||
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT
|
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_SOCKS
|
|| type == I2P_TUNNELS_SECTION_TYPE_SOCKS
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS
|
|| type == I2P_TUNNELS_SECTION_TYPE_WEBSOCKS
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY
|
|| type == I2P_TUNNELS_SECTION_TYPE_HTTPPROXY
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
|
|| type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT)
|
||||||
{
|
{
|
||||||
// mandatory params
|
// mandatory params
|
||||||
std::string dest;
|
std::string dest;
|
||||||
|
@ -640,9 +640,9 @@ namespace client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER
|
else if (type == I2P_TUNNELS_SECTION_TYPE_SERVER
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_HTTP
|
|| type == I2P_TUNNELS_SECTION_TYPE_HTTP
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_IRC
|
|| type == I2P_TUNNELS_SECTION_TYPE_IRC
|
||||||
|| type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
|
|| type == I2P_TUNNELS_SECTION_TYPE_UDPSERVER)
|
||||||
{
|
{
|
||||||
// mandatory params
|
// mandatory params
|
||||||
std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
|
std::string host = section.second.get<std::string> (I2P_SERVER_TUNNEL_HOST);
|
||||||
|
@ -699,7 +699,7 @@ namespace client
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2PServerTunnel> serverTunnel;
|
std::shared_ptr<I2PServerTunnel> serverTunnel;
|
||||||
if (type == I2P_TUNNELS_SECTION_TYPE_HTTP)
|
if (type == I2P_TUNNELS_SECTION_TYPE_HTTP)
|
||||||
serverTunnel = std::make_shared<I2PServerTunnelHTTP> (name, host, port, localDestination, hostOverride, inPort, gzip);
|
serverTunnel = std::make_shared<I2PServerTunnelHTTP> (name, host, port, localDestination, hostOverride, inPort, gzip);
|
||||||
else if (type == I2P_TUNNELS_SECTION_TYPE_IRC)
|
else if (type == I2P_TUNNELS_SECTION_TYPE_IRC)
|
||||||
|
@ -745,7 +745,7 @@ namespace client
|
||||||
ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
|
ins.first->second->SetLocalDestination (serverTunnel->GetLocalDestination ());
|
||||||
}
|
}
|
||||||
ins.first->second->isUpdated = true;
|
ins.first->second->isUpdated = true;
|
||||||
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
|
LogPrint (eLogInfo, "Clients: I2P server tunnel for destination/port ", m_AddressBook.ToAddress(localDestination->GetIdentHash ()), "/", inPort, " already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -769,9 +769,9 @@ namespace client
|
||||||
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys);
|
||||||
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
|
std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr);
|
||||||
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
|
uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort);
|
||||||
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
|
|
||||||
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
|
std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL);
|
||||||
bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper);
|
bool httpAddresshelper; i2p::config::GetOption("httpproxy.addresshelper", httpAddresshelper);
|
||||||
|
i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType);
|
||||||
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
|
LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort);
|
||||||
if (httpProxyKeys.length () > 0)
|
if (httpProxyKeys.length () > 0)
|
||||||
{
|
{
|
||||||
|
@ -786,12 +786,12 @@ namespace client
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "Clients: failed to load HTTP Proxy key");
|
LogPrint(eLogError, "Clients: failed to load HTTP Proxy key");
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, httpAddresshelper, localDestination);
|
m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, httpAddresshelper, localDestination);
|
||||||
m_HttpProxy->Start();
|
m_HttpProxy->Start();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
|
LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what());
|
||||||
ThrowFatal ("Unable to start HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort, ": ", e.what ());
|
ThrowFatal ("Unable to start HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort, ": ", e.what ());
|
||||||
|
@ -826,13 +826,13 @@ namespace client
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key");
|
LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key");
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort,
|
m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort,
|
||||||
socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination);
|
socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination);
|
||||||
m_SocksProxy->Start();
|
m_SocksProxy->Start();
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what());
|
LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what());
|
||||||
ThrowFatal ("Unable to start SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort, ": ", e.what ());
|
ThrowFatal ("Unable to start SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort, ": ", e.what ());
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue