📄 pgpike.c
字号:
if( IsNull( exchange ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
partner->ike->numExchanges++;
exchange->ike = partner->ike;
exchange->partner = partner;
exchange->initiator = initiator;
exchange->state = state;
exchange->doi = kPGPike_DOI_IPSEC;
exchange->exchangeT = exchangeT;
if( ( exchangeT == kPGPike_EX_IPSEC_Quick ) ||
( ( exchangeT == kPGPike_EX_Informational ) && partner->ready ) )
{
PGPByte p2iv[kPGPike_MaxHashSize];
if( IsNull( messageID ) )
{
err = PGPContextGetRandomBytes( partner->ike->pgpContext,
&exchange->messageID,
sizeof(PGPikeMessageID) ); CKERR;
}
else
{
pgpCopyMemory( messageID, exchange->messageID,
sizeof(PGPikeMessageID) );
}
/* Set the last CBC block to correct value for a new P1/P2 exchange */
err = PGPNewHashContext( partner->ike->memMgr,
partner->sdkHashAlg, &hash ); CKERR;
err = PGPContinueHash( hash, partner->lastP1CBC,
kPGPike_MaxCipherBlockSize ); CKERR;
err = PGPContinueHash( hash, &exchange->messageID,
sizeof(PGPikeMessageID) ); CKERR;
err = PGPFinalizeHash( hash, p2iv ); CKERR;
pgpCopyMemory( p2iv, exchange->lastCBC, partner->cipherBlockSize );
}
if( IsNull( partner->exchanges ) )
partner->exchanges = exchange;
else
{
PGPikeExchange *cn = partner->exchanges;
while( IsntNull( cn->nextExchange ) )
cn = cn->nextExchange;
cn->nextExchange = exchange;
}
*exchangeP = exchange;
done:
if( PGPHashContextRefIsValid( hash ) )
(void)PGPFreeHashContext( hash );
if( IsPGPError( err ) )
(void)PGPFreeData( exchange );
return err;
}
PGPError
pgpIKECreatePartner(
PGPikeContextPriv * ike,
PGPikeMTSASetup * setup,
PGPBoolean initiator,
PGPikePartner ** partnerP )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner;
pgpAssert( IsntNull( setup ) );
pgpAssert( IsntNull( partnerP ) );
*partnerP = NULL;
partner = PGPNewData( ike->memMgr, sizeof(PGPikePartner),
kPGPMemoryMgrFlags_Clear );
if( IsntNull( partner ) )
{
partner->magic = kPGPike_Magic;
partner->rttMillisec = kPGPike_RoundTripSlack * 2;
partner->ike = ike;
partner->ipAddress = setup->ipAddress;
partner->localIPAddress = setup->localIPAddress;
partner->initiator = initiator;
partner->birthTime = PGPGetTime();
if( initiator )
err = pgpIKEBakeCookie( ike, setup->ipAddress, setup->localIPAddress,
&partner->initCookie[0] );
else
err = pgpIKEBakeCookie( ike, setup->ipAddress, setup->localIPAddress,
&partner->respCookie[0] );
CKERR;
partner->sharedKeySize = setup->sharedKeySize;
if( IsntNull( setup->sharedKey ) )
{
partner->sharedKey = PGPNewSecureData( ike->memMgr,
setup->sharedKeySize, kPGPMemoryMgrFlags_Clear );
if( IsntNull( partner->sharedKey ) )
pgpCopyMemory( setup->sharedKey,
partner->sharedKey,
setup->sharedKeySize );
else
{
err = kPGPError_OutOfMemory;
goto done;
}
}
pgpCopyMemory( &setup->u.ipsec, &partner->ipsecOpts,
sizeof(PGPipsecDOIOptions) );
partner->ipsecOpts.ipAddrStart &= partner->ipsecOpts.ipMaskEnd;
if( IsntNull( setup->u.ipsec.idData ) )
{
partner->ipsecOpts.idData = NULL;
partner->ipsecOpts.idData = PGPNewData( ike->memMgr,
partner->ipsecOpts.idDataSize,
kPGPMemoryMgrFlags_Clear );
if( IsNull( partner->ipsecOpts.idData ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( setup->u.ipsec.idData, partner->ipsecOpts.idData,
partner->ipsecOpts.idDataSize );
}
err = pgpIKEGetCert( partner, kPGPike_MT_LocalPGPCert ); CKERR;
err = pgpIKEGetCert( partner, kPGPike_MT_LocalX509Cert ); CKERR;
/* we're all set, hook it into our partners list */
partner->nextPartner = ike->partner;
ike->partner = partner;
*partnerP = partner;
}
else
err = kPGPError_OutOfMemory;
done:
if( IsPGPError(err) && IsntNull( partner ) )
pgpIKEFreePartner( partner );
return err;
}
PGPError
pgpIKEBakeCookie(
PGPikeContextPriv * ike,
PGPUInt32 destAddress,
PGPUInt32 srcAddress,
PGPByte * outCookie )
{
PGPError err = kPGPError_NoErr;
PGPHashContextRef hash = kInvalidPGPHashContextRef;
PGPUInt16 port = kPGPike_CommonPort;
PGPTime now = PGPGetTime();
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->memMgr, 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 };
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 ) &&
( 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) ) &&
( startP1 ||
pgpMemoryEqual( respCookie, partner->respCookie, sizeof(PGPikeCookie) )) )
break;
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, "Rcvd: %sexchange=%s, firstPayload=%s%s%s\n",
( flags & kPGPike_ISAKMPEncryptBit ) ? "(E):" : "",
pgpIKEExchangeTypeString(exchangeT),
pgpIKEPayloadTypeString(firstPayload),
( flags & kPGPike_ISAKMPCommitBit ) ? ", Commit" : "",
( flags & kPGPike_ISAKMPAuthOnlyBit ) ? ", AuthOnly" : "" );
#endif
if( IsNull( partner ) )
{
if( startP1 )
{
PGPikeMTSASetup msg;
pgpClearMemory( &msg, sizeof(PGPikeMTSASetup) );
msg.ipAddress = packet->ipAddress;
err = (ike->msgProc)( (PGPikeContextRef)ike, ike->userData,
kPGPike_MT_PolicyCheck, &msg );CKERR;
if( msg.approved )
{
err = pgpIKECreatePartner( ike, &msg, FALSE, &partner );CKERR;
err = pgpIKECreateExchange( partner, kPGPike_EX_Identity, NULL,
kPGPike_S_MM_WaitSA, FALSE,
&exchange );CKERR;
pgpCopyMemory( initCookie, partner->initCookie, kPGPike_CookieSize );
}
}
else
{
if( ( exchangeT == kPGPike_EX_Informational ) &&
( firstPayload == kPGPike_PY_Notification ) &&
!( flags & kPGPike_ISAKMPEncryptBit ) &&
( *mp++ == kPGPike_PY_None ) )
{
PGPikeNDPayload nd;
mp++; /* reserved */
nd.nextND = NULL;
nd.payType = kPGPike_PY_Notification;
nd.payLen = PGPEndianToUInt16( kPGPBigEndian, mp ) -
kPGPike_ISAKMPPayloadHeaderSize;
mp += sizeof(PGPUInt16);
nd.pay = mp;
err = pgpIKEProcessInformational( ike, packet->ipAddress,
NULL, &nd ); CKERR;
}
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->state == kPGPike_S_MM_WaitSA )
pgpCopyMemory( respCookie, partner->respCookie, kPGPike_CookieSize );
else
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, "\tDetected repeat packet(1)\n" );
#endif
partner->rttMillisec *= 2;
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 ) )
{
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, kPGPike_EX_Identity, NULL,
kPGPike_S_MM_WaitSA, FALSE,
&exchange );CKERR;
}
else if( ( exchangeT == kPGPike_EX_Informational ) ||
( ( exchangeT == kPGPike_EX_IPSEC_Quick ) &&
partner->ready ) )
{
err = pgpIKECreateExchange( partner, exchangeT, &messageID,
( exchangeT == kPGPike_EX_Informational ) ?
kPGPike_S_ND_Informational : kPGPike_S_QM_WaitSA,
FALSE, &exchange ); CKERR;
}
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 PGPIKE_DEBUG
pgpIKEDebugLog( ike, "\tDetected repeat packet(2)\n" );
#endif
goto done;
}
exchange->lastRcvdLength = packet->packetSize;
exchange->lastRcvdCksm = thisCksm;
/* average in estimate of round trip time */
if( partner->rttMillisec )
{
partner->rttMillisec += PGPGetMilliseconds() - exchange->lastTransmit;
partner->rttMillisec /= 2;
}
else if( exchange->lastTransmit )
{
partner->rttMillisec = PGPGetMilliseconds() - exchange->lastTransmit;
}
if( flags & kPGPike_ISAKMPEncryptBit )
{
if( PGPCBCContextRefIsValid( partner->cbc ) )
{
err = PGPInitCBC( partner->cbc, partner->cipherKey,
exchange->lastCBC ); CKERR;
/* Save the IV for the next packet */
pgpCopyMemory( ep - kPGPike_MaxCipherBlockSize,
exchange->lastCBC, kPGPike_MaxCipherBlockSize );
if( ( exchange->exchangeT == kPGPike_EX_Identity ) ||
( exchange->exchangeT == kPGPike_EX_Aggressive ) )
pgpCopyMemory( exchange->lastCBC,
partner->lastP1CBC, kPGPike_MaxCipherBlockSize );
/* 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, "\tDetected auth-only IKE, rejecting\n" );
#endif
goto done;
}
err = pgpIKEPayloadLengthCheck( partner, firstPayload, mp, ep,
&valid ); CKERR;
if( !valid )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_UnequalPayloadLengths ); CKERR;
}
/* OK, everything looks cool, now on to the payloads */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -