📄 pgpike.c
字号:
err = kPGPError_NoErr;
else
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, "pgpIKE PGPError: %ld\n", err );
#endif
}
}
return err;
}
PGPError
pgpIKEFindSAPartner(
PGPikeContextPriv * ike,
PGPikeSA * sa,
PGPBoolean mustBeReady,
PGPikePartner ** partnerP )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner;
*partnerP = NULL;
for( partner = ike->partner; IsntNull( partner );
partner = partner->nextPartner )
{
if( ( sa->ipAddress == partner->ipAddress ) &&
( partner->ready || !mustBeReady ) &&
( sa->ipAddrStart == partner->ipsecOpts.ipAddrStart ) &&
( sa->ipMaskEnd == partner->ipsecOpts.ipMaskEnd ) &&
( sa->destIsRange == partner->ipsecOpts.destIsRange ) )
{
*partnerP = partner;
goto done;
}
}
err = kPGPError_ItemNotFound;
done:
return err;
}
PGPError
pgpIKEFreeSA(
PGPikeContextPriv * ike,
PGPikeSA * sa )
{
PGPError err = kPGPError_NoErr;
err = pgpIKELocalAlert( ike, sa->ipAddress,
kPGPike_AL_None, kPGPike_IA_DeadPhase2SA, FALSE );
if( IsntNull( sa->prevSA ) )
sa->prevSA->nextSA = sa->nextSA;
else
ike->sa = sa->nextSA;
if( IsntNull( sa->nextSA ) )
sa->nextSA->prevSA = sa->prevSA;
(void)PGPFreeData( sa );
return err;
}
PGPError
pgpIKEHandleSAEvent(
PGPikeContextPriv * ike,
PGPBoolean death,
PGPikeSA * sa )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner;
PGPikeExchange * exchange;
if( IsntPGPError( pgpIKEFindSAPartner( ike, sa, TRUE, &partner ) ) )
{
if( death )
{
err = pgpIKEKillSA( &partner, sa ); CKERR;
}
else if( IsNull( partner->exchanges ) )
{
PGPikeSA * oSA;
PGPBoolean found = FALSE;
for( oSA = ike->sa; IsntNull( oSA ); oSA = oSA->nextSA )
{
if( ( oSA->ipAddress == sa->ipAddress ) && ( sa != oSA ) &&
( oSA->ipAddrStart == sa->ipAddrStart ) &&
( oSA->ipMaskEnd == sa->ipMaskEnd ) &&
( oSA->destIsRange == sa->destIsRange ) )
{
found = TRUE;
break;
}
}
if( !found )
{
err = pgpIKEStartQMExchange( partner, &exchange ); CKERR;
}
}
}
done:
return err;
}
PGPError
pgpIKESetPref(
PGPikeContextPriv * ike,
PGPikeMTPref * pref )
{
PGPError err = kPGPError_NoErr;
switch( pref->pref )
{
case kPGPike_PF_Expiration:
ike->secLifeTimeIKE = pref->u.expiration.secLifeTimeIKE;
if( ike->secLifeTimeIKE && ( ike->secLifeTimeIKE < 60 ) )
ike->secLifeTimeIKE = 60;
ike->kbLifeTimeIKE = pref->u.expiration.kbLifeTimeIKE;
if( ike->kbLifeTimeIKE && ( ike->kbLifeTimeIKE < kPGPike_KBLifeMinimum ) )
ike->kbLifeTimeIKE = kPGPike_KBLifeMinimum;
ike->secLifeTimeIPSEC = pref->u.expiration.secLifeTimeIPSEC;
if( ike->secLifeTimeIPSEC && ( ike->secLifeTimeIPSEC < 60 ) )
ike->secLifeTimeIPSEC = 60;
ike->kbLifeTimeIPSEC = pref->u.expiration.kbLifeTimeIPSEC;
if( ike->kbLifeTimeIPSEC && ( ike->kbLifeTimeIPSEC < kPGPike_KBLifeMinimum ) )
ike->kbLifeTimeIPSEC = kPGPike_KBLifeMinimum;
break;
case kPGPike_PF_IKEProposals:
if( IsntNull( ike->defaultIKEProps ) )
{
err = pgpContextMemFree( ike->pgpContext,
ike->defaultIKEProps );CKERR;
}
ike->defaultIKEProps = (PGPikeTransform *)
pgpContextMemAlloc( ike->pgpContext,
sizeof(PGPikeTransform) * pref->u.ikeProposals.numTransforms,
kPGPMemoryMgrFlags_Clear );
if( IsNull( ike->defaultIKEProps ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
ike->numIKEProps = pref->u.ikeProposals.numTransforms;
pgpCopyMemory( pref->u.ikeProposals.t, ike->defaultIKEProps,
ike->numIKEProps * sizeof(PGPikeTransform) );
break;
case kPGPike_PF_IPSECProposals:
if( IsntNull( ike->defaultIPSECProps ) )
{
err = pgpContextMemFree( ike->pgpContext,
ike->defaultIPSECProps );CKERR;
}
ike->defaultIPSECProps = (PGPipsecTransform *)
pgpContextMemAlloc( ike->pgpContext,
sizeof(PGPipsecTransform) * pref->u.ipsecProposals.numTransforms,
kPGPMemoryMgrFlags_Clear );
if( IsNull( ike->defaultIPSECProps ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
ike->numIPSECProps = pref->u.ipsecProposals.numTransforms;
pgpCopyMemory( pref->u.ipsecProposals.t, ike->defaultIPSECProps,
ike->numIPSECProps * sizeof(PGPipsecTransform) );
break;
case kPGPike_PF_AllowedAlgorithms:
pgpCopyMemory( &pref->u.allowedAlgorithms, &ike->allowedAlgorithms,
sizeof(PGPikeAllowedAlgorithms) );
break;
default:
err = kPGPError_FeatureNotAvailable;
break;
}
done:
return err;
}
PGPError
pgpIKEAddPending(
PGPikeContextPriv * ike,
PGPUInt32 ipAddress,
PGPUInt32 ipAddrStart,
PGPUInt32 ipMaskEnd,
PGPBoolean destIsRange )
{
PGPikeDestination * dest;
PGPError err = kPGPError_NoErr;
/* The pending list is really just for debugging purposes */
dest = (PGPikeDestination *)PGPNewData( ike->memMgr, sizeof(PGPikeDestination), 0 );
if( IsntNull( dest ) )
{
dest->ipAddress = ipAddress;
dest->ipAddrStart = ipAddrStart;
dest->ipMaskEnd = ipMaskEnd;
dest->destIsRange = destIsRange;
dest->nextD = ike->pending;
ike->pending = dest;
}
else
err = kPGPError_OutOfMemory;
return err;
}
PGPBoolean
pgpIKEFindPending(
PGPikeContextPriv * ike,
PGPUInt32 ipAddress,
PGPUInt32 ipAddrStart,
PGPUInt32 ipMaskEnd,
PGPBoolean destIsRange )
{
PGPBoolean found = FALSE;
PGPikeDestination * dest;
for( dest = ike->pending; IsntNull( dest ); dest = dest->nextD )
{
if( ( dest->ipAddress == ipAddress ) &&
( dest->ipAddrStart == ipAddrStart ) &&
( dest->ipMaskEnd == ipMaskEnd ) &&
( dest->destIsRange == destIsRange ) )
{
found = TRUE;
break;
}
}
return found;
}
PGPError
pgpIKERemovePending(
PGPikeContextPriv * ike,
PGPUInt32 ipAddress,
PGPUInt32 ipAddrStart,
PGPUInt32 ipMaskEnd,
PGPBoolean destIsRange )
{
PGPikeDestination * dest;
PGPikeDestination * lastDest = NULL;
PGPError err = kPGPError_NoErr;
for( dest = ike->pending; IsntNull( dest ); dest = dest->nextD )
{
if( ( dest->ipAddress == ipAddress ) &&
( dest->ipAddrStart == ipAddrStart ) &&
( dest->ipMaskEnd == ipMaskEnd ) &&
( dest->destIsRange == destIsRange ) )
{
if( IsNull( lastDest ) )
ike->pending = dest->nextD;
else
lastDest->nextD = dest->nextD;
(void)PGPFreeData( dest );
break;
}
lastDest = dest;
}
return err;
}
PGPError
pgpIKEHandleSARequest(
PGPikeContextPriv * ike,
PGPikeMTSASetup * saReq )
{
PGPError err = kPGPError_NoErr;
PGPikePartner * partner = NULL;
if( IsNull( saReq ) )
return kPGPError_BadParams;
if( saReq->doi != kPGPike_DOI_IPSEC )
return kPGPError_FeatureNotAvailable;
/* currently, if a P2 Tunnel Mode SA exists, and we want to communicate with
a different destination inside the Tunnel, we establish another P1 and P2
SA for that. This is unnecessary, and a good optimization here would be
to only establish the P2 SA using the existing P1 SA if there is one. */
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, "SARequest: %u.%u.%u.%u (%u.%u.%u.%u/%u.%u.%u.%u)\n",
( saReq->ipAddress >> 24 ), ( saReq->ipAddress >> 16 ) & 0xFF,
( saReq->ipAddress >> 8 ) & 0xFF, ( saReq->ipAddress & 0xFF ),
( saReq->u.ipsec.ipAddrStart >> 24 ), ( saReq->u.ipsec.ipAddrStart >> 16 ) & 0xFF,
( saReq->u.ipsec.ipAddrStart >> 8 ) & 0xFF, ( saReq->u.ipsec.ipAddrStart & 0xFF ),
( saReq->u.ipsec.ipMaskEnd >> 24 ), ( saReq->u.ipsec.ipMaskEnd >> 16 ) & 0xFF,
( saReq->u.ipsec.ipMaskEnd >> 8 ) & 0xFF, ( saReq->u.ipsec.ipMaskEnd & 0xFF ) );
#endif
if( pgpIKEFindPending( ike, saReq->ipAddress, saReq->u.ipsec.ipAddrStart,
saReq->u.ipsec.ipMaskEnd, saReq->u.ipsec.destIsRange ) )
{
#if PGPIKE_DEBUG
pgpIKEDebugLog( ike, "IGNORED: Already in progress\n" );
#endif
goto done;
}
err = pgpIKEAddPending( ike, saReq->ipAddress, saReq->u.ipsec.ipAddrStart,
saReq->u.ipsec.ipMaskEnd, saReq->u.ipsec.destIsRange ); CKERR;
err = pgpIKEStartIdentityExchange( ike, saReq->ipAddress, saReq, FALSE, 0, 0 ); CKERR;
done:
return err;
}
PGPError
pgpIKECreateProposals(
PGPikeExchange * exchange )
{
PGPError err = kPGPError_NoErr;
PGPikeProposal * proposal = NULL;
PGPUInt16 transIndex,
numTransforms;
proposal = PGPNewData( exchange->ike->memMgr, sizeof(PGPikeProposal),
kPGPMemoryMgrFlags_Clear );
if( IsNull( proposal ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
switch( exchange->exchangeT )
{
case kPGPike_EX_Identity:
proposal->number = 1;
proposal->protocol = kPGPike_PR_IKE;
numTransforms = exchange->ike->numIKEProps;
if( numTransforms > kPGPike_MaxPropTransforms )
numTransforms = kPGPike_MaxPropTransforms;
for( transIndex = 0; transIndex < numTransforms; transIndex++ )
if( pgpIKEIsTransformValid( exchange->partner, kPGPike_PR_IKE,
(PGPikeGenericTransform *)
&exchange->ike->defaultIKEProps[transIndex] ) )
{
pgpCopyMemory( &exchange->ike->defaultIKEProps[transIndex],
&proposal->t[proposal->numTransforms].u.ike,
sizeof( PGPikeTransform ) );
proposal->numTransforms++;
}
proposal->secLifeTime = exchange->ike->secLifeTimeIKE;
proposal->kbLifeTime = exchange->ike->kbLifeTimeIKE;
break;
case kPGPike_EX_IPSEC_Quick:
{
PGPikeProposal * nproposal = NULL;
PGPUInt32 propType,
propIndex;
PGPBoolean useProtocol;
PGPipsecTransform * curp;
for( propIndex = exchange->ike->numIPSECProps; propIndex > 0; propIndex-- )
{
curp = &exchange->ike->defaultIPSECProps[propIndex - 1];
for( propType = 0; propType < 3; propType++ )
{
useProtocol = FALSE;
if( IsNull( nproposal ) )
nproposal = proposal;
else
{
nproposal = PGPNewData( exchange->ike->memMgr,
sizeof(PGPikeProposal), kPGPMemoryMgrFlags_Clear );
if( IsNull( nproposal ) )
{
err = kPGPError_OutOfMemory;
goto done;
}
nproposal->nextProposal = proposal;
proposal = nproposal;
}
switch( propType ) // in reverse order
{
case 0: // IPCOMP
if( curp->useIPCOMP )
{
useProtocol = TRUE;
proposal->protocol = kPGPike_PR_IPCOMP;
pgpCopyMemory( &curp->ipcomp,
&proposal->t[0].u.ipsec.ipcomp,
sizeof(PGPipsecIPCOMPTransform) );
}
break;
case 1: // ESP
if( curp->useESP )
{
useProtocol = TRUE;
proposal->protocol = kPGPike_PR_ESP;
pgpCopyMemory( &curp->esp, &proposal->t[0].u.ipsec.esp,
sizeof(PGPipsecESPTransform) );
proposal->t[0].u.ipsec.esp.mode =
exchange->partner->ipsecOpts.packetMode;
}
break;
case 2: // AH
if( curp->useAH )
{
useProtocol = TRUE;
proposal->protocol = kPGPike_PR_AH;
pgpCopyMemory( &curp->ah, &proposal->t[0].u.ipsec.ah,
sizeof(PGPipsecAHTransform) );
proposal->t[0].u.ipsec.ah.mode =
exchange->partner->ipsecOpts.packetMode;
}
break;
}
if( useProtocol )
{
proposal->number = propIndex;
proposal->numTransforms = 1;
proposal->t[0].u.ipsec.groupID = curp->groupID;
proposal->secLifeTime = exchange->ike->secLifeTimeIPSEC;
proposal->kbLifeTime = exchange->ike->kbLifeTimeIPSEC;
err = PGPContextGetRandomBytes( exchange->ike->pgpContext,
&proposal->initSPI, sizeof(PGPipsecSPI) ); CKERR;
}
else
{
nproposal = proposal;
proposal = proposal->nextProposal;
err = PGPFreeData( nproposal ); CKERR;
}
}
}
break;
}
default:
break;
}
pgpAssert( IsNull( exchange->proposals ) );
exchange->proposals = proposal;
proposal = NULL;
done:
if( IsntNull( proposal ) )
(void) PGPFreeData( proposal );
return err;
}
PGPError
pgpIKECreateExchange(
PGPikePartner * partner,
PGPikeExchangeT exchangeT,
PGPikeMessageID * messageID,
PGPikeState state,
PGPBoolean initiator,
PGPikeExchange ** exchangeP )
{
PGPError err = kPGPError_NoErr;
PGPikeExchange * exchange = NULL;
PGPHashContextRef hash = kInvalidPGPHashContextRef;
*exchangeP = NULL;
pgpAssertAddrValid( partner, PGPikePartner );
exchange = PGPNewData( partner->ike->memMgr, sizeof(PGPikeExchange),
kPGPMemoryMgrFlags_Clear );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -