mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-12-26 18:19:53 +03:00
Implement EAP-MSCHAPv2
This commit is contained in:
parent
a2f30c8aad
commit
22a9231c33
@ -267,6 +267,22 @@ void PPPThread(THREAD *thread, void *param)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPP_EAP_TYPE_MSCHAPV2:
|
||||
// Sending challenge
|
||||
p->Eap_PacketId = p->NextId;
|
||||
lcp = BuildMSCHAP2ChallengePacket(p);
|
||||
BUF *b = BuildLCPData(lcp);
|
||||
lcpEap = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId, PPP_EAP_TYPE_MSCHAPV2, b->Size);
|
||||
eapPacket = lcpEap->Data;
|
||||
Copy(eapPacket->Data, b->Buf, b->Size);
|
||||
Free(b);
|
||||
PPPSetStatus(p, PPP_STATUS_AUTHENTICATING);
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcpEap))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
}
|
||||
break;
|
||||
case PPP_EAP_TYPE_IDENTITY:
|
||||
default: // We treat the unspecified protocol as the IDENTITY protocol
|
||||
p->Eap_Protocol = PPP_EAP_TYPE_IDENTITY;
|
||||
@ -1011,9 +1027,13 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
|
||||
|
||||
// Process CHAP responses
|
||||
bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req)
|
||||
{
|
||||
return PPPProcessCHAPResponsePacketEx(p, pp, req, pp->Lcp, false);
|
||||
}
|
||||
bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool eap)
|
||||
{
|
||||
PPP_LCP *lcp;
|
||||
if (pp->Lcp->Code == PPP_CHAP_CODE_RESPONSE)
|
||||
if (chap->Code == PPP_CHAP_CODE_RESPONSE)
|
||||
{
|
||||
bool ok = false;
|
||||
if (p->PPPStatus != PPP_STATUS_AUTHENTICATING && !p->AuthOk)
|
||||
@ -1023,7 +1043,7 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
if (p->AuthProtocol != PPP_PROTOCOL_CHAP)
|
||||
if (p->AuthProtocol != PPP_PROTOCOL_CHAP && !eap)
|
||||
{
|
||||
Debug("Receiving CHAP packet when auth protocol set to 0x%x\n", p->AuthProtocol);
|
||||
PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_PAP", pp->Protocol);
|
||||
@ -1031,10 +1051,10 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
return false;
|
||||
}
|
||||
|
||||
ok = PPPParseMSCHAP2ResponsePacket(p, pp);
|
||||
ok = PPPParseMSCHAP2ResponsePacketEx(p, chap);
|
||||
|
||||
// If we got only first packet of double CHAP then send second challenge
|
||||
if (ok && p->MsChapV2_UseDoubleMsChapV2 && p->EapClient != NULL && p->Ipc == NULL)
|
||||
if (ok && p->MsChapV2_UseDoubleMsChapV2 && p->EapClient != NULL && p->Ipc == NULL && !eap)
|
||||
{
|
||||
lcp = BuildMSCHAP2ChallengePacket(p);
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_CHAP, lcp))
|
||||
@ -1050,7 +1070,6 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
char hex[MAX_SIZE];
|
||||
char ret_str[MAX_SIZE];
|
||||
BUF *lcp_ret_data = NewBuf();
|
||||
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
|
||||
BinToStr(hex, sizeof(hex), p->MsChapV2_ServerResponse, 20);
|
||||
|
||||
Format(ret_str, sizeof(ret_str),
|
||||
@ -1067,19 +1086,39 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
FreeBuf(lcp_ret_data);
|
||||
}
|
||||
|
||||
res->Lcp = lcp;
|
||||
res->IsControl = true;
|
||||
res->Protocol = PPP_PROTOCOL_CHAP;
|
||||
|
||||
if (!PPPSendPacketAndFree(p, res))
|
||||
if (!eap)
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
|
||||
res->Lcp = lcp;
|
||||
res->IsControl = true;
|
||||
res->Protocol = PPP_PROTOCOL_CHAP;
|
||||
|
||||
if (!PPPSendPacketAndFree(p, res))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
BUF *b = BuildLCPData(lcp);
|
||||
p->Eap_PacketId = p->NextId++;
|
||||
lcp = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId, PPP_EAP_TYPE_MSCHAPV2, b->Size);
|
||||
PPP_EAP *eapPacket = lcp->Data;
|
||||
Copy(eapPacket->Data, b->Buf, b->Size);
|
||||
Free(b);
|
||||
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
p->AuthOk = true;
|
||||
PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS);
|
||||
}
|
||||
// We failed MSCHAPv2 auth
|
||||
else
|
||||
@ -1087,7 +1126,6 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
char hex[MAX_SIZE];
|
||||
char ret_str[MAX_SIZE];
|
||||
BUF *lcp_ret_data = NewBuf();
|
||||
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
|
||||
|
||||
BinToStr(hex, sizeof(hex), p->MsChapV2_ServerChallenge, 16);
|
||||
|
||||
@ -1105,19 +1143,39 @@ bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
FreeBuf(lcp_ret_data);
|
||||
}
|
||||
|
||||
res->Lcp = lcp;
|
||||
res->IsControl = true;
|
||||
res->Protocol = PPP_PROTOCOL_CHAP;
|
||||
|
||||
if (!PPPSendPacketAndFree(p, res))
|
||||
if (!eap)
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
PPP_PACKET *res = ZeroMalloc(sizeof(PPP_PACKET));
|
||||
res->Lcp = lcp;
|
||||
res->IsControl = true;
|
||||
res->Protocol = PPP_PROTOCOL_CHAP;
|
||||
|
||||
if (!PPPSendPacketAndFree(p, res))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
|
||||
}
|
||||
else
|
||||
{
|
||||
BUF *b = BuildLCPData(lcp);
|
||||
p->Eap_PacketId = p->NextId++;
|
||||
lcp = BuildEAPPacketEx(PPP_EAP_CODE_REQUEST, p->Eap_PacketId, PPP_EAP_TYPE_MSCHAPV2, b->Size);
|
||||
PPP_EAP *eapPacket = lcp->Data;
|
||||
Copy(eapPacket->Data, b->Buf, b->Size);
|
||||
Free(b);
|
||||
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PPPLog(p, "LP_CHAP_FAILED");
|
||||
PPPSetStatus(p, PPP_STATUS_AUTH_FAIL);
|
||||
}
|
||||
|
||||
return ok;
|
||||
@ -1219,8 +1277,14 @@ 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:
|
||||
/// TODO: implement alternative EAP protocol selection based on received NAK
|
||||
// For now just fallback to auth protocol selection to try to select MSCHAP or PAP
|
||||
if (p->Eap_Protocol == PPP_EAP_TYPE_TLS)
|
||||
{
|
||||
// Propose EAP-MSCHAPv2
|
||||
p->Eap_Protocol = PPP_EAP_TYPE_MSCHAPV2;
|
||||
PPPSetStatus(p, PPP_STATUS_BEFORE_AUTH);
|
||||
break;
|
||||
}
|
||||
// Fallback to auth protocol selection to try to select MSCHAP or PAP
|
||||
Debug("Got a EAP_NAK, abandoning EAP protocol\n");
|
||||
PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
PPPSetStatus(p, PPP_STATUS_CONNECTED);
|
||||
@ -1239,6 +1303,51 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
|
||||
case PPP_EAP_TYPE_TLS:
|
||||
PPPProcessEAPTlsResponse(p, eap_packet, eap_datasize);
|
||||
break;
|
||||
case PPP_EAP_TYPE_MSCHAPV2:
|
||||
if (p->PPPStatus != PPP_STATUS_AUTHENTICATING)
|
||||
{
|
||||
Debug("Received EAP-MSCHAPv2 response not during authentication\n");
|
||||
break;
|
||||
}
|
||||
if (eap_datasize == 1)
|
||||
{
|
||||
// Success or failure response
|
||||
PPP_PACKET *pack = ZeroMalloc(sizeof(PPP_PACKET));
|
||||
pack->IsControl = true;
|
||||
pack->Protocol = PPP_PROTOCOL_EAP;
|
||||
|
||||
if (p->AuthOk)
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS);
|
||||
pack->Lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, p->Eap_PacketId);
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// CHAP response
|
||||
PPP_LCP *chap = PPPParseLCP(PPP_PROTOCOL_CHAP, eap_packet->Data, eap_datasize);
|
||||
if (chap == NULL)
|
||||
{
|
||||
Debug("Received an invalid EAP-MSCHAPv2 packet\n");
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
break;
|
||||
}
|
||||
PPPProcessCHAPResponsePacketEx(p, pp, req, chap, true);
|
||||
FreePPPLCP(chap);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug("We got an unexpected EAP response packet! Ignoring...\n");
|
||||
break;
|
||||
@ -2686,6 +2795,15 @@ PPP_LCP *PPPParseLCP(USHORT protocol, void *data, UINT size)
|
||||
goto LABEL_ERROR;
|
||||
}
|
||||
len = READ_USHORT(buf);
|
||||
// Fix bad endianness
|
||||
if (len > size)
|
||||
{
|
||||
USHORT len1 = Swap16(len);
|
||||
if (len1 <= size)
|
||||
{
|
||||
len = len1;
|
||||
}
|
||||
}
|
||||
if (len < 4)
|
||||
{
|
||||
goto LABEL_ERROR;
|
||||
@ -2761,6 +2879,10 @@ LABEL_ERROR:
|
||||
|
||||
// Analyse MS CHAP v2 Response packet
|
||||
bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
{
|
||||
return PPPParseMSCHAP2ResponsePacketEx(p, pp->Lcp);
|
||||
}
|
||||
bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp)
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
@ -2783,18 +2905,18 @@ bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
UINT error_code;
|
||||
UINT64 eap_client_ptr = (UINT64)p->EapClient;
|
||||
|
||||
if (pp->Lcp != NULL && pp->Lcp->DataSize >= 51)
|
||||
if (lcp != NULL && lcp->DataSize >= 51)
|
||||
{
|
||||
BUF *b;
|
||||
if (pp->Lcp->Id != p->MsChapV2_PacketId)
|
||||
if (lcp->Id != p->MsChapV2_PacketId)
|
||||
{
|
||||
Debug("Got incorrect LCP PacketId! Should be 0x%x, got 0x%x\n", p->MsChapV2_PacketId, pp->Lcp->Id);
|
||||
p->MsChapV2_PacketId = pp->Lcp->Id;
|
||||
Debug("Got incorrect LCP PacketId! Should be 0x%x, got 0x%x\n", p->MsChapV2_PacketId, lcp->Id);
|
||||
p->MsChapV2_PacketId = lcp->Id;
|
||||
}
|
||||
|
||||
b = NewBuf();
|
||||
|
||||
WriteBuf(b, pp->Lcp->Data, pp->Lcp->DataSize);
|
||||
WriteBuf(b, lcp->Data, lcp->DataSize);
|
||||
SeekBuf(b, 0, 0);
|
||||
|
||||
if (ReadBufChar(b) == 49)
|
||||
|
@ -111,6 +111,7 @@
|
||||
#define PPP_EAP_TYPE_NOTIFICATION 2
|
||||
#define PPP_EAP_TYPE_NAK 3
|
||||
#define PPP_EAP_TYPE_TLS 13
|
||||
#define PPP_EAP_TYPE_MSCHAPV2 26
|
||||
|
||||
// EAP-TLS Flags
|
||||
#define PPP_EAP_TLS_FLAG_NONE 0
|
||||
@ -336,6 +337,7 @@ bool PPPSendEchoRequest(PPP_SESSION *p);
|
||||
bool PPPProcessResponsePacket(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 PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req, PPP_LCP *chap, bool eap);
|
||||
bool PPPProcessIPCPResponsePacket(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);
|
||||
@ -376,6 +378,7 @@ PPP_OPTION *NewPPPOption(UCHAR type, void *data, UINT size);
|
||||
PPP_PACKET *ParsePPPPacket(void *data, UINT size);
|
||||
PPP_LCP *PPPParseLCP(USHORT protocol, void *data, UINT size);
|
||||
bool PPPParseMSCHAP2ResponsePacket(PPP_SESSION *p, PPP_PACKET *req);
|
||||
bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp);
|
||||
// Packet building utilities
|
||||
BUF *BuildPPPPacketData(PPP_PACKET *pp);
|
||||
BUF *BuildLCPData(PPP_LCP *c);
|
||||
|
Loading…
Reference in New Issue
Block a user