1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-23 01:49:53 +03:00

Improve EAP behavior with RADIUS

This commit is contained in:
domosekai 2021-07-09 05:50:56 +00:00
parent 22a9231c33
commit eff784b624
2 changed files with 121 additions and 24 deletions

View File

@ -269,7 +269,7 @@ void PPPThread(THREAD *thread, void *param)
break; break;
case PPP_EAP_TYPE_MSCHAPV2: case PPP_EAP_TYPE_MSCHAPV2:
// Sending challenge // Sending challenge
p->Eap_PacketId = p->NextId; p->Eap_PacketId = p->NextId; // Do not increase NextId so that MSCHAPv2 could use the same id
lcp = BuildMSCHAP2ChallengePacket(p); lcp = BuildMSCHAP2ChallengePacket(p);
BUF *b = BuildLCPData(lcp); BUF *b = BuildLCPData(lcp);
lcpEap = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId, PPP_EAP_TYPE_MSCHAPV2, b->Size); lcpEap = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId, PPP_EAP_TYPE_MSCHAPV2, b->Size);
@ -281,6 +281,7 @@ void PPPThread(THREAD *thread, void *param)
{ {
PPPSetStatus(p, PPP_STATUS_FAIL); PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE; WHERE;
break;
} }
break; break;
case PPP_EAP_TYPE_IDENTITY: case PPP_EAP_TYPE_IDENTITY:
@ -1030,7 +1031,7 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
{ {
return PPPProcessCHAPResponsePacketEx(p, pp, req, pp->Lcp, false); return PPPProcessCHAPResponsePacketEx(p, pp, req, pp->Lcp, false);
} }
bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool eap) bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool use_eap)
{ {
PPP_LCP *lcp; PPP_LCP *lcp;
if (chap->Code == PPP_CHAP_CODE_RESPONSE) if (chap->Code == PPP_CHAP_CODE_RESPONSE)
@ -1043,7 +1044,7 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *
WHERE; WHERE;
return false; return false;
} }
if (p->AuthProtocol != PPP_PROTOCOL_CHAP && !eap) if (p->AuthProtocol != PPP_PROTOCOL_CHAP && use_eap == false)
{ {
Debug("Receiving CHAP packet when auth protocol set to 0x%x\n", p->AuthProtocol); Debug("Receiving CHAP packet when auth protocol set to 0x%x\n", p->AuthProtocol);
PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_PAP", pp->Protocol); PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_PAP", pp->Protocol);
@ -1051,10 +1052,10 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *
return false; return false;
} }
ok = PPPParseMSCHAP2ResponsePacketEx(p, chap); ok = PPPParseMSCHAP2ResponsePacketEx(p, chap, use_eap);
// If we got only first packet of double CHAP then send second challenge // If we got only first packet of double CHAP then send second challenge
if (ok && p->MsChapV2_UseDoubleMsChapV2 && p->EapClient != NULL && p->Ipc == NULL && !eap) if (ok && p->MsChapV2_UseDoubleMsChapV2 && p->EapClient != NULL && p->Ipc == NULL)
{ {
lcp = BuildMSCHAP2ChallengePacket(p); lcp = BuildMSCHAP2ChallengePacket(p);
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_CHAP, lcp)) if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_CHAP, lcp))
@ -1086,7 +1087,7 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *
FreeBuf(lcp_ret_data); FreeBuf(lcp_ret_data);
} }
if (!eap) if (use_eap == false)
{ {
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET)); PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
res->Lcp = lcp; res->Lcp = lcp;
@ -1143,7 +1144,7 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *
FreeBuf(lcp_ret_data); FreeBuf(lcp_ret_data);
} }
if (!eap) if (use_eap == false)
{ {
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET)); PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
res->Lcp = lcp; res->Lcp = lcp;
@ -1261,6 +1262,12 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
UINT64 offer = 0; UINT64 offer = 0;
PPP_LCP *c; PPP_LCP *c;
UCHAR ms_chap_v2_code[3]; UCHAR ms_chap_v2_code[3];
ETHERIP_ID d;
char username[MAX_SIZE];
char hubname[MAX_SIZE];
HUB *hub;
bool found = false;
UINT authtype;
WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP);
ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2;
@ -1268,11 +1275,101 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
switch (eap_packet->Type) switch (eap_packet->Type)
{ {
case PPP_EAP_TYPE_IDENTITY: case PPP_EAP_TYPE_IDENTITY:
// Parse username
Copy(p->Eap_Identity, eap_packet->Data, MIN(MAX_SIZE, eap_datasize)); Copy(p->Eap_Identity, eap_packet->Data, MIN(MAX_SIZE, eap_datasize));
// As we received the identity packet, we switch back to BEFORE_AUTH and switch to the EAP_TLS proto to send the TlsStart packet on the next tick 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);
// Locate user
LockHubList(p->Cedar);
{
hub = GetHub(p->Cedar, hubname);
}
UnlockHubList(p->Cedar);
if (hub != NULL)
{
AcLock(hub);
{
USER *user = AcGetUser(hub, username);
if (user == NULL)
{
user = AcGetUser(hub, "*");
}
if (user != NULL)
{
found = true;
authtype = user->AuthType;
ReleaseUser(user);
}
}
AcUnlock(hub);
ReleaseHub(hub);
}
if (!found)
{
// User not found, fail immediately
PPP_PACKET *pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack->Lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId);
if (!PPPSendPacketAndFree(p, pack))
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
break;
}
// Select EAP method based on auth type
switch (authtype)
{
case AUTHTYPE_RADIUS:
// Create EAP client if needed
if (p->MsChapV2_UseDoubleMsChapV2 && p->EapClient == NULL)
{
char client_ip_tmp[256];
IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP);
Debug("EAP-MSCHAPv2 creating EAP RADIUS client\n");
p->EapClient = HubNewEapClient(p->Cedar, hubname, client_ip_tmp, username, "L3:PPP");
if (p->EapClient == NULL)
{
PPP_PACKET *pack = ZeroMalloc(sizeof(PPP_PACKET));
pack->IsControl = true;
pack->Protocol = PPP_PROTOCOL_EAP;
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
pack->Lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId);
if (PPPSendPacketAndFree(p, pack) == false)
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
}
break;
}
}
case AUTHTYPE_ANONYMOUS:
case AUTHTYPE_PASSWORD:
case AUTHTYPE_NT:
// Propose EAP-MSCHAPv2 directly
p->Eap_Protocol = PPP_EAP_TYPE_MSCHAPV2;
PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH);
break;
default:
// Propose EAP-TLS first
p->Eap_Protocol = PPP_EAP_TYPE_TLS; p->Eap_Protocol = PPP_EAP_TYPE_TLS;
PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH); PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH);
break; break;
}
break;
case PPP_EAP_TYPE_NOTIFICATION: case PPP_EAP_TYPE_NOTIFICATION:
// Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here... // Basically this is just an acknoweldgment that the notification was accepted by the client. Nothing to do here...
break; break;
@ -1331,6 +1428,7 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
{ {
PPPSetStatus(p, PPP_STATUS_FAIL); PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE; WHERE;
return false;
} }
} }
else else
@ -1342,7 +1440,7 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
Debug("Received an invalid EAP-MSCHAPv2 packet\n"); Debug("Received an invalid EAP-MSCHAPv2 packet\n");
PPPSetStatus(p, PPP_STATUS_FAIL); PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE; WHERE;
break; return false;
} }
PPPProcessCHAPResponsePacketEx(p, pp, req, chap, true); PPPProcessCHAPResponsePacketEx(p, pp, req, chap, true);
FreePPPLCP(chap); FreePPPLCP(chap);
@ -2880,9 +2978,9 @@ LABEL_ERROR:
// Analyse MS CHAP v2 Response packet // Analyse MS CHAP v2 Response packet
bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp) bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp)
{ {
return PPPParseMSCHAP2ResponsePacketEx(p, pp->Lcp); return PPPParseMSCHAP2ResponsePacketEx(p, pp->Lcp, false);
} }
bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp) bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp, bool use_eap)
{ {
bool ok = false; bool ok = false;
@ -2964,24 +3062,23 @@ bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp)
client_response_hex, client_response_hex,
eap_client_hex); eap_client_hex);
if (p->MsChapV2_UseDoubleMsChapV2 && p->EapClient == NULL) // Normal MSCHAPv2 only
// For EAP-MSCHAPv2, EAP client is created before sending the challenge
if (p->MsChapV2_UseDoubleMsChapV2 && p->EapClient == NULL && use_eap == false)
{ {
Debug("Double MSCHAPv2 creating EAP client\n"); Debug("Double MSCHAPv2 creating EAP client\n");
eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP"); eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP");
// We do not know the user's auth type, so do not fail PPP if eap is null
if (eap) if (eap)
{ {
ok = true; ok = true;
p->EapClient = eap; p->EapClient = eap;
} FreeBuf(b);
else return ok;
{
PPPSetStatus(p, PPP_STATUS_FAIL);
WHERE;
return false;
} }
} }
else if (p->Ipc == NULL) if (p->Ipc == NULL)
{ {
Debug("MSCHAPv2 creating IPC\n"); Debug("MSCHAPv2 creating IPC\n");
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL, ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL,

View File

@ -337,7 +337,7 @@ bool PPPSendEchoRequest(PPP_SESSION *p);
bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool eap); bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool use_eap);
bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
@ -377,8 +377,8 @@ PPP_OPTION *NewPPPOption(UCHAR type, void *data, UINT size);
// Packet parse utilities // Packet parse utilities
PPP_PACKET *ParsePPPPacket(void *data, UINT size); PPP_PACKET *ParsePPPPacket(void *data, UINT size);
PPP_LCP *PPPParseLCP(USHORT protocol, void *data, UINT size); PPP_LCP *PPPParseLCP(USHORT protocol, void *data, UINT size);
bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *req); bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp);
bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp); bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp, bool use_eap);
// Packet building utilities // Packet building utilities
BUF *BuildPPPPacketData(PPP_PACKET *pp); BUF *BuildPPPPacketData(PPP_PACKET *pp);
BUF *BuildLCPData(PPP_LCP *c); BUF *BuildLCPData(PPP_LCP *c);