📄 pgpike.c
字号:
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;
PGPikePayload payload,
nextPayload;
PGPUInt16 payLength;
PGPikeProposal * proposal = NULL;
PGPikeSA * sa;
PGPBoolean rcvdSA = FALSE;
PGPBoolean rcvdHash = FALSE;
PGPBoolean found = FALSE;
PGPBoolean sendRL = FALSE;
PGPByte hashPY[kPGPike_MaxHashSize];
PGPHMACContextRef p2hmac = kInvalidPGPHMACContextRef;
PGPikeNDPayload * ndPays = NULL,
* wNDPays;
PGPBoolean sharedKey;
if( ( ( exchange->state == kPGPike_S_MM_WaitSA ) &&
( firstPayload != kPGPike_PY_SA ) ) ||
( ( exchange->state == kPGPike_S_QM_WaitSA ) &&
( ( firstPayload != kPGPike_PY_Hash ) ||
( (PGPikePayload)*mp != kPGPike_PY_SA ) ) ) ||
( ( exchange->state == kPGPike_S_ND_Informational ) &&
partner->ready && ( firstPayload != kPGPike_PY_Hash ) ) )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_InvalidPayload );
goto done;
}
if( PGPCBCContextRefIsValid( partner->cbc ) &&
( ( exchange->exchangeT == kPGPike_EX_IPSEC_Quick ) ||
( ( exchange->exchangeT == kPGPike_EX_Informational ) &&
( firstPayload == kPGPike_PY_Hash ) ) ) )
{
pgpClearMemory( hashPY, kPGPike_MaxHashSize );
err = PGPNewHMACContext( partner->ike->memMgr,
partner->sdkHashAlg,
partner->skeyid_a,
partner->hashSize,
&p2hmac ); CKERR;
if( !exchange->initiator && ( exchange->state == kPGPike_S_QM_WaitHash3 ) )
{
err = PGPContinueHMAC( p2hmac, "\0", 1 ); CKERR;
}
err = PGPContinueHMAC( p2hmac, exchange->messageID,
sizeof(PGPikeMessageID) ); CKERR;
if( exchange->exchangeT == kPGPike_EX_IPSEC_Quick )
{
if( ( exchange->initiator && ( exchange->state == kPGPike_S_QM_WaitSA ) ) ||
( !exchange->initiator && ( exchange->state == kPGPike_S_QM_WaitHash3 ) ) )
err = PGPContinueHMAC( p2hmac, exchange->initNonce,
exchange->initNonceLen );CKERR;
if( !exchange->initiator && ( exchange->state == kPGPike_S_QM_WaitHash3 ) )
err = PGPContinueHMAC( p2hmac, exchange->respNonce,
exchange->respNonceLen );CKERR;
}
}
payload = firstPayload;
while( payload != kPGPike_PY_None )
{
PGPByte * pp,
* ep;
nextPayload = (PGPikePayload)*mp++;
mp++; /* reserved */
payLength = PGPEndianToUInt16( kPGPBigEndian, mp );
mp += sizeof(PGPUInt16);
if( PGPHMACContextRefIsValid( p2hmac ) && ( payload != kPGPike_PY_Hash ) )
{
err = PGPContinueHMAC( p2hmac, mp - kPGPike_ISAKMPPayloadHeaderSize,
payLength ); CKERR;
}
payLength -= kPGPike_ISAKMPPayloadHeaderSize;
pp = mp;
ep = mp + payLength;
switch( payload )
{
case kPGPike_PY_SA:
{
PGPikeDOI doi;
PGPUInt32 situation;
PGPikePayload nextSAPayload;
PGPUInt16 saPayLength;
PGPikeAlert alert = kPGPike_AL_None;
PGPikeProposal * nproposal;
PGPBoolean valid = FALSE;
if( rcvdSA ) /* we only handle one SA payload */
break;
rcvdSA = TRUE;
if( ( exchange->state != kPGPike_S_QM_WaitSA ) &&
( exchange->state != kPGPike_S_MM_WaitSA ) )
goto invalidPayload;
if( !exchange->initiator &&
( exchange->state == kPGPike_S_MM_WaitSA ) )
{
/* save the SA payload body for HASH_X */
pgpAssert( IsNull( exchange->initSABody ) );
exchange->initSABodySize = payLength;
exchange->initSABody = PGPNewData(
exchange->ike->memMgr,
payLength, kPGPMemoryMgrFlags_Clear );
if( IsNull( exchange->initSABody ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( pp, exchange->initSABody, payLength );
}
if( ep - pp < sizeof(PGPUInt32) * 2 )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_UnequalPayloadLengths );
goto done;
}
/* doi */
doi = (PGPikeDOI)PGPEndianToUInt32( kPGPBigEndian, pp );
pp += sizeof( PGPikeDOI );
if( doi != kPGPike_DOI_IPSEC )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_DOIUnsupported );
goto done;
}
/* situation */
situation = PGPEndianToUInt32( kPGPBigEndian, pp );
pp += sizeof( PGPUInt32 );
if( ( situation & kPGPike_IPSEC_SIT_Integrity ) ||
( situation & kPGPike_IPSEC_SIT_Secrecy ) ||
!( situation & kPGPike_IPSEC_SIT_IdentityOnly ))
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_SituationUnsupported );
goto done;
}
/* Proposals */
do
{
nproposal = NULL;
if( ep - pp < kPGPike_ISAKMPPayloadHeaderSize )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_UnequalPayloadLengths );
goto done;
}
nextSAPayload = (PGPikePayload)*pp++; pp++;
saPayLength = PGPEndianToUInt16( kPGPBigEndian, pp ) -
kPGPike_ISAKMPPayloadHeaderSize;
pp += sizeof(PGPUInt16);
err = pgpIKEProcessProposal( &exchange, pp, ep,
&alert, &nproposal );
if( IsPGPError( err ) || ( alert != kPGPike_AL_None ) )
goto done;
if( IsntNull( nproposal ) )
{
PGPikeProposal *wproposal = proposal;
if( IsNull( wproposal ) )
proposal = nproposal;
else
{
while( IsntNull( wproposal->nextProposal ) )
wproposal = wproposal->nextProposal;
wproposal->nextProposal = nproposal;
}
}
pp += saPayLength;
} while( nextSAPayload == kPGPike_PY_Proposal );
if( IsNull( proposal ) )
{
if( alert == kPGPike_AL_None )
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_BadProposal );
goto done;
}
err = pgpIKESelectProposal( exchange, proposal, &valid );CKERR;
if( !valid )
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_NoProposalChoice );
goto done;
}
break;
}
case kPGPike_PY_KeyExchange:
if( ( exchange->state == kPGPike_S_MM_WaitKE ) ||
( exchange->state == kPGPike_S_QM_WaitSA ) )
{
err = pgpIKEProcessKE( &exchange, pp,
payLength );CKERR;
}
else
goto invalidPayload;
break;
case kPGPike_PY_Identification:
if( exchange->exchangeT == kPGPike_EX_IPSEC_Quick )
{
if( exchange->initiator )
{
PGPBoolean goodID = FALSE;
if( !exchange->checkedIDci )
{
if( ( payLength == exchange->idBodySize ) &&
pgpMemoryEqual( pp, exchange->idBody, payLength ) )
{
exchange->checkedIDci = TRUE;
goodID = TRUE;
}
}
else if( !exchange->checkedIDcr )
{
if( ( payLength == exchange->idRBodySize ) &&
pgpMemoryEqual( pp, exchange->idRBody, payLength ) )
{
exchange->checkedIDcr = TRUE;
goodID = TRUE;
}
}
if( !goodID )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( exchange->ike, "\tToo many IDs rcvd.\n" );
#endif
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_InvalidID );
goto done;
}
}
else
{
if( IsNull( exchange->idBody ) )
{
goto saveIDBody;
}
if( IsNull( exchange->idRBody ) )
{
exchange->idRBodySize = payLength;
exchange->idRBody = PGPNewData( exchange->ike->memMgr,
payLength, kPGPMemoryMgrFlags_Clear );
if( IsNull( exchange->idBody ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( pp, exchange->idRBody, payLength );
}
else
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( exchange->ike, "\tToo many IDs rcvd.\n" );
#endif
err = pgpIKEAbortExchange( &exchange, kPGPike_AL_InvalidID );
goto done;
}
}
}
else
{
PGPByte ipProtocol;
PGPUInt16 ipPort;
saveIDBody:
/* save the ID payload for HASH_X */
if( IsntNull( exchange->idBody ) )
{
(void)PGPFreeData( exchange->idBody );
exchange->idBody = NULL;
}
exchange->idBodySize = payLength;
exchange->idBody = PGPNewData( exchange->ike->memMgr,
payLength, kPGPMemoryMgrFlags_Clear );
if( IsNull( exchange->idBody ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
pgpCopyMemory( pp, exchange->idBody, payLength );
#if PGPIKE_DEBUG
pgpIKEDebugLog( exchange->ike,
"\tRemote ID: %s\n", pgpIKEIDTypeString( (PGPipsecIdentity)*pp ) );
#endif
*pp++;
ipProtocol = *pp++;
ipPort = PGPEndianToUInt16( kPGPBigEndian, pp );
pp += sizeof(PGPUInt16);
if( ( exchange->exchangeT != kPGPike_EX_IPSEC_Quick ) &&
( ( ( ipProtocol != 0 ) && (ipProtocol != kPGPike_IPProtocolUDP ) ) ||
( ( ipPort != 0 ) && ( ipPort != kPGPike_CommonPort ) ) ) )
{
err = pgpIKEAbortExchange( &exchange, kPGPike_AL_InvalidID );
goto done;
}
}
break;
case kPGPike_PY_Certificate:
if( ( exchange->state == kPGPike_S_MM_WaitFinal ) &&
( ( exchange->proposals->t[0].u.ike.authMethod ==
kPGPike_AM_DSS_Sig ) ||
( exchange->proposals->t[0].u.ike.authMethod ==
kPGPike_AM_RSA_Sig ) ) )
{
err = pgpIKEProcessCert( &exchange, pp, payLength );CKERR;
}
else
goto invalidPayload;
break;
case kPGPike_PY_Signature:
if( ( exchange->state == kPGPike_S_MM_WaitFinal ) &&
( ( exchange->proposals->t[0].u.ike.authMethod ==
kPGPike_AM_DSS_Sig ) ||
( exchange->proposals->t[0].u.ike.authMethod ==
kPGPike_AM_RSA_Sig ) ) )
{
err = pgpIKEProcessSig( &exchange, pp, payLength );CKERR;
}
else
goto invalidPayload;
break;
case kPGPike_PY_CertRequest:
err = pgpIKEProcessCertRequest( &exchange, pp, payLength );CKERR;
break;
case kPGPike_PY_Hash:
if( !rcvdHash && ( partner->hashSize == payLength ) )
{
switch( exchange->state )
{
case kPGPike_S_MM_WaitFinal:
switch( exchange->proposals->t[0].u.ike.authMethod )
{
case kPGPike_AM_PreSharedKey:
case kPGPike_AM_RSA_Encrypt:
case kPGPike_AM_RSA_Encrypt_R:
{
PGPByte lHash[kPGPike_MaxHashSize];
err = pgpIKEGetAuthHash( exchange,
(PGPBoolean)!exchange->initiator,
lHash ); CKERR;
if( pgpMemoryEqual( lHash, pp,
partner->hashSize ) )
{
partner->authenticated = TRUE;
}
else
{
err = pgpIKEAbortExchange( &exchange,
kPGPike_AL_AuthenticationFailed );
goto done;
}
break;
}
default:
goto invalidPayload;
}
break;
case kPGPike_S_QM_WaitSA:
case kPGPike_S_QM_WaitHash3:
case kPGPike_S_ND_Informational:
pgpCopyMemory( pp, hashPY, payLength );
break;
default:
goto invalidPayload;
}
rcvdHash = TRUE;
}
else
goto invalidPayload;
break;
case kPGPike_PY_Nonce:
if( ( exchange->state == kPGPike_S_MM_WaitKE ) ||
( exchange->state == kPGPike_S_QM_WaitSA ) )
{
if( ( payLength >= kPGPike_MinNonceSize ) &&
( payLength <= kPGPike_MaxNonceSize ) )
{
if( exchange->initiator )
{
exchange->respNonceLen = payLength;
pgpCopyMemory( pp, exchange->respNonce,
payLength );
}
else
{
exchange->initNonceLen = payLength;
pgpCopyMemory( pp, exchange->initNonce,
payLength );
}
}
else
goto invalidPayload;
}
else
goto invalidPayload;
break;
case kPGPike_PY_Notification:
case kPGPike_PY_Delete:
{
PGPikeNDPayload * newND;
/* save off the notify and delete payloads to make
sure the QM hash is approved prior to action */
newND = PGPNewData( exchange->ike->memMgr,
sizeof(PGPikeNDPayload), kPGPMemoryMgrFlags_Clear );
if( IsntNull( newND ) )
newND->pay = PGPNewData( exchange->ike->memMgr,
payLength, 0 );
if( IsntNull( newND ) && IsntNull( newND->pay ) )
{
pgpCopyMemory( pp, newND->pay, payLength );
newND->payLen = payLength;
newND->payType = payload;
newND->nextND = ndPays;
ndPays = newND;
}
else
{
err = kPGPError_OutOfMemory;
goto done;
}
break;
}
case kPGPike_PY_VendorID:
{
PGPSize vidSize = strlen( kPGPike_PGPVendorString1 );
if( pgpMemoryEqual( kPGPike_PGPVendorString1, pp, vidSize ) )
{
partner->remotePGPVersion = 1;
if( payLength > vidSize )
{
partner->remotePGPVersion = 2;
#if PGPIKE_DEBUG
pgpIKEDebugLog( exchange->ike, "\tDetected PGPikeV2\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -