⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpike.c

📁 pgp soucecode pgp soucecode
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -