1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-12-25 17:49:52 +03:00

Merge pull request #1751 from Evengard/eap-tls-fixups

TLS 1.3 for EAP-TLS, user search by certificate CN
This commit is contained in:
Ilya Shipitsin 2023-02-01 09:47:38 +06:00 committed by GitHub
commit 11828be9e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 328 additions and 127 deletions

View File

@ -897,6 +897,35 @@ USER *AcGetUser(HUB *h, char *name)
return u;
}
USER* AcGetUserByCert(HUB *h, X *cert)
{
int i;
if (cert == NULL)
{
return NULL;
}
for (i = 0; i < LIST_NUM(h->HubDb->UserList); i++)
{
USER* u = LIST_DATA(h->HubDb->UserList, i);
if (u->AuthType == AUTHTYPE_USERCERT)
{
X* ucert = ((AUTHUSERCERT*)u->AuthData)->UserX;
if (ucert != NULL)
{
if (CompareX(cert, ucert))
{
AddRef(u->ref);
return u;
}
}
}
}
return NULL;
}
// Delete the user
bool AcDeleteUser(HUB *h, char *name)
{

View File

@ -177,6 +177,7 @@ void FreeAuthData(UINT authtype, void *authdata);
bool AcAddUser(HUB *h, USER *u);
bool AcAddGroup(HUB *h, USERGROUP *g);
USER *AcGetUser(HUB *h, char *name);
USER* AcGetUserByCert(HUB* h, X *cert);
USERGROUP *AcGetGroup(HUB *h, char *name);
bool AcIsUser(HUB *h, char *name);
bool AcIsGroup(HUB *h, char *name);

View File

@ -616,6 +616,7 @@ void DataToHubOptionStruct(HUB_OPTION *o, RPC_ADMIN_OPTION *ao)
GetHubAdminOptionDataAndSet(ao, "NoPhysicalIPOnPacketLog", o->NoPhysicalIPOnPacketLog);
GetHubAdminOptionDataAndSet(ao, "UseHubNameAsDhcpUserClassOption", o->UseHubNameAsDhcpUserClassOption);
GetHubAdminOptionDataAndSet(ao, "UseHubNameAsRadiusNasId", o->UseHubNameAsRadiusNasId);
GetHubAdminOptionDataAndSet(ao, "AllowEapMatchUserByCert", o->AllowEapMatchUserByCert);
}
// Convert the contents of the HUB_OPTION to data
@ -690,6 +691,7 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
Add(aol, NewAdminOption("NoPhysicalIPOnPacketLog", o->NoPhysicalIPOnPacketLog));
Add(aol, NewAdminOption("UseHubNameAsDhcpUserClassOption", o->UseHubNameAsDhcpUserClassOption));
Add(aol, NewAdminOption("UseHubNameAsRadiusNasId", o->UseHubNameAsRadiusNasId));
Add(aol, NewAdminOption("AllowEapMatchUserByCert", o->AllowEapMatchUserByCert));
Zero(ao, sizeof(RPC_ADMIN_OPTION));

View File

@ -182,6 +182,7 @@ struct HUB_OPTION
bool NoPhysicalIPOnPacketLog; // Disable saving physical IP address on the packet log
bool UseHubNameAsDhcpUserClassOption; // Add HubName to DHCP request as User-Class option
bool UseHubNameAsRadiusNasId; // Add HubName to Radius request as NAS-Identifier attrioption
bool AllowEapMatchUserByCert; // Allow matching EAP Identity with user certificate CNs
};
// MAC table entry

View File

@ -13,7 +13,6 @@
#include "Hub.h"
#include "IPC.h"
#include "Logging.h"
#include "Proto_IPsec.h"
#include "Radius.h"
#include "Server.h"
@ -599,6 +598,9 @@ THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_
p->AuthProtocol = PPP_UNSPECIFIED;
p->MsChapV2_ErrorCode = 691;
p->EapClient = NULL;
Zero(&p->Eap_Identity, sizeof(p->Eap_Identity));
p->Eap_TlsCtx.DisableTls13 = false;
p->Eap_TlsCtx.Tls13SessionTicketsCount = 2; // Default count as per hardcoded in OpenSSL
p->DataTimeout = PPP_DATA_TIMEOUT;
p->PacketRecvTimeout = PPP_PACKET_RECV_TIMEOUT;
@ -1263,12 +1265,12 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
UINT64 offer = 0;
PPP_LCP *c;
UCHAR ms_chap_v2_code[3];
ETHERIP_ID d;
char username[MAX_SIZE];
char hubname[MAX_SIZE];
HUB *hub;
bool found = false;
UINT authtype;
UCHAR eapidentitypkt[MAX_SIZE] = { 0 };
WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP);
ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2;
@ -1277,24 +1279,23 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
{
case PPP_EAP_TYPE_IDENTITY:
// Parse username
Copy(p->Eap_Identity, eap_packet->Data, MIN(MAX_SIZE, eap_datasize));
Zero(&d, sizeof(d));
PPPParseUsername(p->Cedar, p->Eap_Identity, &d);
StrCpy(username, sizeof(username), d.UserName);
StrCpy(hubname, sizeof(hubname), d.HubName);
Debug("EAP: username=%s, hubname=%s\n", username, hubname);
Copy(eapidentitypkt, eap_packet->Data, MIN(MAX_SIZE, eap_datasize));
Zero(&p->Eap_Identity, sizeof(p->Eap_Identity));
PPPParseUsername(p->Cedar, eapidentitypkt, &p->Eap_Identity);
Debug("EAP: username=%s, hubname=%s\n", p->Eap_Identity.UserName, p->Eap_Identity.HubName);
// Locate user
LockHubList(p->Cedar);
{
hub = GetHub(p->Cedar, hubname);
hub = GetHub(p->Cedar, p->Eap_Identity.HubName);
}
UnlockHubList(p->Cedar);
if (hub != NULL)
{
AcLock(hub);
{
USER *user = AcGetUser(hub, username);
USER *user = AcGetUser(hub, p->Eap_Identity.UserName);
if (user == NULL)
{
user = AcGetUser(hub, "*");
@ -1305,12 +1306,18 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
authtype = user->AuthType;
ReleaseUser(user);
}
else if (hub->Option->AllowEapMatchUserByCert == true)
{
authtype = AUTHTYPE_USERCERT;
Zero(p->Eap_Identity.UserName, sizeof(p->Eap_Identity.UserName));
p->Eap_MatchUserByCert = true;
}
}
AcUnlock(hub);
ReleaseHub(hub);
}
if (found == false)
if (found == false && p->Eap_MatchUserByCert == false)
{
// User not found, fail immediately
PPP_PACKET *pack = ZeroMalloc(sizeof(PPP_PACKET));
@ -1375,7 +1382,7 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
// Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here...
break;
case PPP_EAP_TYPE_NAK:
if (p->Eap_Protocol == PPP_EAP_TYPE_TLS)
if (p->Eap_Protocol == PPP_EAP_TYPE_TLS && p->Eap_MatchUserByCert == false)
{
// Propose EAP-MSCHAPv2
p->Eap_Protocol = PPP_EAP_TYPE_MSCHAPV2;
@ -3410,7 +3417,7 @@ bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip)
}
// EAP packet utilities
bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSize)
bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapSize)
{
UCHAR *dataBuffer;
UINT dataSize;
@ -3420,8 +3427,8 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
PPP_EAP *eap;
UCHAR flags = PPP_EAP_TLS_FLAG_NONE;
UINT sizeLeft = 0;
Debug("Got EAP-TLS size=%i\n", eapTlsSize);
if (eapTlsSize == 1)
Debug("Got EAP-TLS size=%i\n", eapSize);
if (eapSize == 1 && eap_packet->Tls.Flags == PPP_EAP_TLS_FLAG_NONE)
{
// This is an EAP-TLS message ACK
if (p->Eap_TlsCtx.CachedBufferSend != NULL)
@ -3459,116 +3466,47 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
p->Eap_TlsCtx.CachedBufferSendPntr = NULL;
}
}
else
else if (p->AuthOk == true && p->Ipc != NULL && p->PPPStatus == PPP_STATUS_AUTHENTICATING)
{
// It probably should be the final ACK on closed SSL pipe
SyncSslPipe(p->Eap_TlsCtx.SslPipe);
if (p->Eap_TlsCtx.ClientCert.X != NULL)
// The handshake terminated and we received the final ACK, the auth is successful
// Just send an EAP-Success
PPP_PACKET* pack;
UINT identificator = p->Eap_PacketId;
PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS);
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
IPC *ipc;
ETHERIP_ID d;
UINT error_code;
/*if (!p->Eap_TlsCtx.SslPipe->IsDisconnected)
{
dataSize = FifoSize(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo);
p->Eap_PacketId = p->NextId++;
lcp = BuildEAPTlsRequest(p->Eap_PacketId, dataSize, 0);
eap = lcp->Data;
ReadFifo(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo, &(eap->Tls.TlsDataWithoutLength), dataSize);
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp))
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags);
return true;
}*/
PPPParseUsername(p->Cedar, p->Eap_Identity, &d);
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);
if (ipc != NULL)
{
PPP_PACKET *pack;
UINT identificator = p->Eap_PacketId;
p->Ipc = ipc;
PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS);
// Setting user timeouts
p->PacketRecvTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000 * 3 / 4; // setting to 3/4 of the user timeout
p->DataTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000;
if (p->TubeRecv != NULL)
{
p->TubeRecv->DataTimeout = p->DataTimeout;
}
p->UserConnectionTimeout = (UINT64)p->Ipc->Policy->AutoDisconnect * 1000;
p->UserConnectionTick = Tick64();
// Just send an EAP-Success
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i SUCCESS\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
return true;
}
else
{
PPP_PACKET *pack;
UINT identificator = p->Eap_PacketId;
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
return false;
}
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
else
return true;
}
else if (p->Eap_TlsCtx.ClientCert.X == NULL)
{
// Some clients needs a little help it seems - namely VPN Client Pro on Android
flags |= PPP_EAP_TLS_FLAG_SSLSTARTED;
p->Eap_PacketId = p->NextId++;
lcp = BuildEAPTlsRequest(p->Eap_PacketId, 0, flags);
PPPSetStatus(p, PPP_STATUS_AUTHENTICATING);
if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp) == false)
{
// Some clients needs a little help it seems - namely VPN Client Pro on Android
flags |= PPP_EAP_TLS_FLAG_SSLSTARTED;
p->Eap_PacketId = p->NextId++;
lcp = BuildEAPTlsRequest(p->Eap_PacketId, 0, flags);
PPPSetStatus(p, PPP_STATUS_AUTHENTICATING);
if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
Debug("Sent EAP-TLS size=%i\n", lcp->DataSize);
return true;
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
Debug("Sent EAP-TLS size=%i\n", lcp->DataSize);
}
return true;
}
dataBuffer = eap_packet->Tls.TlsDataWithoutLength;
dataSize = eapTlsSize - 1;
dataSize = eapSize - 1;
if (eap_packet->Tls.Flags & PPP_EAP_TLS_FLAG_TLS_LENGTH)
{
dataBuffer = eap_packet->Tls.TlsDataWithLength.Data;
@ -3593,7 +3531,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
if (p->Eap_TlsCtx.SslPipe == NULL)
{
p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT);
p->Eap_TlsCtx.SslPipe = NewSslPipeEx2(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Cedar->ServerChain, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.ClientCert));
p->Eap_TlsCtx.SslPipe = NewSslPipeEx3(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Cedar->ServerChain, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.ClientCert), p->Eap_TlsCtx.Tls13SessionTicketsCount, p->Eap_TlsCtx.DisableTls13);
}
// If the current frame is fragmented, or it is a possible last of a fragmented series, bufferize it
@ -3640,9 +3578,11 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
return false;
}
Debug("Sent EAP-TLS size=%i\n", lcp->DataSize);
return true;
}
else
{
bool syncOk;
/*Debug("=======RECV EAP-TLS FIFO DUMP=======\n");
for (i = 0; i < dataSize; i++)
{
@ -3651,7 +3591,8 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
}
Debug("\n=======RECV EAP-TLS PACKET FIFO END=======\n");*/
WriteFifo(p->Eap_TlsCtx.SslPipe->RawIn->SendFifo, dataBuffer, dataSize);
SyncSslPipe(p->Eap_TlsCtx.SslPipe);
syncOk = SyncSslPipe(p->Eap_TlsCtx.SslPipe);
// Delete the cached buffer after we fed it into the pipe
if (p->Eap_TlsCtx.CachedBufferRecv != NULL)
{
@ -3660,6 +3601,153 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
p->Eap_TlsCtx.CachedBufferRecvPntr = NULL;
}
// Special case - we attempt to restart downgrading TLS settings
if (!syncOk && (p->Eap_TlsCtx.DisableTls13 == false || p->Eap_TlsCtx.Tls13SessionTicketsCount == 0))
{
// If we authenticated earlier, deauthenticate back
p->DataTimeout = PPP_DATA_TIMEOUT;
p->PacketRecvTimeout = PPP_PACKET_RECV_TIMEOUT;
p->UserConnectionTimeout = 0;
p->UserConnectionTick = 0;
if (p->Ipc != NULL)
{
FreeIPC(p->Ipc);
p->Ipc = NULL;
p->AuthOk = false;
}
FreeSslPipe(p->Eap_TlsCtx.SslPipe);
DhFree(p->Eap_TlsCtx.Dh);
p->Eap_TlsCtx.SslPipe = NULL;
p->Eap_TlsCtx.Dh = NULL;
if (p->Eap_TlsCtx.Tls13SessionTicketsCount == 0)
{
p->Eap_TlsCtx.DisableTls13 = true;
}
else
{
p->Eap_TlsCtx.Tls13SessionTicketsCount = 0;
}
flags |= PPP_EAP_TLS_FLAG_SSLSTARTED;
p->Eap_PacketId = p->NextId++;
lcp = BuildEAPTlsRequest(p->Eap_PacketId, 0, flags);
if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
Debug("EAP-TLS: Restarting the handshake! Tls13SessionTicketsCount = %d, DisableTls13 = %d\n", p->Eap_TlsCtx.Tls13SessionTicketsCount, p->Eap_TlsCtx.DisableTls13);
Debug("Sent EAP-TLS size=%i\n", lcp->DataSize);
return false;
}
// If on the server we have enough data to authenticate, let's do this before we continue with the handshake
// Check if we received the client certificate and the handshake is finished
if (p->Eap_TlsCtx.ClientCert.X != NULL && p->Ipc == NULL)
{
IPC* ipc;
UINT error_code;
if (p->Eap_MatchUserByCert)
{
HUB* hub = GetHub(p->Cedar, p->Eap_Identity.HubName);
bool found = false;
if (hub != NULL)
{
USER* user = AcGetUserByCert(hub, p->Eap_TlsCtx.ClientCert.X);
if (user != NULL)
{
StrCpy(p->Eap_Identity.UserName, sizeof(p->Eap_Identity.UserName), user->Name);
found = true;
ReleaseUser(user);
}
ReleaseHub(hub);
}
if (found == false)
{
PPP_PACKET* pack;
UINT identificator = p->Eap_PacketId;
ReleaseHub(hub);
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
return false;
}
}
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, p->Eap_Identity.HubName, p->Eap_Identity.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);
// We use the SAM authentication here, because the handshake can still fail at this point
if (ipc != NULL)
{
// Setting user timeouts
p->Ipc = ipc;
p->PacketRecvTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000 * 3 / 4; // setting to 3/4 of the user timeout
p->DataTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000;
if (p->TubeRecv != NULL)
{
p->TubeRecv->DataTimeout = p->DataTimeout;
}
p->UserConnectionTimeout = (UINT64)p->Ipc->Policy->AutoDisconnect * 1000;
p->UserConnectionTick = Tick64();
p->AuthOk = true;
if (p->Eap_TlsCtx.SslPipe->SslVersion == TLS1_3_VERSION)
{
// Before starting IPC and sending an EAP-Success in case of TLS 1.3 we need to send a 0x00 data packet as per RFC 9190
char zeroPacket[1] = { 0 };
WriteFifo(p->Eap_TlsCtx.SslPipe->SslInOut->SendFifo, zeroPacket, sizeof(zeroPacket));
if (!SyncSslPipe(p->Eap_TlsCtx.SslPipe))
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
}
}
else
{
PPP_PACKET* pack;
UINT identificator = p->Eap_PacketId;
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
return false;
}
}
// We continue the TLS handshake
if (p->Eap_TlsCtx.SslPipe->IsDisconnected == false)
{
dataSize = FifoSize(p->Eap_TlsCtx.SslPipe->RawOut->RecvFifo);
@ -3691,8 +3779,9 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
return false;
}
Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags);
return true;
}
else
else if (dataSize > 0 || p->Eap_TlsCtx.ClientCert.X == NULL)
{
p->Eap_PacketId = p->NextId++;
lcp = BuildEAPTlsRequest(p->Eap_PacketId, dataSize, 0);
@ -3705,8 +3794,34 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
return false;
}
Debug("Sent EAP-TLS size=%i type=%i flag=%i\n", lcp->DataSize, eap->Type, eap->Tls.Flags);
return true;
}
}
// If we end up here, we got problems, send an EAP failure
if (p->Eap_TlsCtx.SslPipe->IsDisconnected)
{
PPP_PACKET* pack;
UINT identificator = p->Eap_PacketId;
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, identificator);
pack->Lcp = lcp;
Debug("Sent EAP-TLS size=%i FAILURE\n", lcp->DataSize);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
return false;
}
}
}
else

View File

@ -9,6 +9,7 @@
#define PROTO_PPP_H
#include "CedarType.h"
#include "Proto_IPsec.h"
#include "Mayaqua/TcpIp.h"
@ -229,6 +230,8 @@ struct PPP_EAP_TLS_CONTEXT
UCHAR *CachedBufferRecvPntr;
UCHAR *CachedBufferSend;
UCHAR *CachedBufferSendPntr;
bool DisableTls13;
int Tls13SessionTicketsCount;
};
// PPP request resend
@ -302,7 +305,8 @@ struct PPP_SESSION
// EAP contexts
UINT Eap_Protocol; // Current EAP Protocol used
UINT Eap_PacketId; // EAP Packet ID;
UCHAR Eap_Identity[MAX_SIZE]; // Received from client identity
ETHERIP_ID Eap_Identity; // Received from client identity
bool Eap_MatchUserByCert; // Attempt to match the user from it's certificate during EAP-TLS, ignoring the EAP-identification
PPP_EAP_TLS_CONTEXT Eap_TlsCtx; // Context information for EAP TLS. May be possibly reused for EAP TTLS?
LIST *SentReqPacketList; // Sent requests list
@ -387,7 +391,7 @@ bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify);
bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip);
bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify);
// EAP packet utilities
bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSize);
bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapSize);
PPP_LCP *BuildEAPPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize);
PPP_LCP *BuildEAPTlsPacketEx(UCHAR code, UCHAR id, UCHAR type, UINT datasize, UCHAR flags);
PPP_LCP *BuildEAPTlsRequest(UCHAR id, UINT datasize, UCHAR flags);

View File

@ -3932,6 +3932,7 @@ void SiLoadHubOptionCfg(FOLDER *f, HUB_OPTION *o)
o->NoPhysicalIPOnPacketLog = CfgGetBool(f, "NoPhysicalIPOnPacketLog");
o->UseHubNameAsDhcpUserClassOption = CfgGetBool(f, "UseHubNameAsDhcpUserClassOption");
o->UseHubNameAsRadiusNasId = CfgGetBool(f, "UseHubNameAsRadiusNasId");
o->AllowEapMatchUserByCert = CfgGetBool(f, "AllowEapMatchUserByCert");
// Enabled by default
if (CfgIsItem(f, "ManageOnlyPrivateIP"))
@ -4037,6 +4038,7 @@ void SiWriteHubOptionCfg(FOLDER *f, HUB_OPTION *o)
CfgAddBool(f, "DisableCorrectIpOffloadChecksum", o->DisableCorrectIpOffloadChecksum);
CfgAddBool(f, "UseHubNameAsDhcpUserClassOption", o->UseHubNameAsDhcpUserClassOption);
CfgAddBool(f, "UseHubNameAsRadiusNasId", o->UseHubNameAsRadiusNasId);
CfgAddBool(f, "AllowEapMatchUserByCert", o->AllowEapMatchUserByCert);
}
// Write the user
@ -7521,6 +7523,7 @@ void SiCalledUpdateHub(SERVER *s, PACK *p)
o.DisableCorrectIpOffloadChecksum = PackGetBool(p, "DisableCorrectIpOffloadChecksum");
o.UseHubNameAsDhcpUserClassOption = PackGetBool(p, "UseHubNameAsDhcpUserClassOption");
o.UseHubNameAsRadiusNasId = PackGetBool(p, "UseHubNameAsRadiusNasId");
o.AllowEapMatchUserByCert = PackGetBool(p, "AllowEapMatchUserByCert");
save_packet_log = PackGetInt(p, "SavePacketLog");
packet_log_switch_type = PackGetInt(p, "PacketLogSwitchType");
@ -9355,6 +9358,7 @@ void SiPackAddCreateHub(PACK *p, HUB *h)
PackAddData(p, "SecurePassword", h->SecurePassword, SHA1_SIZE);
PackAddBool(p, "UseHubNameAsDhcpUserClassOption", h->Option->UseHubNameAsDhcpUserClassOption);
PackAddBool(p, "UseHubNameAsRadiusNasId", h->Option->UseHubNameAsRadiusNasId);
PackAddBool(p, "AllowEapMatchUserByCert", h->Option->AllowEapMatchUserByCert);
SiAccessListToPack(p, h->AccessList);

View File

@ -22,8 +22,10 @@ include(CheckSymbolExists)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::SSL)
check_symbol_exists(EVP_PKEY_get_raw_public_key "openssl/evp.h" HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY)
check_symbol_exists(SSL_CTX_set_num_tickets "openssl/ssl.h" HAVE_SSL_CTX_SET_NUM_TICKETS)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
@ -32,6 +34,12 @@ if(NOT HAVE_EVP_PKEY_GET_RAW_PUBLIC_KEY)
message(FATAL_ERROR "Required EVP_PKEY_get_raw_public_key() not found in OpenSSL library!")
endif()
if (HAVE_SSL_CTX_SET_NUM_TICKETS)
add_compile_definitions(HAVE_SSL_CTX_SET_NUM_TICKETS)
endif()
find_package(ZLIB REQUIRED)
# Required because we include <openssl/opensslv.h> in Encrypt.h.

View File

@ -5713,7 +5713,13 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee
{
return NewSslPipeEx2(server_mode, x, k, NULL, dh, verify_peer, clientcert);
}
SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert)
SSL_PIPE* NewSslPipeEx2(bool server_mode, X* x, K* k, LIST* chain, DH_CTX* dh, bool verify_peer, struct SslClientCertInfo* clientcert)
{
return NewSslPipeEx3(server_mode, x, k, chain, dh, verify_peer, clientcert, 2, false); // 2 TLS 1.3 tickets is an OpenSSL default hardcoded in the library
}
SSL_PIPE *NewSslPipeEx3(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert, int tls13ticketscnt, bool disableTls13)
{
SSL_PIPE *s;
SSL *ssl;
@ -5723,10 +5729,6 @@ SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, b
{
if (server_mode)
{
#ifdef SSL_OP_NO_TLSv1_3
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); // For some reason pppd under linux doesn't like it
#endif
if (chain == NULL)
{
AddChainSslCertOnDirectory(ssl_ctx);
@ -5784,6 +5786,16 @@ SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, b
SSL_CTX_set_options(ssl_ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
}
#ifdef SSL_OP_NO_TLSv1_3
if (disableTls13)
{
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3);
}
#endif
#ifdef HAVE_SSL_CTX_SET_NUM_TICKETS
SSL_CTX_set_num_tickets(ssl_ctx, tls13ticketscnt);
#endif
ssl = SSL_new(ssl_ctx);
SSL_set_ex_data(ssl, GetSslClientCertIndex(), clientcert);
@ -5832,6 +5844,8 @@ SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, b
bool SyncSslPipe(SSL_PIPE *s)
{
UINT i;
SSL_SESSION* sess;
// Validate arguments
if (s == NULL || s->IsDisconnected)
{
@ -5862,6 +5876,8 @@ bool SyncSslPipe(SSL_PIPE *s)
}
}
s->SslVersion = SSL_version(s->ssl);
return true;
}
@ -15832,6 +15848,14 @@ DH *TmpDhCallback(SSL *ssl, int is_export, int keylength)
return ret;
}
// Log SSL keys
void keylog_cb_func(const SSL* ssl, const char* line)
{
Debug("SSL_KEYLOG_BEGIN\n");
Debug(line);
Debug("\nSSL_KEYLOG_END\n");
}
// Create the SSL_CTX
struct ssl_ctx_st *NewSSLCtx(bool server_mode)
{
@ -15868,6 +15892,8 @@ struct ssl_ctx_st *NewSSLCtx(bool server_mode)
SSL_CTX_set_ecdh_auto(ctx, 1);
#endif // SSL_CTX_set_ecdh_auto
SSL_CTX_set_keylog_callback(ctx, &keylog_cb_func);
return ctx;
}

View File

@ -11,6 +11,8 @@
#include "Encrypt.h"
#include "Mayaqua.h"
#include <openssl/ssl.h> // This is needed only for the SSL/TLS version defines
#ifdef OS_UNIX
#include <netinet/in.h>
@ -537,6 +539,7 @@ struct SSL_PIPE
{
bool ServerMode; // Whether it's in the server mode
bool IsDisconnected; // Disconnected
int SslVersion;
SSL *ssl; // SSL object
struct ssl_ctx_st *ssl_ctx; // SSL_CTX
SSL_BIO *SslInOut; // I/O BIO for the data in the SSL tunnel
@ -1407,6 +1410,7 @@ struct SslClientCertInfo {
SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh);
SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert);
SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert);
SSL_PIPE* NewSslPipeEx3(bool server_mode, X* x, K* k, LIST* chain, DH_CTX* dh, bool verify_peer, struct SslClientCertInfo* clientcert, int tls13ticketscnt, bool disableTls13);
void FreeSslPipe(SSL_PIPE *s);
bool SyncSslPipe(SSL_PIPE *s);

View File

@ -570,6 +570,7 @@ HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value,
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.)
HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.

View File

@ -568,6 +568,7 @@ HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value,
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.)
HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
# Concerning failed connection dialogs

View File

@ -588,6 +588,7 @@ HUB_AO_DetectDormantSessionInterval この項目が 0 以外の場合は、指
HUB_AO_NoPhysicalIPOnPacketLog この項目が 1 (有効) の場合は、パケットログに送信元および宛先 VPN セッションの物理的な接続元 VPN クライアントの IP アドレスが記録されないようになります。
HUB_AO_UseHubNameAsDhcpUserClassOption この項目が 1 (有効) の場合は、仮想 HUB は DHCP サーバーに対して IP アドレスの取得を要求する際に仮想 HUB 名を DHCP パケットの "User-Class" オプションに埋め込むようになります。この機能は、複数の仮想 HUB がある場合に、DHCP サーバーがそれぞれの仮想 HUB 用に IP プールを確保する場合に便利です。(L2TP/IPsec および OpenVPN セッションのみ対応。)
HUB_AO_UseHubNameAsRadiusNasId この項目が 1 (有効) の場合は、NAS-Identifier RADIUS 属性に仮想 HUB 名が埋め込まれます。この機能は、RADIUS サーバにおいて仮想 HUB ごとにアクセスの許可 / 拒否を設定したい場合に便利です。
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
# Caps 関係

View File

@ -589,6 +589,7 @@ HUB_AO_AssignVLanIdByRadiusAttribute VLAN ID의 동적 할당 기능을 활성
HUB_AO_SecureNAT_RandomizeAssignIp 이 항목을 1 (유효)의 경우 SecureNAT 기능의 가상 DHCP 서버는 DHCP 클라이언트에 할당 된 IP 주소를 지정된 IP 주소 풀에서 사용하지 않는 주소에서 임의로 선택하도록합니다. 또한, 기본 동작은 미사용 주소 중 첫 번째 주소를 할당 할 수 있도록되어 있습니다.
HUB_AO_DetectDormantSessionInterval 이 항목이 0이 아닌 경우, 지정된 초 비활성이었다 VPN 세션을 드 폰 망토 상태 (최대 절전 모드)로 식별합니다. 드 폰 망토 상태의 VPN 세션에 가상 HUB에서 홍수되어야 패킷이 침수 없습니다.
HUB_AO_NoPhysicalIPOnPacketLog 이 항목이 0 (사용)의 경우 패킷 로그에 원본 및 대상 VPN 세션의 물리적 연결 원래 VPN 클라이언트의 IP 주소가 기록되지 않도록합니다.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
# Caps 관계

View File

@ -479,7 +479,7 @@ NATT_MSG ** Connected with NAT traversal - might be unstable **\r\n\r\nThis VPN
# Virtual HUB Admin Options
HUB_AO_CLICK Select an item to view the description here.
HUB_AO_UNKNOWN The description of the item was not found. Refer to the documents, or speculate the meaning and purpose of the item from the name of the item.
HUB_AO_allow_hub_admin_change_option This is a special item. If you are enable (set to 1) this option, then not only the VPN Server's global administrator but also the Virtual Hub's administrator will be granted to modify the Virtual Hub Admin Options by himself.
HUB_AO_allow_eap_tls_match_user_by_cert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificate CNs during the PPP EAP authentication flow.
HUB_AO_deny_hub_admin_change_ext_option If you are enable (set to 1) this option, the Virtual Hub's administrator will be forbidden to modify any values on the Virtual Hub Extended Options, then only the VPN Server's global administrator can modify them.
HUB_AO_no_delay_jitter_packet_loss If you set this option to non-zero value, then all parameters of delay, jitter and packet-loss on the access-list entry will be ignored even if these parameters are set when the administrator adds a new access list entry. Therefore, delay, jitter and packet-loss generating function will be virtually disabled. Because of the delay generating function sometimes make a high volume of load on the CPU and RAM, a Virtual Hub which is shared by several users should have this option enabled.
HUB_AO_max_users If you set this option to non-zero value, the maximum number of user objects registered on the Virtual Hub will be limited to this value, then greater number of user objects than this value cannot be added.
@ -581,6 +581,7 @@ HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value, th
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.)
HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
# Concerning failed connection dialogs

View File

@ -567,6 +567,7 @@ HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value,
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.)
HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
# Concerning failed connection dialogs

View File

@ -573,6 +573,7 @@ HUB_AO_DetectDormantSessionInterval If you set this option to non-zero value,
HUB_AO_NoPhysicalIPOnPacketLog If you set this option to non-zero value, then the physical IP addresses of VPN clients of either the source VPN session or the destination VPN session will not be recorded on the packet log file.
HUB_AO_UseHubNameAsDhcpUserClassOption If you set this option to non-zero value, then the Virtual Hub Name will be added to a DHCP request to an external DHCP server as the "User-Class" option. This allows to use separate pools of IP addresses for each Virtual Hub. (For only L2TP/IPsec and OpenVPN sessions.)
HUB_AO_UseHubNameAsRadiusNasId If you set this option to non-zero value, then the NAS-Identifier RADIUS attribute will be set to a name of the Virtual Hub. This allows to determine on RADIUS server whether access to the Virtual Hub should be granted or denied.
HUB_AO_AllowEapMatchUserByCert If you enable (set to 1) this option, the Virtual Hub will attempt to match the EAP Identity not only with usernames, but also with user certificates during the PPP EAP authentication flow.
#關於失敗連接對話方塊