📄 pgpike.c
字号:
PGPByte rawOut[32];
/* cookie recipe per draft-ietf-ipsec-isakmp-10, 2.5.3 */
if( !ike->cookieDough )
{
err = PGPContextGetRandomBytes( ike->pgpContext, &ike->cookieSecret,
kPGPike_CookieSize ); CKERR;
ike->cookieDough = TRUE;
}
err = PGPNewHashContext( ike->pgpContext, kPGPHashAlgorithm_SHA, &hash); CKERR;
(void)PGPContinueHash( hash, &srcAddress, sizeof(srcAddress) );
(void)PGPContinueHash( hash, &destAddress, sizeof(destAddress) );
(void)PGPContinueHash( hash, &port, sizeof(port) ); /* srcPort */
(void)PGPContinueHash( hash, &port, sizeof(port) ); /* destPort */
(void)PGPContinueHash( hash, &ike->cookieSecret, sizeof(ike->cookieSecret) );
(void)PGPContinueHash( hash, &now, sizeof(now) );
(void)PGPFinalizeHash( hash, rawOut );
pgpCopyMemory( rawOut, outCookie, kPGPike_CookieSize );
done:
if( PGPHashContextRefIsValid( hash ) )
PGPFreeHashContext( hash );
return err;
}
/* The Mighty ISAKMP Packet Interpreter */
PGPError
pgpIKEHandlePacket(
PGPikeContextPriv * ike,
PGPikeMTPacket * packet )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner;
PGPikeExchange * exchange;
PGPByte * mp;
PGPByte * ep;
PGPSize mLen;
PGPBoolean valid = FALSE;
PGPBoolean startP1 = FALSE;
PGPikeCookie initCookie,
respCookie;
PGPikePayload firstPayload;
PGPikeExchangeT exchangeT;
PGPikeMessageID messageID;
PGPUInt8 flags;
PGPUInt32 thisCksm = 0;
PGPByte noMessageID[4] = { 0, 0, 0, 0 };
PGPByte noCookie[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
err = pgpIKEHeaderSniffer( ike, packet, &valid );
if( !valid )
goto done;
mp = packet->packet;
mLen = packet->packetSize;
ep = mp + mLen;
pgpCopyMemory( mp, initCookie, sizeof( PGPikeCookie ) );
mp += sizeof( PGPikeCookie );
pgpCopyMemory( mp, respCookie, sizeof( PGPikeCookie ) );
mp += sizeof( PGPikeCookie );
firstPayload = (PGPikePayload) *mp++; mp++;
exchangeT = (PGPikeExchangeT) *mp++;
flags = *mp++;
pgpCopyMemory( mp, messageID, sizeof( PGPikeMessageID ) );
mp += sizeof( PGPikeMessageID );
mp += sizeof( PGPUInt32 ); /* length checked by pgpIKEHeaderSniffer */
if( ( ( exchangeT == kPGPike_EX_Identity ) || ( exchangeT == kPGPike_EX_Aggressive ) ) &&
( firstPayload == kPGPike_PY_SA ) &&
pgpMemoryEqual( &messageID, &noMessageID, sizeof(PGPikeMessageID) ) )
startP1 = TRUE;
if( startP1 && ( ike->numExchanges >= kPGPike_MaxExchanges ) )
{
err = pgpIKELocalAlert( ike, packet->ipAddress,
kPGPike_AL_None, kPGPike_IA_TooManyExchanges, FALSE );
goto done;
}
for( partner = ike->partner; IsntNull( partner ); partner = partner->nextPartner )
if( ( partner->ipAddress == packet->ipAddress ) &&
pgpMemoryEqual( initCookie, partner->initCookie, sizeof(PGPikeCookie) ) &&
pgpMemoryEqual( respCookie, partner->respCookie, sizeof(PGPikeCookie) ) )
break;
if( IsNull( partner ) )
{
for( partner = ike->partner; IsntNull( partner ); partner = partner->nextPartner )
if( ( partner->ipAddress == packet->ipAddress ) &&
( ( exchangeT == kPGPike_EX_Informational ) ||
pgpMemoryEqual( initCookie, partner->initCookie, sizeof(PGPikeCookie) ) ) &&
( startP1 || ( exchangeT == kPGPike_EX_Informational ) ||
pgpMemoryEqual( respCookie, partner->respCookie, sizeof(PGPikeCookie) )) )
break;
}
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "Rcvd: %sexchange=%s, firstPayload=%s%s%s, port=%u\n",
( flags & kPGPike_ISAKMPEncryptBit ) ? "(E):" : "",
pgpIKEExchangeTypeString(exchangeT),
pgpIKEPayloadTypeString(firstPayload),
( flags & kPGPike_ISAKMPCommitBit ) ? ", Commit" : "",
( flags & kPGPike_ISAKMPAuthOnlyBit ) ? ", AuthOnly" : "",
(PGPUInt32)packet->port );
#endif
if( IsNull( partner ) )
{
if( startP1 )
{
PGPikeMTSASetup msg;
if( !pgpMemoryEqual( respCookie, noCookie, sizeof(PGPikeCookie) ) )
{
#if PGPIKE_DEBUG
{
char ip1Str[20];
pgpIKEGetIPString( packet->ipAddress, ip1Str );
pgpIKEDebugLog( ike, TRUE, "\tALERT(R): Found ancient cookie from %s (discarded)\n", ip1Str );
}
#endif
goto done;
}
pgpClearMemory( &msg, sizeof(PGPikeMTSASetup) );
msg.ipAddress = packet->ipAddress;
err = (ike->msgProc)( (PGPikeContextRef)ike, ike->userData,
kPGPike_MT_PolicyCheck, &msg );CKERR;
if( msg.approved )
{
if( ( ( exchangeT == kPGPike_EX_Aggressive ) && !msg.aggressive ) ||
( !( exchangeT == kPGPike_EX_Aggressive ) && msg.aggressive ) )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "Aggressive mode mismatch\n" );
#endif
err = pgpIKELocalAlert( ike, packet->ipAddress,
kPGPike_AL_InvalidExchange, kPGPike_IA_None, FALSE );
goto done;
}
err = pgpIKECreatePartner( ike, &msg, FALSE, &partner );CKERR;
err = pgpIKECreateExchange( partner, exchangeT, NULL,
( exchangeT == kPGPike_EX_Aggressive ) ?
kPGPike_S_AM_WaitSA : kPGPike_S_MM_WaitSA, FALSE,
&exchange );CKERR;
pgpCopyMemory( initCookie, partner->initCookie, kPGPike_CookieSize );
partner->destPort = packet->port;
if(( packet->port != kPGPike_CommonPort ) &&
!IsNATTraversalVendorIDStringPresent(packet->packet, packet->packetSize))
{
pgpIKEAbortExchange( &exchange, kPGPike_AL_NATTranslationFailure );
partner = NULL;
}
}
}
else
{
err = pgpIKELocalAlert( ike, packet->ipAddress,
kPGPike_AL_InvalidExchange, kPGPike_IA_None, FALSE );
goto done;
}
}
else
{
if( startP1 )
{
if( !partner->ready && partner->initiator &&
IsntNull( partner->exchanges ) )
{
if( ( ( partner->exchanges->exchangeT == kPGPike_EX_Aggressive ) &&
( partner->exchanges->state == kPGPike_S_AM_WaitSA ) ) ||
( ( partner->exchanges->exchangeT == kPGPike_EX_Identity ) &&
( partner->exchanges->state == kPGPike_S_MM_WaitSA ) ) )
pgpCopyMemory( respCookie, partner->respCookie, kPGPike_CookieSize );
else
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "\tDetected repeat packet(1)\n" );
#endif
partner->rttMillisec *= 2;
if( partner->rttMillisec > kPGPike_MaxRoundTrip )
partner->rttMillisec = kPGPike_MaxRoundTrip;
goto done;
}
}
else
{
err = pgpIKELocalAlert( ike, partner->ipAddress,
kPGPike_AL_InvalidCookie, kPGPike_IA_None, FALSE );
goto done;
}
}
else if( !pgpMemoryEqual( respCookie, partner->respCookie,
kPGPike_CookieSize ) )
{
/* Force informational exchanges to be encrypted if the
Phase 1 SA has been setup. */
if( ( exchangeT == kPGPike_EX_Informational ) && !partner->ready )
{
/* super lame versions of IKE send notifications about Phase 1
negotiations without any of the cookies */
/*pgpCopyMemory( respCookie, partner->respCookie, kPGPike_CookieSize );*/
}
else
{
err = pgpIKELocalAlert( ike, partner->ipAddress,
kPGPike_AL_InvalidCookie, kPGPike_IA_None, FALSE );
goto done;
}
}
}
if( IsntNull( partner ) )
{
PGPBoolean found = FALSE;
/* find the exchange */
for( exchange = partner->exchanges; IsntNull( exchange );
exchange = exchange->nextExchange )
{
if( ( exchange->exchangeT == exchangeT ) &&
pgpMemoryEqual( &exchange->messageID, messageID,
sizeof( PGPikeMessageID ) ) )
{
found = TRUE;
break;
}
}
if( !found )
{
if( startP1 )
{
err = pgpIKECreateExchange( partner, exchangeT, NULL,
( exchangeT == kPGPike_EX_Aggressive ) ?
kPGPike_S_AM_WaitSA : kPGPike_S_MM_WaitSA, FALSE,
&exchange );CKERR;
}
else if( ( exchangeT == kPGPike_EX_Informational ) ||
( ( ( exchangeT == kPGPike_EX_IPSEC_Quick ) ||
( exchangeT == kPGPike_EX_Transaction ) ) &&
partner->ready ) )
{
if( exchangeT == kPGPike_EX_IPSEC_Quick )
{
PGPUInt32 exchIndex;
for( exchIndex = 0; exchIndex < kPGPike_MaxOldExchanges; exchIndex++ )
{
if( pgpMemoryEqual( &partner->oldMessageID[exchIndex], messageID, sizeof(PGPikeMessageID) ) )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "\tRemote tried to recycle MessageID, protocol violation\n" );
#endif
goto done;
}
}
}
err = pgpIKECreateExchange( partner, exchangeT, &messageID,
( exchangeT == kPGPike_EX_IPSEC_Quick ) ?
kPGPike_S_QM_WaitSA : kPGPike_S_ND_OneState,
FALSE, &exchange ); CKERR;
if( exchangeT == kPGPike_EX_IPSEC_Quick )
{
exchange->destination = (PGPikePendingDest *)PGPNewData( ike->memMgr,
sizeof(PGPikePendingDest), kPGPMemoryMgrFlags_Clear );
if( IsNull( exchange->destination ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
exchange->destination->ipAddrStart = 0;
exchange->destination->ipMaskEnd = 0;
exchange->destination->destIsRange = FALSE;
exchange->destination->ipPort = 0;
exchange->destination->ipProtocol = 0;
}
}
else
{
err = pgpIKELocalAlert( ike, partner->ipAddress,
kPGPike_AL_InvalidMessageID, kPGPike_IA_None, FALSE );
goto done;
}
}
pgpAssertAddrValid( exchange, PGPikeExchange * );
{
PGPByte * cp,
* ecp;
cp = packet->packet;
ecp = cp + packet->packetSize;
while( cp < ecp )
thisCksm += *cp++;
}
/* Check for repeat packets because this silly protocol
doesn't have sequence numbers */
if( ( packet->packetSize == exchange->lastRcvdLength ) &&
( thisCksm == exchange->lastRcvdCksm ) )
{
/* just let ourselves time out because we may have already resent */
partner->rttMillisec *= 2;
if( partner->rttMillisec > kPGPike_MaxRoundTrip )
partner->rttMillisec = kPGPike_MaxRoundTrip;
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "\tDetected repeat packet(2)\n" );
#endif
goto done;
}
exchange->lastRcvdLength = packet->packetSize;
exchange->lastRcvdCksm = thisCksm;
/* average in estimate of round trip time */
if( exchange->lastTransmit )
{
if( partner->rttMillisec )
{
partner->rttMillisec += PGPGetMilliseconds() - exchange->lastTransmit;
partner->rttMillisec /= 2;
}
else
{
partner->rttMillisec = PGPGetMilliseconds() - exchange->lastTransmit;
}
if( partner->rttMillisec > kPGPike_MaxRoundTrip )
partner->rttMillisec = kPGPike_MaxRoundTrip;
}
if( flags & kPGPike_ISAKMPEncryptBit )
{
if( PGPCBCContextRefIsValid( partner->cbc ) )
{
#if PGPIKE_VERBOSE
pgpIKEDebugData( partner->ike, "iv", exchange->lastCBC, partner->cipherBlockSize );
#endif
err = PGPInitCBC( partner->cbc, partner->cipherKey,
exchange->lastCBC ); CKERR;
/* Save the IV for the next packet */
pgpCopyMemory( ep - partner->cipherBlockSize,
exchange->lastCBC, partner->cipherBlockSize );
if( ( exchange->exchangeT == kPGPike_EX_Identity ) ||
( exchange->exchangeT == kPGPike_EX_Aggressive ) )
pgpCopyMemory( exchange->lastCBC,
partner->lastP1CBC, partner->cipherBlockSize );
/* Decrypt packet */
err = PGPCBCDecrypt( partner->cbc,
packet->packet + kPGPike_ISAKMPHeaderSize,
mLen - kPGPike_ISAKMPHeaderSize,
packet->packet + kPGPike_ISAKMPHeaderSize );CKERR;
}
else
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_InvalidPayload );CKERR;
}
}
if( flags & kPGPike_ISAKMPCommitBit )
{
exchange->needsCommit = TRUE;
}
if( flags & kPGPike_ISAKMPAuthOnlyBit )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "\tDetected auth-only IKE, rejecting\n" );
#endif
goto done;
}
err = pgpIKEPayloadLengthCheck( partner, firstPayload, mp, ep, &valid ); CKERR;
if( !valid )
{
if( exchange->exchangeT != kPGPike_EX_Informational )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_UnequalPayloadLengths ); CKERR;
}
else
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, TRUE, "\tNotify decryption failed (discarded)\n" );
#endif
err = pgpIKELocalAlert( ike, partner->ipAddress,
kPGPike_AL_UnequalPayloadLengths, kPGPike_IA_None, FALSE );
goto done;
}
}
/* OK, everything looks cool, now on to the payloads */
err = pgpIKEProcessPayloads( exchange, firstPayload, mp );CKERR;
}
done:
return err;
}
PGPError
pgpIKEProcessPayloads(
PGPikeExchange * exchange,
PGPikePayload firstPayload,
PGPByte * mp )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner = exchange->partner,
* oPartner;
PGPikePayload payload,
nextPayload;
PGPUInt16 payLength;
PGPikeProposal * proposal = NULL;
PGPipsecSA * sa;
PGPBoolean rcvdSA = FALSE;
PGPBoolean rcvdHash = FALSE;
PGPBoolean found = FALSE;
PGPBoolean sendRL = FALSE;
PGPBoolean rcvdLocalNatDiscoveryPayload = FALSE;
PGPBoolean bFoundRemoteHashMatch = FALSE;
PGPByte hashPY[kPGPike_MaxHashSize];
PGPHMACContextRef p2hmac = kInvalidPGPHMACContextRef;
PGPikeNDPayload * ndPays = NULL,
* wNDPays;
PGPBoolean sharedKey;
PGPikeMTAuthCheck * authCheck = NULL;
if( ( ( ( exchange->state == kPGPike_S_MM_WaitSA ) ||
( exchange->state == kPGPike_S_AM_WaitSA ) ) &&
( firstPayload != kPGPike_PY_SA ) ) ||
( ( exchange->state == kPGPike_S_QM_WaitSA ) &&
( ( firstPayload != kPGPike_PY_Hash ) ||
( (PGPikePayload)*mp != kPGPike_PY_SA ) ) ) )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_InvalidPayload );
goto done;
}
if( ( exchange->state == kPGPike_S_ND_OneState ) &&
partner->ready && ( firstPayload != kPGPike_PY_Hash ) )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( partner->ike, TRUE, "\tRcvd unencrypted Notify linked to P1 (discarded)\n" );
#endif
err = pgpIKELocalAlert( exchange->ike, partner->ipAddress,
kPGPike_AL_PayloadMalformed, kPGPike_IA_None, FALSE );
goto done;
}
if( PGPCBCContextRefIsVal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -