1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-04-24 07:49:26 +03:00

Merge PR #1200: Implement support for WireGuard

This commit is contained in:
Davide Beatrici
2021-03-01 03:59:35 +01:00
committed by GitHub
41 changed files with 2410 additions and 134 deletions
+218 -4
View File
@@ -1509,6 +1509,9 @@ PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
DECLARE_RPC_EX("GetServerCipherList", RPC_STR, StGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("AddWgk", RPC_WGK, StAddWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC_EX("DeleteWgk", RPC_WGK, StDeleteWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC_EX("EnumWgk", RPC_WGK, StEnumWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_RPC("CreateHub", RPC_CREATE_HUB, StCreateHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_RPC("SetHub", RPC_CREATE_HUB, StSetHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_RPC("GetHub", RPC_CREATE_HUB, StGetHub, InRpcCreateHub, OutRpcCreateHub)
@@ -1693,6 +1696,9 @@ DECLARE_SC_EX("GetServerCert", RPC_KEY_PAIR, ScGetServerCert, InRpcKeyPair, OutR
DECLARE_SC_EX("GetServerCipherList", RPC_STR, ScGetServerCipherList, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("AddWgk", RPC_WGK, ScAddWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC_EX("DeleteWgk", RPC_WGK, ScDeleteWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC_EX("EnumWgk", RPC_WGK, ScEnumWgk, InRpcWgk, OutRpcWgk, FreeRpcWgk)
DECLARE_SC("CreateHub", RPC_CREATE_HUB, ScCreateHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_SC("SetHub", RPC_CREATE_HUB, ScSetHub, InRpcCreateHub, OutRpcCreateHub)
DECLARE_SC("GetHub", RPC_CREATE_HUB, ScGetHub, InRpcCreateHub, OutRpcCreateHub)
@@ -9061,9 +9067,12 @@ UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t)
{
StrCpy(t->HubName, sizeof(t->HubName), h->Name);
t->Online = h->Offline ? false : true;
t->HubType = h->Type;
t->HubOption.DefaultGateway = h->Option->DefaultGateway;
t->HubOption.DefaultSubnet = h->Option->DefaultSubnet;
t->HubOption.MaxSession = h->Option->MaxSession;
t->HubOption.NoEnum = h->Option->NoEnum;
t->HubType = h->Type;
}
Unlock(h->lock);
@@ -9090,7 +9099,6 @@ UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t)
return ERR_INVALID_PARAMETER;
}
CHECK_RIGHT;
NO_SUPPORT_FOR_BRIDGE;
@@ -9175,8 +9183,12 @@ UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t)
else
{
h->Type = t->HubType;
h->Option->DefaultGateway = t->HubOption.DefaultGateway;
h->Option->DefaultSubnet = t->HubOption.DefaultSubnet;
h->Option->MaxSession = t->HubOption.MaxSession;
h->Option->NoEnum = t->HubOption.NoEnum;
if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&
IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)
{
@@ -9234,8 +9246,6 @@ UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t)
return ERR_NOT_FARM_CONTROLLER;
}
if (IsEmptyStr(t->HubName) || IsSafeStr(t->HubName) == false)
{
return ERR_INVALID_PARAMETER;
@@ -9279,6 +9289,8 @@ UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t)
// Create a hub object
Zero(&o, sizeof(o));
o.DefaultGateway = t->HubOption.DefaultGateway;
o.DefaultSubnet = t->HubOption.DefaultSubnet;
o.MaxSession = t->HubOption.MaxSession;
o.NoEnum = t->HubOption.NoEnum;
@@ -9497,6 +9509,144 @@ UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
return ERR_NO_ERROR;
}
// Add a WireGuard key to the allowed key list
UINT StAddWgk(ADMIN *a, RPC_WGK *t)
{
UINT ret = ERR_NO_ERROR;
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
LIST *to_add;
SERVER_ADMIN_ONLY;
to_add = NewListFast(NULL);
LockList(c->WgkList);
{
UINT i;
for (i = 0; i < t->Num; ++i)
{
WGK *rpc_wgk = &t->Wgks[i];
WGK *wgk;
if (IsEmptyStr(rpc_wgk->Key))
{
ret = ERR_INVALID_PARAMETER;
break;
}
if (Search(c->WgkList, rpc_wgk) != NULL)
{
ret = ERR_OBJECT_EXISTS;
break;
}
wgk = Malloc(sizeof(WGK));
StrCpy(wgk->Key, sizeof(wgk->Key), rpc_wgk->Key);
StrCpy(wgk->Hub, sizeof(wgk->Hub), rpc_wgk->Hub);
StrCpy(wgk->User, sizeof(wgk->User), rpc_wgk->User);
Add(to_add, wgk);
}
for (i = 0; i < LIST_NUM(to_add); ++i)
{
WGK *wgk = LIST_DATA(to_add, i);
ret == ERR_NO_ERROR ? Add(c->WgkList, wgk) : Free(wgk);
}
}
UnlockList(c->WgkList);
if (ret == ERR_NO_ERROR)
{
ALog(a, NULL, "LA_ADD_WGK", LIST_NUM(to_add));
IncrementServerConfigRevision(a->Server);
}
ReleaseList(to_add);
return ret;
}
// Delete a WireGuard key from the allowed key list
UINT StDeleteWgk(ADMIN *a, RPC_WGK *t)
{
UINT ret = ERR_NO_ERROR;
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
LIST *to_delete;
SERVER_ADMIN_ONLY;
to_delete = NewListFast(NULL);
LockList(c->WgkList);
{
UINT i;
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = Search(c->WgkList, &t->Wgks[i]);
if (wgk == NULL)
{
ret = ERR_OBJECT_NOT_FOUND;
break;
}
Add(to_delete, wgk);
}
if (ret == ERR_NO_ERROR)
{
for (i = 0; i < LIST_NUM(to_delete); ++i)
{
WGK *wgk = LIST_DATA(to_delete, i);
Delete(c->WgkList, wgk);
Free(wgk);
}
}
}
UnlockList(c->WgkList);
if (ret == ERR_NO_ERROR)
{
ALog(a, NULL, "LA_DELETE_WGK", LIST_NUM(to_delete));
IncrementServerConfigRevision(a->Server);
}
ReleaseList(to_delete);
return ret;
}
// List the allowed WireGuard keys
UINT StEnumWgk(ADMIN *a, RPC_WGK *t)
{
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
SERVER_ADMIN_ONLY;
LockList(c->WgkList);
{
UINT i;
t->Num = LIST_NUM(c->WgkList);
t->Wgks = Malloc(sizeof(WGK) * t->Num);
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = LIST_DATA(c->WgkList, i);
WGK *rpc_wgk = &t->Wgks[i];
StrCpy(rpc_wgk->Key, sizeof(rpc_wgk->Key), wgk->Key);
StrCpy(rpc_wgk->Hub, sizeof(rpc_wgk->Hub), wgk->Hub);
StrCpy(rpc_wgk->User, sizeof(rpc_wgk->User), wgk->User);
}
}
UnlockList(c->WgkList);
return ERR_NO_ERROR;
}
// Get status of connection to cluster controller
UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t)
{
@@ -10021,6 +10171,8 @@ UINT StGetProtoOptions(ADMIN *a, RPC_PROTO_OPTIONS *t)
UINT ret = ERR_NO_ERROR;
LIST *options;
SERVER_ADMIN_ONLY;
if (proto == NULL)
{
return ERR_NOT_SUPPORTED;
@@ -12885,6 +13037,8 @@ void InRpcHubOption(RPC_HUB_OPTION *t, PACK *p)
}
Zero(t, sizeof(RPC_HUB_OPTION));
t->DefaultGateway = PackGetInt(p, "DefaultGateway");
t->DefaultSubnet = PackGetInt(p, "DefaultSubnet");
t->MaxSession = PackGetInt(p, "MaxSession");
t->NoEnum = PackGetBool(p, "NoEnum");
}
@@ -12896,6 +13050,8 @@ void OutRpcHubOption(PACK *p, RPC_HUB_OPTION *t)
return;
}
PackAddInt(p, "DefaultGateway", t->DefaultGateway);
PackAddInt(p, "DefaultSubnet", t->DefaultSubnet);
PackAddInt(p, "MaxSession", t->MaxSession);
PackAddBool(p, "NoEnum", t->NoEnum);
}
@@ -14455,6 +14611,64 @@ void FreeRpcKeyPair(RPC_KEY_PAIR *t)
FreeK(t->Key);
}
// RPC_WGK
void InRpcWgk(RPC_WGK *t, PACK *p)
{
UINT i;
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
Zero(t, sizeof(RPC_WGK));
t->Num = PackGetIndexCount(p, "Key");
if (t->Num == 0)
{
return;
}
t->Wgks = ZeroMalloc(sizeof(WGK) * t->Num);
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = &t->Wgks[i];
PackGetStrEx(p, "Key", wgk->Key, sizeof(wgk->Key), i);
PackGetStrEx(p, "Hub", wgk->Hub, sizeof(wgk->Hub), i);
PackGetStrEx(p, "User", wgk->User, sizeof(wgk->User), i);
}
}
void OutRpcWgk(PACK *p, RPC_WGK *t)
{
UINT i;
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
for (i = 0; i < t->Num; ++i)
{
WGK *wgk = &t->Wgks[i];
PackAddStrEx(p, "Key", wgk->Key, i, t->Num);
PackAddStrEx(p, "Hub", wgk->Hub, i, t->Num);
PackAddStrEx(p, "User", wgk->User, i, t->Num);
}
}
void FreeRpcWgk(RPC_WGK *t)
{
// Validate arguments
if (t == NULL)
{
return;
}
Free(t->Wgks);
}
// NODE_INFO
void InRpcNodeInfo(NODE_INFO *t, PACK *p)
{
+18
View File
@@ -226,9 +226,18 @@ struct RPC_KEY_PAIR
UINT Flag1; // Flag1
};
// WireGuard keys
struct RPC_WGK
{
UINT Num; // Number of keys
WGK *Wgks; // Keys
};
// HUB option
struct RPC_HUB_OPTION
{
UINT DefaultGateway; // Default gateway address
UINT DefaultSubnet; // Default subnet mask
UINT MaxSession; // Maximum number of sessions
bool NoEnum; // Not listed
};
@@ -987,6 +996,9 @@ UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
UINT StGetServerCipherList(ADMIN *a, RPC_STR *t);
UINT StGetServerCipher(ADMIN *a, RPC_STR *t);
UINT StSetServerCipher(ADMIN *a, RPC_STR *t);
UINT StAddWgk(ADMIN *a, RPC_WGK *t);
UINT StDeleteWgk(ADMIN *a, RPC_WGK *t);
UINT StEnumWgk(ADMIN *a, RPC_WGK *t);
UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t);
UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t);
UINT StGetHub(ADMIN *a, RPC_CREATE_HUB *t);
@@ -1135,6 +1147,9 @@ UINT ScGetServerCert(RPC *r, RPC_KEY_PAIR *t);
UINT ScGetServerCipherList(RPC *r, RPC_STR *t);
UINT ScGetServerCipher(RPC *r, RPC_STR *t);
UINT ScSetServerCipher(RPC *r, RPC_STR *t);
UINT ScAddWgk(RPC *r, RPC_WGK *t);
UINT ScDeleteWgk(RPC *r, RPC_WGK *t);
UINT ScEnumWgk(RPC *r, RPC_WGK *t);
UINT ScCreateHub(RPC *r, RPC_CREATE_HUB *t);
UINT ScSetHub(RPC *r, RPC_CREATE_HUB *t);
UINT ScGetHub(RPC *r, RPC_CREATE_HUB *t);
@@ -1392,6 +1407,9 @@ void OutRpcMemInfo(PACK *p, MEMINFO *t);
void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p);
void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t);
void FreeRpcKeyPair(RPC_KEY_PAIR *t);
void InRpcWgk(RPC_WGK *t, PACK *p);
void OutRpcWgk(PACK *p, RPC_WGK *t);
void FreeRpcWgk(RPC_WGK *t);
void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p);
void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t);
void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p);
+24 -2
View File
@@ -19,6 +19,28 @@ set_target_properties(cedar
RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIRECTORY}"
)
cmake_host_system_information(RESULT HAS_SSE2 QUERY HAS_SSE2)
set(BLAKE2_SRC_PATH $<IF:$<BOOL:HAS_SSE2>,${TOP_DIRECTORY}/3rdparty/BLAKE2/sse,${TOP_DIRECTORY}/3rdparty/BLAKE2/ref>)
target_include_directories(cedar PUBLIC ${BLAKE2_SRC_PATH})
target_sources(cedar PRIVATE "${BLAKE2_SRC_PATH}/blake2s.c")
if(VCPKG_TARGET_TRIPLET)
find_package(unofficial-sodium CONFIG REQUIRED)
target_link_libraries(cedar PUBLIC unofficial-sodium::sodium)
else()
find_package(PkgConfig REQUIRED)
pkg_search_module(SODIUM libsodium REQUIRED)
target_include_directories(cedar PUBLIC ${SODIUM_INCLUDE_DIRS})
if(NOT ("$ENV{TRAVIS_CPU_ARCH}" STREQUAL ppc64le))
target_link_libraries(cedar PUBLIC $<IF:$<BOOL:SODIUM_LINK_LIBRARIES>,${SODIUM_LINK_LIBRARIES},${SODIUM_LIBRARIES}>)
else()
# TODO: investigate why on ppc64le the use of SODIUM_LINK_LIBRARIES causes undefined references to libsodium functions.
target_link_libraries(cedar PUBLIC ${SODIUM_LIBRARIES})
endif()
endif()
if(WIN32)
set_target_properties(cedar
PROPERTIES
@@ -31,10 +53,10 @@ if(WIN32)
endif()
if(UNIX)
find_library(LIB_READLINE readline)
find_package(Curses REQUIRED)
find_library(LIB_READLINE readline)
target_link_libraries(cedar PRIVATE ${LIB_READLINE} ${CURSES_LIBRARIES})
target_link_libraries(cedar PRIVATE ${CURSES_LIBRARIES} ${LIB_READLINE})
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
target_link_libraries(cedar PRIVATE mayaqua pcap)
+12 -4
View File
@@ -1094,12 +1094,13 @@ void CleanupCedar(CEDAR *c)
WuFreeWebUI(c->WebUI);
FreeCedarLayer3(c);
/*
for (i = 0;i < LIST_NUM(c->HubList);i++)
for (i = 0; i < LIST_NUM(c->WgkList); ++i)
{
HUB *h = LIST_DATA(c->HubList, i);
WGK *wgk = LIST_DATA(c->WgkList, i);
Free(wgk);
}
*/
ReleaseList(c->WgkList);
for (i = 0;i < LIST_NUM(c->CaList);i++)
{
X *x = LIST_DATA(c->CaList, i);
@@ -1491,6 +1492,7 @@ CEDAR *NewCedar(X *server_x, K *server_k)
c->Traffic = NewTraffic();
c->TrafficLock = NewLock();
c->CaList = NewList(CompareCert);
c->WgkList = NewList(CompareWgk);
c->TrafficDiffList = NewList(NULL);
@@ -1600,6 +1602,12 @@ void InitCedar()
return;
}
if (sodium_init() == -1)
{
Debug("InitCedar(): sodium_init() failed!\n");
return;
}
// Initialize protocol module
InitProtocol();
}
+5 -2
View File
@@ -363,6 +363,7 @@
#define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority
#define AUTHTYPE_RADIUS 4 // Radius authentication
#define AUTHTYPE_NT 5 // Windows NT authentication
#define AUTHTYPE_WIREGUARD_KEY 97 // WireGuard public key authentication
#define AUTHTYPE_OPENVPN_CERT 98 // TLS client certificate authentication
#define AUTHTYPE_TICKET 99 // Ticket authentication
@@ -919,6 +920,7 @@ typedef struct CEDAR
UINT Type; // Type
LIST *ListenerList; // Listener list
LIST *HubList; // HUB list
LIST *WgkList; // WireGuard key list
LIST *ConnectionList; // Negotiating connection list
LIST *CaList; // List of CA
volatile bool Halt; // Halt flag
@@ -1028,8 +1030,6 @@ typedef struct CEDAR
#include <Cedar/Command.h>
// RPC over HTTP
#include <Cedar/Wpc.h>
// Layer-2/Layer-3 converter
#include <Cedar/IPC.h>
// Third party protocols
#include <Cedar/Proto.h>
#include <Cedar/Proto_IPsec.h>
@@ -1041,6 +1041,9 @@ typedef struct CEDAR
#include <Cedar/Proto_PPP.h>
#include <Cedar/Proto_SSTP.h>
#include <Cedar/Proto_Win7.h>
#include <Cedar/Proto_WireGuard.h>
// Layer-2/Layer-3 converter
#include <Cedar/IPC.h>
// UDP Acceleration
#include <Cedar/UdpAccel.h>
// DDNS Client
+2
View File
@@ -277,6 +277,7 @@ typedef struct HUB_SNAPSHOT HUB_SNAPSHOT;
typedef struct SERVER_SNAPSHOT SERVER_SNAPSHOT;
typedef struct SERVER_HUB_CREATE_HISTORY SERVER_HUB_CREATE_HISTORY;
typedef struct OPENVPN_SSTP_CONFIG OPENVPN_SSTP_CONFIG;
typedef struct WGK WGK;
// ==============================================================
// Server Admin Tool
@@ -299,6 +300,7 @@ typedef struct RPC_ENUM_FARM_ITEM RPC_ENUM_FARM_ITEM;
typedef struct RPC_ENUM_FARM RPC_ENUM_FARM;
typedef struct RPC_FARM_CONNECTION_STATUS RPC_FARM_CONNECTION_STATUS;
typedef struct RPC_KEY_PAIR RPC_KEY_PAIR;
typedef struct RPC_WGK RPC_WGK;
typedef struct RPC_HUB_OPTION RPC_HUB_OPTION;
typedef struct RPC_RADIUS RPC_RADIUS;
typedef struct RPC_HUB RPC_HUB;
+188
View File
@@ -7483,6 +7483,9 @@ void PsMain(PS *ps)
{"RouterTableDel", PsRouterTableDel},
{"LogFileList", PsLogFileList},
{"LogFileGet", PsLogFileGet},
{"WgkAdd", PsWgkAdd},
{"WgkDelete", PsWgkDelete},
{"WgkEnum", PsWgkEnum},
{"HubCreate", PsHubCreate},
{"HubCreateDynamic", PsHubCreateDynamic},
{"HubCreateStatic", PsHubCreateStatic},
@@ -7493,6 +7496,7 @@ void PsMain(PS *ps)
{"Hub", PsHub},
{"Online", PsOnline},
{"Offline", PsOffline},
{"SetStaticNetwork", PsSetStaticNetwork},
{"SetMaxSession", PsSetMaxSession},
{"SetHubPassword", PsSetHubPassword},
{"SetEnumAllow", PsSetEnumAllow},
@@ -10561,6 +10565,137 @@ UINT PsLogFileGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
return ret;
}
// Add a WireGuard key (TODO: ability add multiple keys in a single call)
UINT PsWgkAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
PS *ps = (PS *)param;
RPC_WGK t;
UINT ret;
LIST *o;
PARAM args[] =
{
{"[key]", CmdPrompt, _UU("CMD_WgkAdd_Prompt_[key]"), CmdEvalNotEmpty, NULL},
{"HUB", CmdPrompt, _UU("CMD_WgkAdd_Prompt_HUB"), NULL, NULL},
{"USER", CmdPrompt, _UU("CMD_WgkAdd_Prompt_USER"), NULL, NULL}
};
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
t.Num = 1;
t.Wgks = ZeroMalloc(sizeof(WGK));
StrCpy(t.Wgks[0].Key, sizeof(t.Wgks[0].Key), GetParamStr(o, "[key]"));
StrCpy(t.Wgks[0].Hub, sizeof(t.Wgks[0].Hub), GetParamStr(o, "HUB"));
StrCpy(t.Wgks[0].User, sizeof(t.Wgks[0].User), GetParamStr(o, "USER"));
FreeParamValueList(o);
ret = ScAddWgk(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
CmdPrintError(c, ret);
}
FreeRpcWgk(&t);
return ret;
}
// Delete a WireGuard key (TODO: ability to delete multiple keys in a single call)
UINT PsWgkDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
PS *ps = (PS *)param;
RPC_WGK t;
UINT ret;
LIST *o;
PARAM args[] =
{
{"[key]", CmdPrompt, _UU("CMD_WgkDelete_Prompt_[key]"), CmdEvalNotEmpty, NULL},
};
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
t.Num = 1;
t.Wgks = ZeroMalloc(sizeof(WGK));
StrCpy(t.Wgks[0].Key, sizeof(t.Wgks[0].Key), GetParamStr(o, "[key]"));
FreeParamValueList(o);
ret = ScDeleteWgk(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
CmdPrintError(c, ret);
}
FreeRpcWgk(&t);
return ret;
}
// List the WireGuard keys
UINT PsWgkEnum(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
UINT ret = ERR_NO_ERROR;
PS *ps = (PS *)param;
RPC_WGK t;
LIST *o;
o = ParseCommandList(c, cmd_name, str, NULL, 0);
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
ret = ScEnumWgk(ps->Rpc, &t);
if (ret == ERR_NO_ERROR)
{
UINT i;
CT *ct = CtNew();
CtInsertColumn(ct, _UU("CMD_WgkEnum_Column_Key"), false);
CtInsertColumn(ct, _UU("CMD_WgkEnum_Column_Hub"), false);
CtInsertColumn(ct, _UU("CMD_WgkEnum_Column_User"), false);
for (i = 0; i < t.Num; ++i)
{
const WGK *wgk = &t.Wgks[i];
wchar_t *key, *hub, *user;
key = CopyStrToUni(wgk->Key);
hub = CopyStrToUni(wgk->Hub);
user = CopyStrToUni(wgk->User);
CtInsert(ct, key, hub, user);
Free(key);
Free(hub);
Free(user);
}
CtFree(ct, c);
}
else
{
CmdPrintError(c, ret);
}
FreeRpcWgk(&t);
return ret;
}
// Create a New Virtual HUB
UINT PsHubCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
@@ -11143,6 +11278,53 @@ UINT PsOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
return 0;
}
// Set the static IPv4 network parameters for the Virtual HUB
UINT PsSetStaticNetwork(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
RPC_CREATE_HUB t;
PARAM args[] =
{
{"GATEWAY", CmdPrompt, _UU("CMD_SetStaticNetwork_Prompt_GATEWAY"), CmdEvalIp, NULL},
{"SUBNET", CmdPrompt, _UU("CMD_SetStaticNetwork_Prompt_SUBNET"), CmdEvalIp, NULL}
};
if (ps->HubName == NULL)
{
c->Write(c, _UU("CMD_Hub_Not_Selected"));
return ERR_INVALID_PARAMETER;
}
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
StrCpy(t.HubName, sizeof(t.HubName), ps->HubName);
ret = ScGetHub(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
goto FINAL;
}
t.HubOption.DefaultGateway = StrToIP32(GetParamStr(o, "GATEWAY"));
t.HubOption.DefaultSubnet = StrToIP32(GetParamStr(o, "SUBNET"));
ret = ScSetHub(ps->Rpc, &t);
FINAL:
if (ret != ERR_NO_ERROR)
{
CmdPrintError(c, ret);
}
FreeParamValueList(o);
return ret;
}
// Set the maximum number of concurrent connecting sessions of the Virtual HUB
UINT PsSetMaxSession(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
@@ -11420,6 +11602,12 @@ UINT PsOptionsGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
CtInsert(ct, _UU("CMD_OptionsGet_TYPE"), GetHubTypeStr(t.HubType));
IPToUniStr32(tmp, sizeof(tmp), t.HubOption.DefaultGateway);
CtInsert(ct, _UU("CMD_OptionsGet_GATEWAY"), tmp);
IPToUniStr32(tmp, sizeof(tmp), t.HubOption.DefaultSubnet);
CtInsert(ct, _UU("CMD_OptionsGet_SUBNET"), tmp);
CtFree(ct, c);
}
+4
View File
@@ -446,6 +446,9 @@ UINT PsRouterTableAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsRouterTableDel(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsLogFileList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsLogFileGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsWgkAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsWgkDelete(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsWgkEnum(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsHubCreate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsHubCreateDynamic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsHubCreateStatic(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
@@ -456,6 +459,7 @@ UINT PsHubList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsHub(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOnline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOffline(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSetStaticNetwork(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSetMaxSession(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSetHubPassword(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSetEnumAllow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
+2
View File
@@ -116,6 +116,8 @@ struct HUB_PA
struct HUB_OPTION
{
// Standard options
UINT DefaultGateway; // Used in IPC when DHCP cannot be used (e.g. WireGuard sessions)
UINT DefaultSubnet; // Used in IPC when DHCP cannot be used (e.g. WireGuard sessions)
UINT MaxSession; // Maximum number of simultaneous connections
bool NoEnum; // Excluded from the enumeration
// Advanced options
+16 -7
View File
@@ -226,8 +226,8 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
}
ipc = NewIPC(cedar, param->ClientName, param->Postfix, param->HubName,
param->UserName, param->Password, error_code, &param->ClientIp,
param->ClientPort, &param->ServerIp, param->ServerPort,
param->UserName, param->Password, param->WgKey, error_code,
&param->ClientIp, param->ClientPort, &param->ServerIp, param->ServerPort,
param->ClientHostname, param->CryptName,
param->BridgeMode, param->Mss, NULL, param->ClientCertificate, param->Layer);
@@ -235,13 +235,14 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
}
// Start a new IPC connection
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password, char *wg_key,
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
char *client_hostname, char *crypt_name,
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate,
UINT layer)
{
IPC *ipc;
HUB *hub;
UINT dummy_int = 0;
SOCK *a;
SOCK *s;
@@ -297,9 +298,6 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
ipc->FlushList = NewTubeFlushList();
StrCpy(ipc->ClientHostname, sizeof(ipc->ClientHostname), client_hostname);
StrCpy(ipc->HubName, sizeof(ipc->HubName), hubname);
StrCpy(ipc->UserName, sizeof(ipc->UserName), username);
StrCpy(ipc->Password, sizeof(ipc->Password), password);
// Connect the in-process socket
s = ConnectInProc(a, client_ip, client_port, server_ip, server_port);
@@ -339,7 +337,11 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
FreePack(p);
// Upload the authentication data
if (client_certificate != NULL)
if (IsEmptyStr(wg_key) == false)
{
p = PackLoginWithWireGuardKey(wg_key);
}
else if (client_certificate != NULL)
{
p = PackLoginWithOpenVPNCertificate(hubname, username, client_certificate);
}
@@ -466,6 +468,13 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
PackGetStr(p, "IpcHubName", ipc->HubName, sizeof(ipc->HubName));
Debug("IPC Hub Name: %s\n", ipc->HubName);
hub = GetHub(cedar, ipc->HubName);
if (hub != NULL)
{
UINTToIP(&ipc->DefaultGateway, hub->Option->DefaultGateway);
UINTToIP(&ipc->SubnetMask, hub->Option->DefaultSubnet);
}
MacToStr(macstr, sizeof(macstr), ipc->MacAddress);
Debug("IPC: Session = %s, Connection = %s, Mac = %s\n", ipc->SessionName, ipc->ConnectionName, macstr);
+2 -3
View File
@@ -75,6 +75,7 @@ struct IPC_PARAM
char HubName[MAX_HUBNAME_LEN + 1];
char UserName[MAX_USERNAME_LEN + 1];
char Password[MAX_PASSWORD_LEN + 1];
char WgKey[WG_KEY_BASE64_SIZE];
IP ClientIp;
UINT ClientPort;
IP ServerIp;
@@ -119,8 +120,6 @@ struct IPC
{
CEDAR *Cedar;
char HubName[MAX_HUBNAME_LEN + 1];
char UserName[MAX_USERNAME_LEN + 1];
char Password[MAX_PASSWORD_LEN + 1];
char ClientHostname[MAX_SIZE];
UCHAR random[SHA1_SIZE];
char SessionName[MAX_SESSION_NAME_LEN + 1];
@@ -173,7 +172,7 @@ struct IPC_IPV6_ROUTER_ADVERTISEMENT
UCHAR RouterLinkLayerAddress[6];
};
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password, char *wg_key,
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
char *client_hostname, char *crypt_name,
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate,
+3 -1
View File
@@ -213,6 +213,8 @@ PROTO *ProtoNew(CEDAR *cedar)
AddRef(cedar->ref);
// WireGuard
Add(proto->Containers, ProtoContainerNew(WgsGetProtoImpl()));
// OpenVPN
Add(proto->Containers, ProtoContainerNew(OvsGetProtoImpl()));
// SSTP
@@ -291,7 +293,7 @@ PROTO_CONTAINER *ProtoContainerNew(const PROTO_IMPL *impl)
option->Bool = impl_option->Bool;
break;
case PROTO_OPTION_STRING:
option->String = CopyStr(impl_option->String);
option->String = impl_option->String != NULL ? CopyStr(impl_option->String) : impl->OptionStringValue(option->Name);
break;
default:
Debug("ProtoContainerNew(): unhandled option type %u!\n", impl_option->Type);
+2 -1
View File
@@ -46,9 +46,10 @@ typedef struct PROTO_IMPL
{
const char *(*Name)();
const PROTO_OPTION *(*Options)();
char *(*OptionStringValue)(const char *name);
bool (*Init)(void **param, const LIST *options, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se, const char *cipher, const char *hostname);
void (*Free)(void *param);
bool (*IsPacketForMe)(const PROTO_MODE mode, const UCHAR *data, const UINT size);
bool (*IsPacketForMe)(const PROTO_MODE mode, const void *data, const UINT size);
bool (*ProcessData)(void *param, TCP_RAW_DATA *in, FIFO *out);
bool (*ProcessDatagrams)(void *param, LIST *in, LIST *out);
} PROTO_IMPL;
+1 -1
View File
@@ -59,7 +59,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p)
EtherIPLog(s, "LE_START_IPC", id.HubName, id.UserName, mss);
ipc = NewIPC(s->Cedar, client_name,
(s->L2TPv3 ? ETHERIP_L2TPV3_POSTFIX : ETHERIP_POSTFIX),
id.HubName, id.UserName, id.Password,
id.HubName, id.UserName, id.Password, NULL,
&error_code,
&s->ClientIP, s->ClientPort,
&s->ServerIP, s->ServerPort,
+9 -7
View File
@@ -20,6 +20,7 @@ const PROTO_IMPL *OvsGetProtoImpl()
{
OvsName,
OvsOptions,
NULL,
OvsInit,
OvsFree,
OvsIsPacketForMe,
@@ -69,16 +70,17 @@ void OvsFree(void *param)
}
// Check whether it's an OpenVPN packet
bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size)
bool OvsIsPacketForMe(const PROTO_MODE mode, const void *data, const UINT size)
{
if (data == NULL || size < 2)
{
return false;
}
if (mode == PROTO_MODE_TCP)
{
if (data == NULL || size < 2)
{
return false;
}
if (data[0] == 0x00 && data[1] == 0x0E)
const UCHAR *raw = data;
if (raw[0] == 0x00 && raw[1] == 0x0E)
{
return true;
}
+1 -3
View File
@@ -215,11 +215,9 @@ const char *OvsName();
const PROTO_OPTION *OvsOptions();
bool OvsInit(void **param, const LIST *options, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se, const char *cipher, const char *hostname);
void OvsFree(void *param);
bool OvsIsPacketForMe(const PROTO_MODE mode, const UCHAR *data, const UINT size);
bool OvsIsPacketForMe(const PROTO_MODE mode, const void *data, const UINT size);
bool OvsProcessData(void *param, TCP_RAW_DATA *in, FIFO *out);
bool OvsProcessDatagrams(void *param, LIST *in, LIST *out);
bool OvsIsOk(void *param);
UINT OvsEstablishedSessions(void *param);
OPENVPN_SERVER *NewOpenVpnServer(const LIST *options, CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event);
void FreeOpenVpnServer(OPENVPN_SERVER *s);
+3 -3
View File
@@ -1519,7 +1519,7 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
// Attempt to connect with IPC
UINT error_code;
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL,
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL,
IPC_LAYER_3);
@@ -2844,7 +2844,7 @@ bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp)
else if (p->Ipc == NULL)
{
Debug("MSCHAPv2 creating IPC\n");
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL,
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL,
+ IPC_LAYER_3);
@@ -3252,7 +3252,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
PPPParseUsername(p->Cedar, p->Eap_Identity, &d);
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "",
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, d.HubName, d.UserName, "", NULL,
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, p->Eap_TlsCtx.ClientCert.X,
IPC_LAYER_3);
+1
View File
@@ -13,6 +13,7 @@ const PROTO_IMPL *SstpGetProtoImpl()
{
SstpName,
SstpOptions,
NULL,
SstpInit,
SstpFree,
NULL,
File diff suppressed because it is too large Load Diff
+209
View File
@@ -0,0 +1,209 @@
#ifndef PROTO_WIREGUARD_H
#define PROTO_WIREGUARD_H
#include <sodium.h>
#define WG_IPC_POSTFIX "WIREGUARD"
#define WG_CIPHER "ChaCha20-Poly1305"
#define WG_CONSTRUCTION "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
#define WG_IDENTIFIER "WireGuard v1 zx2c4 Jason@zx2c4.com"
#define WG_LABEL_COOKIE "cookie--"
#define WG_LABEL_MAC1 "mac1----"
#define WG_MAX_INITIATIONS_PER_SECOND 50
#define WG_KEEPALIVE_TIMEOUT 10000 // 10 seconds
#define WG_INITIATION_GIVEUP 30000 // 30 seconds
#define WG_REJECT_AFTER_TIME 180000 // 180 seconds
#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - 16 - 1)
#define WG_KEY_SIZE crypto_aead_chacha20poly1305_ietf_KEYBYTES
#define WG_IV_SIZE crypto_aead_chacha20poly1305_ietf_NPUBBYTES
#define WG_TAG_SIZE crypto_aead_chacha20poly1305_ietf_ABYTES
#define WG_COOKIE_IV_SIZE crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
#define WG_COOKIE_TAG_SIZE crypto_aead_xchacha20poly1305_ietf_ABYTES
#define WG_HASH_SIZE 32
#define WG_BLOCK_SIZE 16
#define WG_COOKIE_SIZE 16
#define WG_TIMESTAMP_SIZE (sizeof(UINT64) + sizeof(UINT))
#define WG_KEY_BASE64_SIZE (sodium_base64_ENCODED_LEN(WG_KEY_SIZE, sodium_base64_VARIANT_ORIGINAL))
#define WG_AEAD_SIZE(plain_size) (plain_size + WG_TAG_SIZE)
#define WG_PLAIN_SIZE(aead_size) (aead_size - WG_TAG_SIZE)
// RFC 6479
#define WG_REPLAY_WINDOW_SIZE 1024
#define WG_REPLAY_BITMAP_SIZE (WG_REPLAY_WINDOW_SIZE / (sizeof(int) * 8))
#define WG_REPLAY_BITMAP_INDEX_MASK (WG_REPLAY_BITMAP_SIZE - 1)
#define WG_REPLAY_REDUNDANT_BIT_SHIFTS 5
#define WG_REPLAY_REDUNDANT_BITS (1 << WG_REPLAY_REDUNDANT_BIT_SHIFTS)
#define WG_REPLAY_BITMAP_LOC_MASK (WG_REPLAY_REDUNDANT_BITS - 1)
typedef enum WG_MSG_TYPE
{
WG_MSG_INVALID = 0,
WG_MSG_HANDSHAKE_INIT,
WG_MSG_HANDSHAKE_REPLY,
WG_MSG_HANDSHAKE_COOKIE,
WG_MSG_TRANSPORT_DATA
} WG_MSG_TYPE;
typedef enum WG_KEYPAIR_STATE
{
WG_KEYPAIR_INVALID = 0,
WG_KEYPAIR_INITIATED,
WG_KEYPAIR_CONFIRMED
} WG_KEYPAIR_STATE;
typedef struct WG_HEADER
{
BYTE Type;
BYTE Reserved[3];
} WG_HEADER;
typedef struct WG_COMMON
{
WG_HEADER Header;
UINT Index;
} WG_COMMON;
typedef struct WG_MACS
{
BYTE Mac1[WG_COOKIE_SIZE];
BYTE Mac2[WG_COOKIE_SIZE];
} WG_MACS;
typedef struct WG_HANDSHAKE_INIT
{
WG_HEADER Header;
UINT SenderIndex;
BYTE UnencryptedEphemeral[WG_KEY_SIZE];
BYTE EncryptedStatic[WG_AEAD_SIZE(WG_KEY_SIZE)];
BYTE EncryptedTimestamp[WG_AEAD_SIZE(WG_TIMESTAMP_SIZE)];
WG_MACS Macs;
} WG_HANDSHAKE_INIT;
typedef struct WG_HANDSHAKE_REPLY
{
WG_HEADER Header;
UINT SenderIndex;
UINT ReceiverIndex;
BYTE UnencryptedEphemeral[WG_KEY_SIZE];
BYTE EncryptedNothing[WG_AEAD_SIZE(0)];
WG_MACS Macs;
} WG_HANDSHAKE_REPLY;
typedef struct WG_COOKIE_REPLY
{
WG_HEADER Header;
UINT ReceiverIndex;
BYTE Nonce[WG_COOKIE_IV_SIZE];
BYTE EncryptedCookie[WG_COOKIE_SIZE + WG_COOKIE_TAG_SIZE];
} WG_COOKIE_REPLY;
typedef struct WG_TRANSPORT_DATA
{
WG_HEADER Header;
UINT ReceiverIndex;
UINT64 Counter;
BYTE EncapsulatedPacket[];
} WG_TRANSPORT_DATA;
typedef struct WG_KEYPAIR
{
WG_KEYPAIR_STATE State;
UINT64 CreationTime;
UINT IndexLocal;
UINT IndexRemote;
UINT64 CounterLocal;
UINT64 CounterRemote;
BYTE KeyLocal[WG_KEY_SIZE];
BYTE KeyRemote[WG_KEY_SIZE];
UINT64 ReplayWindow[WG_REPLAY_WINDOW_SIZE];
} WG_KEYPAIR;
typedef struct WG_KEYPAIRS
{
WG_KEYPAIR *Current;
WG_KEYPAIR *Next;
WG_KEYPAIR *Previous;
} WG_KEYPAIRS;
typedef struct WG_SESSION
{
WG_KEYPAIRS Keypairs;
IPC *IPC;
IP IPLocal;
IP IPRemote;
USHORT PortLocal;
USHORT PortRemote;
UINT64 LastInitiationReceived;
UINT64 LastDataReceived;
UINT64 LastDataSent;
BYTE StaticRemote[WG_KEY_SIZE];
BYTE LastTimestamp[WG_TIMESTAMP_SIZE];
BYTE Hash[WG_HASH_SIZE];
BYTE ChainingKey[WG_HASH_SIZE];
BYTE PrecomputedStaticStatic[WG_KEY_SIZE];
} WG_SESSION;
typedef struct WG_SERVER
{
UINT64 Now;
UINT64 CreationTime;
WG_SESSION Session;
CEDAR *Cedar;
SOCK_EVENT *SockEvent;
INTERRUPT_MANAGER *InterruptManager;
BYTE PresharedKey[WG_KEY_SIZE];
BYTE StaticPublic[WG_KEY_SIZE];
BYTE StaticPrivate[WG_KEY_SIZE];
BYTE HandshakeInitHash[WG_HASH_SIZE];
BYTE HandshakeInitChainingKey[WG_HASH_SIZE];
} WG_SERVER;
const PROTO_IMPL *WgsGetProtoImpl();
const char *WgsName();
const PROTO_OPTION *WgsOptions();
char *WgsOptionStringValue(const char *name);
bool WgsInit(void **param, const LIST *options, CEDAR *cedar, INTERRUPT_MANAGER *im, SOCK_EVENT *se, const char *cipher, const char *hostname);
void WgsFree(void *param);
bool WgsIsPacketForMe(const PROTO_MODE mode, const void *data, const UINT size);
bool WgsProcessDatagrams(void *param, LIST *in, LIST *out);
void WgsLog(const WG_SERVER *server, const char *name, ...);
WG_MSG_TYPE WgsDetectMessageType(const void *data, const UINT size);
UINT WgsMSS(const WG_SESSION *session);
IPC *WgsIPCNew(WG_SERVER *server);
WG_KEYPAIR *WgsProcessHandshakeInit(WG_SERVER *server, const WG_HANDSHAKE_INIT *init, BYTE *ephemeral_remote);
WG_HANDSHAKE_REPLY *WgsCreateHandshakeReply(WG_SERVER *server, WG_KEYPAIR *keypair, const BYTE *ephemeral_remote);
bool WgsProcessTransportData(WG_SERVER *server, WG_TRANSPORT_DATA *data, const UINT size);
WG_TRANSPORT_DATA *WgsCreateTransportData(WG_SERVER *server, const void *data, const UINT size, UINT *final_size);
bool WgsIsInReplayWindow(const WG_KEYPAIR *keypair, const UINT64 counter);
void WgsUpdateReplayWindow(WG_KEYPAIR *keypair, const UINT64 counter);
UINT WgsEncryptData(void *key, const UINT64 counter, void *dst, const void *src, const UINT src_size);
UINT WgsDecryptData(void *key, const UINT64 counter, void *dst, const void *src, const UINT src_size);
bool WgsEncryptWithHash(void *dst, const void *src, const UINT src_size, BYTE *hash, const BYTE *key);
bool WgsDecryptWithHash(void *dst, const void *src, const UINT src_size, BYTE *hash, const BYTE *key);
void WgsEphemeral(BYTE *ephemeral_dst, const BYTE *ephemeral_src, BYTE *chaining_key, BYTE *hash);
void WgsHKDF(BYTE *dst_1, BYTE *dst_2, BYTE *dst_3, const BYTE *data, const UINT data_size, const BYTE *chaining_key);
void WgsMixHash(void *dst, const void *src, const UINT size);
bool WgsMixDh(BYTE *chaining_key, BYTE *key, const BYTE *priv, const BYTE *pub);
#endif
+88 -34
View File
@@ -1330,12 +1330,45 @@ bool ServerAccept(CONNECTION *c)
goto CLEANUP;
}
// Login
if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
// Get authentication method and initiate login process
authtype = GetAuthTypeFromPack(p);
if (authtype == AUTHTYPE_WIREGUARD_KEY)
{
WGK *wgk, tmp;
bool ok = false;
if (PackGetStr(p, "key", tmp.Key, sizeof(tmp.Key)) == false)
{
FreePack(p);
c->Err = ERR_PROTOCOL_ERROR;
error_detail = "GetWireGuardKeyFromPack";
goto CLEANUP;
}
LockList(c->Cedar->WgkList);
{
wgk = Search(c->Cedar->WgkList, &tmp);
if (wgk != NULL)
{
ok = true;
StrCpy(hubname, sizeof(hubname), wgk->Hub);
StrCpy(username, sizeof(username), wgk->User);
StrCpy(node.HubName, sizeof(node.HubName), hubname);
}
}
UnlockList(c->Cedar->WgkList);
if (ok == false)
{
FreePack(p);
c->Err = ERR_AUTH_FAILED;
SLog(c->Cedar, "LS_WG_KEY_NOT_FOUND", c->Name, hubname);
error_detail = "ERR_AUTH_FAILED";
goto CLEANUP;
}
}
else if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
{
// Protocol error
FreePack(p);
c->Err = ERR_PROTOCOL_ERROR;
error_detail = "GetHubnameAndUsernameFromPack";
@@ -1345,9 +1378,7 @@ bool ServerAccept(CONNECTION *c)
if (farm_member)
{
bool ok = false;
UINT authtype;
authtype = GetAuthTypeFromPack(p);
if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
authtype == AUTHTYPE_PASSWORD)
{
@@ -1600,9 +1631,6 @@ bool ServerAccept(CONNECTION *c)
PackGetData(p, "unique_id", unique);
}
// Get the authentication method
authtype = GetAuthTypeFromPack(p);
if (1)
{
// Log
@@ -1622,12 +1650,15 @@ bool ServerAccept(CONNECTION *c)
case CLIENT_AUTHTYPE_CERT:
authtype_str = _UU("LH_AUTH_CERT");
break;
case AUTHTYPE_TICKET:
authtype_str = _UU("LH_AUTH_TICKET");
case AUTHTYPE_WIREGUARD_KEY:
authtype_str = _UU("LH_AUTH_WIREGUARD_KEY");
break;
case AUTHTYPE_OPENVPN_CERT:
authtype_str = _UU("LH_AUTH_OPENVPN_CERT");
break;
case AUTHTYPE_TICKET:
authtype_str = _UU("LH_AUTH_TICKET");
break;
}
IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
@@ -1640,7 +1671,6 @@ bool ServerAccept(CONNECTION *c)
// Attempt an anonymous authentication first
auth_ret = SamAuthUserByAnonymous(hub, username);
if (auth_ret)
{
if (c->IsInProc)
@@ -1734,8 +1764,6 @@ bool ServerAccept(CONNECTION *c)
if (auth_ret)
{
// User authentication success by anonymous authentication
HLog(hub, "LH_AUTH_OK", c->Name, username);
is_empty_password = true;
}
}
@@ -1961,6 +1989,24 @@ bool ServerAccept(CONNECTION *c)
}
break;
case AUTHTYPE_WIREGUARD_KEY:
// We already retrieved the hubname and username associated with the key.
// Now we only have to verify that the user effectively exists.
if (c->IsInProc)
{
auth_ret = SamIsUser(hub, username);
}
else
{
// WireGuard public key authentication cannot be used directly by external clients.
Unlock(hub->lock);
ReleaseHub(hub);
FreePack(p);
c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
goto CLEANUP;
}
break;
case AUTHTYPE_OPENVPN_CERT:
// For OpenVPN; mostly same as CLIENT_AUTHTYPE_CERT, but without
// signature verification, because it was already performed during TLS handshake.
@@ -2014,25 +2060,14 @@ bool ServerAccept(CONNECTION *c)
error_detail = "ERR_AUTHTYPE_NOT_SUPPORTED";
goto CLEANUP;
}
if (auth_ret == false)
{
// Get client IP to feed tools such as Fail2Ban
char ip[64];
IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
// Authentication failure
HLog(hub, "LH_AUTH_NG", c->Name, username, ip);
}
else
{
// Authentication success
HLog(hub, "LH_AUTH_OK", c->Name, username);
}
}
if (auth_ret == false)
{
// Authentication failure
char ip[64];
IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
HLog(hub, "LH_AUTH_NG", c->Name, username, ip);
Unlock(hub->lock);
ReleaseHub(hub);
FreePack(p);
@@ -2046,13 +2081,12 @@ bool ServerAccept(CONNECTION *c)
}
else
{
if(is_empty_password)
if (is_empty_password)
{
SOCK *s = c->FirstSock;
const SOCK *s = c->FirstSock;
if (s != NULL && s->RemoteIP.addr[0] != 127)
{
if(StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 ||
GetHubAdminOption(hub, "deny_empty_password") != 0)
if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 || GetHubAdminOption(hub, "deny_empty_password") != 0)
{
// When the password is empty, remote connection is not acceptable
HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
@@ -2066,6 +2100,8 @@ bool ServerAccept(CONNECTION *c)
}
}
}
HLog(hub, "LH_AUTH_OK", c->Name, username);
}
policy = NULL;
@@ -6592,6 +6628,24 @@ PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_pass
return p;
}
// Generate a packet of WireGuard key login
PACK *PackLoginWithWireGuardKey(char *key)
{
PACK *p;
// Validate arguments
if (key == NULL)
{
return NULL;
}
p = NewPack();
PackAddStr(p, "method", "login");
PackAddInt(p, "authtype", AUTHTYPE_WIREGUARD_KEY);
PackAddStr(p, "key", key);
return p;
}
// Generate a packet of OpenVPN certificate login
PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x)
{
+1
View File
@@ -134,6 +134,7 @@ PACK *PackLoginWithAnonymous(char *hubname, char *username);
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size);
PACK *PackLoginWithWireGuardKey(char *key);
PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x);
bool GetMethodFromPack(PACK *p, char *method, UINT size);
bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
+78 -5
View File
@@ -402,6 +402,11 @@ void SiCheckDeadLockMain(SERVER *s, UINT timeout)
CheckDeadLock(cedar->CaList->lock, timeout, "cedar->CaList->lock");
}
if (cedar->WgkList != NULL)
{
CheckDeadLock(cedar->WgkList->lock, timeout, "cedar->WgkList->lock");
}
if (cedar->TrafficLock != NULL)
{
CheckDeadLock(cedar->TrafficLock, timeout, "cedar->TrafficLock");
@@ -2279,6 +2284,8 @@ void SiSetDefaultHubOption(HUB_OPTION *o)
return;
}
o->DefaultGateway = SetIP32(192, 168, 30, 1);
o->DefaultSubnet = SetIP32(255, 255, 255, 0);
o->MaxSession = 0;
o->VlanTypeId = MAC_PROTO_TAGVLAN;
o->NoIPv6DefaultRouterInRAWhenIPv6 = true;
@@ -2675,16 +2682,13 @@ bool SiIsAzureSupported(SERVER *s)
// Read the server settings from the CFG
bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
{
FOLDER *f1, *f2, *f3, *f4, *f5, *f6, *f7, *f8, *f;
FOLDER *f1, *f2, *f3, *f4, *f5, *f6, *f7, *f8, *f9;
// Validate arguments
if (s == NULL || root == NULL)
{
return false;
}
f = NULL;
f1 = CfgGetFolder(root, "ServerConfiguration");
f2 = CfgGetFolder(root, "VirtualHUB");
f3 = CfgGetFolder(root, "ListenerList");
@@ -2693,6 +2697,7 @@ bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
f6 = CfgGetFolder(root, "LicenseManager");
f7 = CfgGetFolder(root, "IPsec");
f8 = CfgGetFolder(root, "DDnsClient");
f9 = CfgGetFolder(root, "WireGuardKeyList");
if (f1 == NULL)
{
@@ -2734,6 +2739,30 @@ bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
if (s->ServerType != SERVER_TYPE_FARM_MEMBER)
{
TOKEN_LIST *t = CfgEnumFolderToTokenList(f9);
if (t != NULL)
{
LockList(s->Cedar->WgkList);
{
UINT i;
for (i = 0; i < t->NumTokens; ++i)
{
const char *name = t->Token[i];
FOLDER *f = CfgGetFolder(f9, name);
if (f != NULL)
{
WGK *wgk = Malloc(sizeof(WGK));
StrCpy(wgk->Key, sizeof(wgk->Key), name);
CfgGetStr(f, "Hub", wgk->Hub, sizeof(wgk->Hub));
CfgGetStr(f, "User", wgk->User, sizeof(wgk->User));
Add(s->Cedar->WgkList, wgk);
}
}
}
UnlockList(s->Cedar->WgkList);
FreeToken(t);
}
SiLoadHubs(s, f2);
}
@@ -3100,9 +3129,28 @@ FOLDER *SiWriteConfigurationToCfg(SERVER *s)
SiWriteServerCfg(CfgCreateFolder(root, "ServerConfiguration"), s);
if (s->UpdatedServerType != SERVER_TYPE_FARM_MEMBER)
{
FOLDER *f = CfgCreateFolder(root, "WireGuardKeyList");
if (f != NULL)
{
LockList(s->Cedar->WgkList);
{
UINT i;
for (i = 0; i < LIST_NUM(s->Cedar->WgkList); ++i)
{
WGK *wgk = LIST_DATA(s->Cedar->WgkList, i);
FOLDER *ff = CfgCreateFolder(f, wgk->Key);
if (ff != NULL)
{
CfgAddStr(ff, "Hub", wgk->Hub);
CfgAddStr(ff, "User", wgk->User);
}
}
}
UnlockList(s->Cedar->WgkList);
}
SiWriteHubs(CfgCreateFolder(root, "VirtualHUB"), s);
}
@@ -3757,6 +3805,8 @@ void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
return;
}
o->DefaultGateway = CfgGetIp32(f, "DefaultGateway");
o->DefaultSubnet = CfgGetIp32(f, "DefaultSubnet");
o->MaxSession = CfgGetInt(f, "MaxSession");
o->NoArpPolling = CfgGetBool(f, "NoArpPolling");
o->NoIPv6AddrPolling = CfgGetBool(f, "NoIPv6AddrPolling");
@@ -3904,6 +3954,8 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
return;
}
CfgAddIp32(f, "DefaultGateway", o->DefaultGateway);
CfgAddIp32(f, "DefaultSubnet", o->DefaultSubnet);
CfgAddInt(f, "MaxSession", o->MaxSession);
CfgAddBool(f, "NoArpPolling", o->NoArpPolling);
CfgAddBool(f, "NoIPv6AddrPolling", o->NoIPv6AddrPolling);
@@ -10295,6 +10347,27 @@ int CompareHubList(void *p1, void *p2)
return StrCmpi(h1->Name, h2->Name);
}
// Search in WireGuard key list
int CompareWgk(void *p1, void *p2)
{
WGK *wgk_1, *wgk_2;
if (p1 == NULL || p2 == NULL)
{
return (p1 == NULL && p2 == NULL ? 0 : (p1 == NULL ? -1 : 1));
}
wgk_1 = *(WGK **)p1;
wgk_2 = *(WGK **)p2;
if (wgk_1 == NULL || wgk_2 == NULL)
{
return (wgk_1 == NULL && wgk_2 == NULL ? 0 : (wgk_1 == NULL ? -1 : 1));
}
return StrCmp(wgk_1->Key, wgk_2->Key);
}
// Connection thread to the controller
void SiConnectToControllerThread(THREAD *thread, void *param)
{
+10
View File
@@ -150,6 +150,14 @@ struct OPENVPN_SSTP_CONFIG
bool EnableSSTP; // SSTP is enabled
};
// WireGuard key structure
struct WGK
{
char Key[WG_KEY_BASE64_SIZE];
char Hub[MAX_HUBNAME_LEN + 1];
char User[MAX_USERNAME_LEN + 1];
};
// Server object
struct SERVER
{
@@ -631,6 +639,8 @@ void SiUpdateCurrentRegion(CEDAR *c, char *region, bool force_update);
void SiGetCurrentRegion(CEDAR *c, char *region, UINT region_size);
bool SiIsEnterpriseFunctionsRestrictedOnOpenSource(CEDAR *c);
int CompareWgk(void *p1, void *p2);
#endif // SERVER_H