mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2026-03-09 17:59:19 +03:00
Compare commits
2 Commits
33d682beee
...
019261e47f
| Author | SHA1 | Date | |
|---|---|---|---|
| 019261e47f | |||
| bd1512f15b |
1
.gitignore
vendored
1
.gitignore
vendored
@ -215,3 +215,4 @@ developer_tools/stbchecker/**/.mfractor/
|
|||||||
/_codeql_build_dir/
|
/_codeql_build_dir/
|
||||||
/_codeql_detected_source_root
|
/_codeql_detected_source_root
|
||||||
/build/
|
/build/
|
||||||
|
/build_test/
|
||||||
|
|||||||
@ -356,6 +356,7 @@ void IKEv2FreeSA(IKE_SERVER *ike, IKEv2_SA *sa)
|
|||||||
FreeBuf(sa->GxI);
|
FreeBuf(sa->GxI);
|
||||||
FreeBuf(sa->GxR);
|
FreeBuf(sa->GxR);
|
||||||
FreeBuf(sa->IDi_Data);
|
FreeBuf(sa->IDi_Data);
|
||||||
|
FreeBuf(sa->IDr_Data);
|
||||||
FreeBuf(sa->InitMsg);
|
FreeBuf(sa->InitMsg);
|
||||||
FreeBuf(sa->RespMsg);
|
FreeBuf(sa->RespMsg);
|
||||||
FreeBuf(sa->LastResponse);
|
FreeBuf(sa->LastResponse);
|
||||||
@ -563,14 +564,15 @@ BUF *IKEv2EncryptSK(IKE_SERVER *ike, IKEv2_SA *sa, UCHAR next_payload,
|
|||||||
UINT total_payload_len; // 4 + IV + enc + ICV
|
UINT total_payload_len; // 4 + IV + enc + ICV
|
||||||
IKE_CRYPTO_PARAM cp;
|
IKE_CRYPTO_PARAM cp;
|
||||||
|
|
||||||
// Pad to block boundary: plaintext | padding | pad_len_byte | next_payload_byte
|
// Pad to block boundary: plaintext = inner_payloads | padding | pad_len
|
||||||
plain_len = inner_size + 2; // +2 for pad-length and next-header
|
// RFC 7296 Section 3.14: the last byte of the plaintext is Pad Length.
|
||||||
|
plain_len = inner_size + 1; // +1 for pad-length byte
|
||||||
if ((plain_len % block_size) != 0)
|
if ((plain_len % block_size) != 0)
|
||||||
plain_len = ((plain_len / block_size) + 1) * block_size;
|
plain_len = ((plain_len / block_size) + 1) * block_size;
|
||||||
pad_len = plain_len - inner_size - 2;
|
pad_len = plain_len - inner_size - 1;
|
||||||
enc_len = plain_len;
|
enc_len = plain_len;
|
||||||
|
|
||||||
// Build plaintext: inner | padding | pad_len | next_payload
|
// Build plaintext: inner | padding (incrementing bytes) | pad_len
|
||||||
plain = ZeroMalloc(plain_len);
|
plain = ZeroMalloc(plain_len);
|
||||||
Copy(plain, inner, inner_size);
|
Copy(plain, inner, inner_size);
|
||||||
{
|
{
|
||||||
@ -579,7 +581,6 @@ BUF *IKEv2EncryptSK(IKE_SERVER *ike, IKEv2_SA *sa, UCHAR next_payload,
|
|||||||
plain[inner_size + i] = (UCHAR)(i + 1);
|
plain[inner_size + i] = (UCHAR)(i + 1);
|
||||||
}
|
}
|
||||||
plain[inner_size + pad_len] = (UCHAR)pad_len;
|
plain[inner_size + pad_len] = (UCHAR)pad_len;
|
||||||
plain[inner_size + pad_len + 1] = next_payload;
|
|
||||||
|
|
||||||
// Random IV
|
// Random IV
|
||||||
Rand(iv, block_size);
|
Rand(iv, block_size);
|
||||||
@ -599,7 +600,8 @@ BUF *IKEv2EncryptSK(IKE_SERVER *ike, IKEv2_SA *sa, UCHAR next_payload,
|
|||||||
result = NewBuf();
|
result = NewBuf();
|
||||||
|
|
||||||
// Generic payload header (4 bytes)
|
// Generic payload header (4 bytes)
|
||||||
hdr[0] = IKEv2_PAYLOAD_NONE; // Next payload (to be filled later by caller via header)
|
// Next Payload = type of first inner payload (RFC 7296 §3.14)
|
||||||
|
hdr[0] = next_payload;
|
||||||
hdr[1] = 0; // Critical
|
hdr[1] = 0; // Critical
|
||||||
WRITE_USHORT(hdr + 2, (USHORT)total_payload_len);
|
WRITE_USHORT(hdr + 2, (USHORT)total_payload_len);
|
||||||
WriteBuf(result, hdr, 4);
|
WriteBuf(result, hdr, 4);
|
||||||
@ -640,7 +642,7 @@ static void IKEv2FillICV(IKE_SERVER *ike, IKEv2_SA *sa,
|
|||||||
// sk_data points to the payload data (after the 4-byte generic header).
|
// sk_data points to the payload data (after the 4-byte generic header).
|
||||||
// Returns a BUF of the decrypted inner payloads, or NULL on failure.
|
// Returns a BUF of the decrypted inner payloads, or NULL on failure.
|
||||||
BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
||||||
void *sk_data, UINT sk_size, UCHAR *out_next_payload)
|
void *sk_data, UINT sk_size)
|
||||||
{
|
{
|
||||||
UINT block_size = sa->Transform.BlockSize;
|
UINT block_size = sa->Transform.BlockSize;
|
||||||
UINT icv_len = IKEv2IntegIcvLen(sa->Transform.IntegAlg);
|
UINT icv_len = IKEv2IntegIcvLen(sa->Transform.IntegAlg);
|
||||||
@ -651,7 +653,6 @@ BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
|||||||
UCHAR *plain;
|
UCHAR *plain;
|
||||||
BUF *result;
|
BUF *result;
|
||||||
UCHAR pad_len;
|
UCHAR pad_len;
|
||||||
UCHAR nxt;
|
|
||||||
|
|
||||||
// sk_data layout (from right after generic header):
|
// sk_data layout (from right after generic header):
|
||||||
// IV (block_size) | ciphertext | ICV (icv_len)
|
// IV (block_size) | ciphertext | ICV (icv_len)
|
||||||
@ -669,25 +670,23 @@ BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
|||||||
plain = Malloc(ct_len);
|
plain = Malloc(ct_len);
|
||||||
IkeCryptoDecrypt(sa->EncKeyI, plain, ciphertext, ct_len, iv);
|
IkeCryptoDecrypt(sa->EncKeyI, plain, ciphertext, ct_len, iv);
|
||||||
|
|
||||||
// Last two bytes of plaintext: pad_len | next_payload
|
// RFC 7296 Section 3.14: last byte of plaintext is Pad Length.
|
||||||
if (ct_len < 2)
|
// Strip Pad Length + 1 bytes from the end to get inner payloads.
|
||||||
|
// The first inner payload type is in the SK generic header (read by caller).
|
||||||
|
if (ct_len < 1)
|
||||||
{
|
{
|
||||||
Free(plain);
|
Free(plain);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pad_len = plain[ct_len - 2];
|
pad_len = plain[ct_len - 1];
|
||||||
nxt = plain[ct_len - 1];
|
|
||||||
|
|
||||||
if (pad_len + 2 > ct_len)
|
if ((UINT)(pad_len + 1) > ct_len)
|
||||||
{
|
{
|
||||||
Free(plain);
|
Free(plain);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_next_payload)
|
result = MemToBuf(plain, ct_len - pad_len - 1);
|
||||||
*out_next_payload = nxt;
|
|
||||||
|
|
||||||
result = MemToBuf(plain, ct_len - pad_len - 2);
|
|
||||||
Free(plain);
|
Free(plain);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1737,157 +1736,94 @@ void IKEv2ProcSAInit(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr)
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
||||||
IKEv2_SA *sa, void *payload_data, UINT payload_size)
|
IKEv2_SA *sa, void *payload_data, UINT payload_size,
|
||||||
|
UCHAR first_payload)
|
||||||
{
|
{
|
||||||
UCHAR nxt = 0;
|
|
||||||
UCHAR *pos = (UCHAR *)payload_data;
|
UCHAR *pos = (UCHAR *)payload_data;
|
||||||
UCHAR *end = pos + payload_size;
|
UCHAR *end = pos + payload_size;
|
||||||
|
UCHAR cur_type = first_payload;
|
||||||
// Parsed payload pointers
|
|
||||||
UCHAR *idi_body = NULL; UINT idi_sz = 0;
|
|
||||||
UCHAR idi_type = 0;
|
|
||||||
UCHAR *auth_body = NULL; UINT auth_sz = 0;
|
|
||||||
UCHAR auth_method = 0;
|
|
||||||
UCHAR *sa_body = NULL; UINT sa_sz = 0;
|
|
||||||
UCHAR *tsi_body = NULL; UINT tsi_sz = 0;
|
|
||||||
UCHAR *tsr_body = NULL; UINT tsr_sz = 0;
|
|
||||||
bool use_transport = false;
|
|
||||||
UINT msg_id = Endian32(hdr->MessageId);
|
UINT msg_id = Endian32(hdr->MessageId);
|
||||||
|
|
||||||
// The first inner payload type was returned from IKEv2DecryptSK
|
// Parsed payload results
|
||||||
// (out_next_payload), so we receive it pre-parsed by the caller.
|
UCHAR *idi_body = NULL; UINT idi_sz = 0; UCHAR idi_type = 0;
|
||||||
// Here payload_data already contains the inner payloads from the SK body.
|
UCHAR *idr_body = NULL; UINT idr_sz = 0; UCHAR idr_type = 0;
|
||||||
// We need the first-payload type. The caller stored it in nxt before calling us.
|
UCHAR *auth_body = NULL; UINT auth_sz = 0; UCHAR auth_method = 0;
|
||||||
// Re-read from the context: we expect the caller to pass nxt; instead we use
|
UCHAR *sa_body = NULL; UINT sa_sz = 0;
|
||||||
// a simple scan approach: iterate payloads from the start of the decrypted data.
|
|
||||||
|
|
||||||
// Actually the caller passes raw inner payload bytes; each payload starts with
|
// Walk the payload linked list (RFC 7296: each payload's byte[0] = type of NEXT payload)
|
||||||
// next_payload (1) | crit (1) | len (2) | body.
|
while (cur_type != IKEv2_PAYLOAD_NONE && pos + 4 <= end)
|
||||||
// The first payload type was stored by the caller before the call.
|
|
||||||
// We receive first_nxt implicitly through the structure.
|
|
||||||
// For simplicity we scan without knowing first type; instead we look at each
|
|
||||||
// 4-byte header and use the "next" field of the PREVIOUS payload.
|
|
||||||
// Use a linked-list walk starting from the nxt passed as first_nxt_payload.
|
|
||||||
// Since we don't have it here, re-scan all payloads by type.
|
|
||||||
// The caller must pass the first-payload type through this function argument.
|
|
||||||
// We add it as a parameter in the next section.
|
|
||||||
|
|
||||||
// Iterate the inner payload chain
|
|
||||||
// The decrypted buffer contains chained payloads starting from first_inner_payload.
|
|
||||||
// The last two bytes of plaintext (pad_len, next_payload) are stripped already.
|
|
||||||
// So we just do a linear scan: each entry is: next(1)|crit(1)|len(2)|body...
|
|
||||||
// We use a simplified approach: look for each payload type by scanning all.
|
|
||||||
|
|
||||||
while (pos + 4 <= end)
|
|
||||||
{
|
{
|
||||||
UCHAR next_pl = pos[0];
|
UCHAR next_type = pos[0]; // type of the NEXT payload
|
||||||
USHORT pl_total = R16(pos + 2);
|
USHORT pl_total = R16(pos + 2);
|
||||||
UCHAR *body = pos + 4;
|
UCHAR *body = pos + 4; // body starts after 4-byte generic header
|
||||||
UINT body_len = (pl_total >= 4) ? (pl_total - 4) : 0;
|
UINT body_len = (pl_total >= 4) ? (pl_total - 4) : 0;
|
||||||
|
|
||||||
if (pl_total < 4 || pos + pl_total > end)
|
if (pl_total < 4 || pos + pl_total > end)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// We identify by matching what we expect in IKE_AUTH inner payloads
|
switch (cur_type)
|
||||||
// Hint: The first payload type is known to be IDi (35) for an initiating IKE_AUTH.
|
{
|
||||||
// But we need to distinguish which payload is which. We track via next-payload chain.
|
case IKEv2_PAYLOAD_IDi:
|
||||||
// Since each node carries the NEXT type in byte[0], we process in order:
|
// IDi body = ID_Type(1) | RESERVED(3) | ID_data
|
||||||
// walk: current type = last_type (from previous iteration), data = body.
|
// RFC 7296 §2.15: MACedIDForI = prf(SK_pi, IDi_b) where IDi_b = full body
|
||||||
// To start, we assume the caller sets nxt to the type of the FIRST payload.
|
idi_type = body[0];
|
||||||
// Since we can't know the first type here without an extra parameter,
|
idi_body = body;
|
||||||
// we re-iterate using a second scan after we know the chain.
|
idi_sz = body_len;
|
||||||
|
|
||||||
// Simple approach: detect payload by context position and expected sequence.
|
|
||||||
// IKE_AUTH: IDi, [CERT], AUTH, SAi2, TSi, TSr
|
|
||||||
// We match type values directly via the next-payload field of the CURRENT payload
|
|
||||||
// to determine what the current payload is. We read the current payload's type
|
|
||||||
// from the previous iteration's next-payload byte.
|
|
||||||
// Since we cannot know the FIRST payload's type without parameter,
|
|
||||||
// we will now just identify based on type value directly.
|
|
||||||
// In practice IDi=35, AUTH=39, SA=33, TSi=44, TSr=45.
|
|
||||||
// The "current type" needs to come from outside.
|
|
||||||
// The cleanest fix: parse as (type, len, body) by using pos[0] as next of prev.
|
|
||||||
// We track current type externally via nxt:
|
|
||||||
|
|
||||||
// BREAK OUT and use the canonical scan below:
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IKEv2_PAYLOAD_IDr:
|
||||||
|
// IDr requested by initiator (Apple's "Remote ID") - echo it back in response
|
||||||
|
idr_type = body[0];
|
||||||
|
idr_body = body;
|
||||||
|
idr_sz = body_len;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IKEv2_PAYLOAD_AUTH:
|
||||||
|
// AUTH body = auth_method(1) | RESERVED(3) | auth_data
|
||||||
|
if (body_len >= 4)
|
||||||
|
{
|
||||||
|
auth_method = body[0];
|
||||||
|
auth_body = body + 4; // auth data starts after method + 3 reserved bytes
|
||||||
|
auth_sz = body_len - 4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IKEv2_PAYLOAD_SA:
|
||||||
|
sa_body = body;
|
||||||
|
sa_sz = body_len;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// TSi, TSr, NOTIFY, CP, CERT, etc. - accepted but not needed here
|
||||||
}
|
}
|
||||||
|
|
||||||
// Canonical scan: use a separate pass where nxt starts as first_payload_type
|
cur_type = next_type;
|
||||||
// passed from the SK decoder. But we don't have that parameter here.
|
|
||||||
// Solution: save first payload type in the existing code that calls IKEv2ProcAuth.
|
|
||||||
// We pass it via the macro below by restarting with nxt = type of first inner payload.
|
|
||||||
// The caller will set nxt before calling; we read nxt from a local variable set
|
|
||||||
// by the caller. The caller already computed it as out_next_payload from IKEv2DecryptSK.
|
|
||||||
// We add it as an extra parameter at the call site.
|
|
||||||
// For now, use a two-pass approach: first pass collects all payload types and bodies.
|
|
||||||
|
|
||||||
// Reset and do a two-pass scan
|
|
||||||
{
|
|
||||||
// Phase 1: walk the chain to map (index -> type)
|
|
||||||
UCHAR types[64];
|
|
||||||
UCHAR *bodies[64];
|
|
||||||
UINT body_lens[64];
|
|
||||||
UINT count = 0;
|
|
||||||
UCHAR cur_nxt = 0; // caller must set first payload type somehow
|
|
||||||
|
|
||||||
// Since we can't know first-payload type without passing it,
|
|
||||||
// use the convention that the SK payload carries the first inner type
|
|
||||||
// in its "next payload" field (byte 0 of the SK payload generic header).
|
|
||||||
// The caller does pass nxt to us: see the call site in ProcIKEv2PacketRecv.
|
|
||||||
// We'll use the approach of scanning by expected IKE_AUTH payload types.
|
|
||||||
|
|
||||||
pos = (UCHAR *)payload_data;
|
|
||||||
while (pos + 4 <= end && count < 64)
|
|
||||||
{
|
|
||||||
USHORT pl_total = R16(pos + 2);
|
|
||||||
if (pl_total < 4 || pos + pl_total > end) break;
|
|
||||||
bodies[count] = pos + 4;
|
|
||||||
body_lens[count] = (pl_total >= 4) ? (pl_total - 4) : 0;
|
|
||||||
// We don't know the type without chain-walking; mark as unknown for now.
|
|
||||||
types[count] = 0;
|
|
||||||
count++;
|
|
||||||
pos += pl_total;
|
pos += pl_total;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Phase 2: identify payloads by expected position in IKE_AUTH:
|
|
||||||
// IDi is always first, then AUTH, then SA, then TSi, TSr.
|
|
||||||
// This works for standard Windows/iOS/Android/Linux clients.
|
|
||||||
if (count >= 4)
|
|
||||||
{
|
|
||||||
idi_type = bodies[0][0];
|
|
||||||
idi_body = bodies[0] + 4;
|
|
||||||
idi_sz = body_lens[0] > 4 ? body_lens[0] - 4 : 0;
|
|
||||||
|
|
||||||
auth_method = bodies[1][0];
|
|
||||||
auth_body = bodies[1] + 4;
|
|
||||||
auth_sz = body_lens[1] > 4 ? body_lens[1] - 4 : 0;
|
|
||||||
|
|
||||||
sa_body = bodies[2];
|
|
||||||
sa_sz = body_lens[2];
|
|
||||||
|
|
||||||
tsi_body = bodies[3];
|
|
||||||
tsi_sz = body_lens[3];
|
|
||||||
|
|
||||||
if (count >= 5)
|
|
||||||
{
|
|
||||||
tsr_body = bodies[4];
|
|
||||||
tsr_sz = body_lens[4];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idi_body == NULL || auth_body == NULL || sa_body == NULL)
|
if (idi_body == NULL || auth_body == NULL || sa_body == NULL)
|
||||||
{
|
{
|
||||||
IKEv2SendNotifyError(ike, p, hdr, sa->ResponderSPI, IKEv2_NOTIFY_AUTHENTICATION_FAILED);
|
IKEv2SendNotifyError(ike, p, hdr, sa->ResponderSPI, IKEv2_NOTIFY_AUTHENTICATION_FAILED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store IDi
|
// Store IDi (full body: ID_type + reserved + id_data, for AUTH computation)
|
||||||
FreeBuf(sa->IDi_Data);
|
FreeBuf(sa->IDi_Data);
|
||||||
sa->IDi_Type = idi_type;
|
sa->IDi_Type = idi_type;
|
||||||
sa->IDi_Data = MemToBuf(idi_body, idi_sz);
|
sa->IDi_Data = MemToBuf(idi_body, idi_sz);
|
||||||
|
|
||||||
|
// Store requested IDr (to echo back in response)
|
||||||
|
FreeBuf(sa->IDr_Data);
|
||||||
|
if (idr_body != NULL)
|
||||||
|
{
|
||||||
|
sa->IDr_Type = idr_type;
|
||||||
|
sa->IDr_Data = MemToBuf(idr_body, idr_sz);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sa->IDr_Type = 0;
|
||||||
|
sa->IDr_Data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify AUTH
|
// Verify AUTH
|
||||||
if (!IKEv2VerifyAuth(ike, sa, auth_method, auth_body, auth_sz))
|
if (!IKEv2VerifyAuth(ike, sa, auth_method, auth_body, auth_sz))
|
||||||
{
|
{
|
||||||
@ -1907,19 +1843,7 @@ void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if TS includes transport-mode request in any notify
|
|
||||||
// (scan through all payloads looking for USE_TRANSPORT_MODE)
|
|
||||||
{
|
|
||||||
UCHAR *pp = (UCHAR *)payload_data;
|
|
||||||
while (pp + 4 <= (UCHAR *)payload_data + payload_size)
|
|
||||||
{
|
|
||||||
USHORT pl_total = R16(pp + 2);
|
|
||||||
if (pl_total < 4 || pp + pl_total > (UCHAR *)payload_data + payload_size) break;
|
|
||||||
// We just assume transport mode is acceptable for L2TP connections
|
|
||||||
pp += pl_total;
|
|
||||||
}
|
|
||||||
child_tf.UseTransport = true; // L2TP/IPsec uses transport mode
|
child_tf.UseTransport = true; // L2TP/IPsec uses transport mode
|
||||||
}
|
|
||||||
|
|
||||||
// Generate our SPI for the server->client direction
|
// Generate our SPI for the server->client direction
|
||||||
UINT spi_r = GenerateNewIPsecSaSpi(ike, spi_i);
|
UINT spi_r = GenerateNewIPsecSaSpi(ike, spi_i);
|
||||||
@ -1944,13 +1868,27 @@ void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
|||||||
UCHAR child_sa_buf[512];
|
UCHAR child_sa_buf[512];
|
||||||
UINT child_sa_len;
|
UINT child_sa_len;
|
||||||
|
|
||||||
// IDr payload
|
// IDr payload: echo back what the initiator requested, or use server IP
|
||||||
{
|
{
|
||||||
UCHAR *idr_pl = ip;
|
UINT idr_body_len;
|
||||||
ip[0] = IKEv2_PAYLOAD_AUTH; // next
|
|
||||||
|
if (sa->IDr_Data != NULL && sa->IDr_Data->Size > 0)
|
||||||
|
{
|
||||||
|
// Echo back the initiator's IDr request exactly
|
||||||
|
idr_body_len = sa->IDr_Data->Size;
|
||||||
|
ip[0] = IKEv2_PAYLOAD_AUTH;
|
||||||
|
ip[1] = 0;
|
||||||
|
W16(ip + 2, (USHORT)(4 + idr_body_len));
|
||||||
|
ip += 4;
|
||||||
|
Copy(ip, sa->IDr_Data->Buf, idr_body_len);
|
||||||
|
ip += idr_body_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default: server IP address as IDr
|
||||||
|
idr_body_len = 4 + (IsIP4(&sa->ServerIP) ? 4 : 16);
|
||||||
|
ip[0] = IKEv2_PAYLOAD_AUTH;
|
||||||
ip[1] = 0;
|
ip[1] = 0;
|
||||||
// IDr body: type=1 (IPv4) + reserved(3) + IP address
|
|
||||||
UINT idr_body_len = 4 + (IsIP4(&sa->ServerIP) ? 4 : 16);
|
|
||||||
W16(ip + 2, (USHORT)(4 + idr_body_len));
|
W16(ip + 2, (USHORT)(4 + idr_body_len));
|
||||||
ip += 4;
|
ip += 4;
|
||||||
ip[0] = IsIP4(&sa->ServerIP) ? IKEv2_ID_IPV4_ADDR : IKEv2_ID_IPV6_ADDR;
|
ip[0] = IsIP4(&sa->ServerIP) ? IKEv2_ID_IPV4_ADDR : IKEv2_ID_IPV6_ADDR;
|
||||||
@ -1966,17 +1904,18 @@ void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
|||||||
Copy(ip, sa->ServerIP.address, 16); ip += 16;
|
Copy(ip, sa->ServerIP.address, 16); ip += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AUTH payload
|
// AUTH payload
|
||||||
{
|
{
|
||||||
IKEv2ComputeOurAuth(ike, sa, auth_val, &auth_val_len);
|
IKEv2ComputeOurAuth(ike, sa, auth_val, &auth_val_len);
|
||||||
|
|
||||||
ip[0] = IKEv2_PAYLOAD_SA; // next
|
ip[0] = IKEv2_PAYLOAD_SA;
|
||||||
ip[1] = 0;
|
ip[1] = 0;
|
||||||
W16(ip + 2, (USHORT)(4 + 1 + 3 + auth_val_len));
|
W16(ip + 2, (USHORT)(4 + 1 + 3 + auth_val_len));
|
||||||
ip += 4;
|
ip += 4;
|
||||||
ip[0] = IKEv2_AUTH_PSK; // method
|
ip[0] = IKEv2_AUTH_PSK;
|
||||||
ip[1] = ip[2] = ip[3] = 0; // reserved
|
ip[1] = ip[2] = ip[3] = 0;
|
||||||
ip += 4;
|
ip += 4;
|
||||||
Copy(ip, auth_val, auth_val_len);
|
Copy(ip, auth_val, auth_val_len);
|
||||||
ip += auth_val_len;
|
ip += auth_val_len;
|
||||||
@ -1997,23 +1936,21 @@ void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
|||||||
{
|
{
|
||||||
ip[0] = IKEv2_PAYLOAD_TSr;
|
ip[0] = IKEv2_PAYLOAD_TSr;
|
||||||
ip[1] = 0;
|
ip[1] = 0;
|
||||||
W16(ip + 2, (USHORT)(4 + 4 + 16)); // hdr + ts_count(1)+res(3) + 1 TS entry(16)
|
W16(ip + 2, (USHORT)(4 + 4 + 16));
|
||||||
ip += 4;
|
ip += 4;
|
||||||
ip[0] = 1; ip[1] = 0; ip[2] = 0; ip[3] = 0; // TS count=1
|
ip[0] = 1; ip[1] = 0; ip[2] = 0; ip[3] = 0; // TS count=1
|
||||||
ip += 4;
|
ip += 4;
|
||||||
// TS entry: type(1)+protocol(1)+selector_len(2)+start_port(2)+end_port(2)+start(4)+end(4)
|
|
||||||
ip[0] = IKEv2_TS_IPV4_ADDR_RANGE;
|
ip[0] = IKEv2_TS_IPV4_ADDR_RANGE;
|
||||||
ip[1] = 0; // all protocols
|
ip[1] = 0;
|
||||||
W16(ip + 2, 16); // selector length
|
W16(ip + 2, 16);
|
||||||
W16(ip + 4, 0); // start port
|
W16(ip + 4, 0);
|
||||||
W16(ip + 6, 65535); // end port
|
W16(ip + 6, 65535);
|
||||||
Zero(ip + 8, 4); // start = 0.0.0.0
|
|
||||||
ip[8] = ip[9] = ip[10] = ip[11] = 0;
|
ip[8] = ip[9] = ip[10] = ip[11] = 0;
|
||||||
ip[12] = ip[13] = ip[14] = ip[15] = 0xff; // end = 255.255.255.255
|
ip[12] = ip[13] = ip[14] = ip[15] = 0xff;
|
||||||
ip += 16;
|
ip += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSr payload: same as TSi
|
// TSr payload: same
|
||||||
{
|
{
|
||||||
ip[0] = IKEv2_PAYLOAD_NONE;
|
ip[0] = IKEv2_PAYLOAD_NONE;
|
||||||
ip[1] = 0;
|
ip[1] = 0;
|
||||||
@ -2225,11 +2162,10 @@ void ProcIKEv2PacketRecv(IKE_SERVER *ike, UDPPACKET *p)
|
|||||||
sk_body_len = sk_pl_len - 4 - icv_len;
|
sk_body_len = sk_pl_len - 4 - icv_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
first_inner_pl = payload_start[0]; // next payload inside SK
|
first_inner_pl = payload_start[0]; // SK header's Next Payload = type of first inner payload
|
||||||
|
|
||||||
decrypted = IKEv2DecryptSK(ike, sa, true,
|
decrypted = IKEv2DecryptSK(ike, sa, true,
|
||||||
sk_body, sk_body_len,
|
sk_body, sk_body_len);
|
||||||
&first_inner_pl);
|
|
||||||
if (decrypted == NULL)
|
if (decrypted == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -2239,7 +2175,8 @@ void ProcIKEv2PacketRecv(IKE_SERVER *ike, UDPPACKET *p)
|
|||||||
if (sa->State == IKEv2_SA_STATE_HALF_OPEN)
|
if (sa->State == IKEv2_SA_STATE_HALF_OPEN)
|
||||||
{
|
{
|
||||||
IKEv2ProcAuth(ike, p, hdr, sa,
|
IKEv2ProcAuth(ike, p, hdr, sa,
|
||||||
decrypted->Buf, decrypted->Size);
|
decrypted->Buf, decrypted->Size,
|
||||||
|
first_inner_pl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@ -210,6 +210,10 @@ struct IKEv2_SA
|
|||||||
UCHAR IDi_Type;
|
UCHAR IDi_Type;
|
||||||
BUF *IDi_Data;
|
BUF *IDi_Data;
|
||||||
|
|
||||||
|
// Responder identity (from initiator's optional IDr payload, echoed back)
|
||||||
|
UCHAR IDr_Type;
|
||||||
|
BUF *IDr_Data;
|
||||||
|
|
||||||
// Message ID tracking
|
// Message ID tracking
|
||||||
UINT NextExpectedMsgId;
|
UINT NextExpectedMsgId;
|
||||||
|
|
||||||
@ -240,7 +244,7 @@ int CmpIKEv2SA(void *p1, void *p2);
|
|||||||
|
|
||||||
void IKEv2ProcSAInit(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr);
|
void IKEv2ProcSAInit(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr);
|
||||||
void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr, IKEv2_SA *sa,
|
void IKEv2ProcAuth(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr, IKEv2_SA *sa,
|
||||||
void *payload_data, UINT payload_size);
|
void *payload_data, UINT payload_size, UCHAR first_payload);
|
||||||
void IKEv2ProcInformational(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr, IKEv2_SA *sa,
|
void IKEv2ProcInformational(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr, IKEv2_SA *sa,
|
||||||
void *payload_data, UINT payload_size);
|
void *payload_data, UINT payload_size);
|
||||||
|
|
||||||
@ -272,7 +276,7 @@ void IKEv2SendNotifyError(IKE_SERVER *ike, UDPPACKET *p, IKE_HEADER *hdr,
|
|||||||
BUF *IKEv2EncryptSK(IKE_SERVER *ike, IKEv2_SA *sa, UCHAR next_payload,
|
BUF *IKEv2EncryptSK(IKE_SERVER *ike, IKEv2_SA *sa, UCHAR next_payload,
|
||||||
void *inner, UINT inner_size);
|
void *inner, UINT inner_size);
|
||||||
BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
BUF *IKEv2DecryptSK(IKE_SERVER *ike, IKEv2_SA *sa, bool is_init_sending,
|
||||||
void *sk_data, UINT sk_size, UCHAR *out_next_payload);
|
void *sk_data, UINT sk_size);
|
||||||
|
|
||||||
UINT IKEv2PrfKeyLen(UINT prf_alg);
|
UINT IKEv2PrfKeyLen(UINT prf_alg);
|
||||||
UINT IKEv2PrfOutLen(UINT prf_alg);
|
UINT IKEv2PrfOutLen(UINT prf_alg);
|
||||||
|
|||||||
Reference in New Issue
Block a user