Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1056 lines
32 KiB

/********************************************************************/
/** Copyright(c) 1985-1998 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: packconv.c
//
// Description:
//
// History: Feb 11,1998 NarenG Created original version.
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <lmcons.h>
#include <lmapibuf.h>
#include <lmaccess.h>
#include <raserror.h>
#include <time.h>
#include <string.h>
#include <rasauth.h>
#include <stdlib.h>
#include <stdio.h>
#include <rtutils.h>
#include <mprlog.h>
#include <mprerror.h>
#define INCL_RASAUTHATTRIBUTES
#define INCL_HOSTWIRE
#include <ppputil.h>
#include "radclnt.h"
#include "hmacmd5.h"
#include "md5.h"
#include "radclnt.h"
//**
//
// Call: Router2Radius
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Converts attribute array from RAS_AUTH_ATTRIBUTE to
// RADIUS_ATTRIBUTE
// INPUT:
// prgRouter - array of attributes passed in from
// the application
// pRadiusServer - RADIUS server
// descriptor(ip address, secret)
// pHeader - RADIUS packet header
// bSubCode - accounting sub codes.
// OUTPUT:
// prgRadius - array of attribtes that will be sent
// to the RADIUS server.
// pAttrLength - Length of the Radius packet.
//
DWORD
Router2Radius(
IN RAS_AUTH_ATTRIBUTE * prgRouter,
OUT RADIUS_ATTRIBUTE UNALIGNED * prgRadius,
IN RADIUSSERVER UNALIGNED * pRadiusServer,
IN RADIUS_PACKETHEADER UNALIGNED * pHeader,
IN BYTE bSubCode,
IN DWORD dwRetryCount,
OUT PBYTE * ppSignature,
OUT DWORD * pAttrLength
)
{
DWORD dwError = NO_ERROR;
BOOL fEAPMessage = FALSE;
*pAttrLength = 0;
*ppSignature = NULL;
do
{
//
// add the attribute for accounting records
//
switch( bSubCode )
{
case atStart:
case atStop:
case atAccountingOn:
case atAccountingOff:
case atInterimUpdate:
//
// Add the accounting status type attribute
//
prgRadius->bType = ptAcctStatusType;
prgRadius->bLength = sizeof(RADIUS_ATTRIBUTE) + sizeof(DWORD);
(*pAttrLength) += prgRadius->bLength;
prgRadius++;
*((DWORD UNALIGNED *) prgRadius) = htonl(bSubCode);
prgRadius = (RADIUS_ATTRIBUTE *)(((PBYTE) prgRadius)+sizeof(DWORD));
//
// Add the accounting delay time attribute
//
prgRadius->bType = raatAcctDelayTime;
prgRadius->bLength = sizeof(RADIUS_ATTRIBUTE) + sizeof(DWORD);
(*pAttrLength) += prgRadius->bLength;
prgRadius++;
HostToWireFormat32( dwRetryCount * pRadiusServer->Timeout.tv_sec,
(LPBYTE)(prgRadius) );
prgRadius = (RADIUS_ATTRIBUTE *)(((PBYTE) prgRadius)+sizeof(DWORD));
break;
default:
break;
}
while( prgRouter->raaType != raatMinimum )
{
//
// Copy attribute type & length
//
prgRadius->bType = (BYTE)(prgRouter->raaType);
prgRadius->bLength = (BYTE)(prgRouter->dwLength);
switch( prgRouter->raaType )
{
case raatUserPassword:
(*pAttrLength) += EncryptPassword( prgRouter,
prgRadius,
pRadiusServer,
pHeader,
bSubCode);
break;
case raatUserName:
case raatMD5CHAPPassword:
case raatFilterId:
case raatReplyMessage:
case raatCallbackNumber:
case raatCallbackId:
case raatFramedRoute:
case raatState:
case raatClass:
case raatVendorSpecific:
case raatCalledStationId:
case raatCallingStationId:
case raatNASIdentifier:
case raatProxyState:
case raatLoginLATService:
case raatLoginLATNode:
case raatLoginLATGroup:
case raatFramedAppleTalkZone:
case raatAcctSessionId:
case raatAcctMultiSessionId:
case raatMD5CHAPChallenge:
case raatLoginLATPort:
case raatTunnelClientEndpoint:
case raatTunnelServerEndpoint:
case raatARAPPassword:
case raatARAPFeatures:
case raatARAPSecurityData:
case raatConnectInfo:
case raatConfigurationToken:
case raatSignature:
case raatCertificateOID:
CopyMemory( prgRadius+1,
(PBYTE)prgRouter->Value,
prgRadius->bLength);
prgRadius->bLength += sizeof(RADIUS_ATTRIBUTE);
(*pAttrLength) += prgRadius->bLength;
break;
case raatEAPMessage:
{
DWORD dwLength = prgRouter->dwLength;
PBYTE pRouterEapMessage = (PBYTE)(prgRouter->Value);
while( dwLength > 0 )
{
if ( dwLength > 253 )
{
CopyMemory( (PBYTE)(prgRadius+1),
pRouterEapMessage,
253 );
prgRadius->bLength = 253;
pRouterEapMessage += 253;
dwLength -= 253;
}
else
{
CopyMemory( prgRadius+1,
(PBYTE)pRouterEapMessage,
dwLength );
prgRadius->bLength = (BYTE)dwLength;
dwLength = 0;
}
prgRadius->bType = (BYTE)raatEAPMessage;
prgRadius->bLength += sizeof(RADIUS_ATTRIBUTE);
(*pAttrLength) += prgRadius->bLength;
if ( dwLength > 0 )
{
prgRadius = (PRADIUS_ATTRIBUTE)
((PBYTE) prgRadius + prgRadius->bLength);
}
}
}
fEAPMessage = TRUE;
break;
case raatNASPort:
case raatServiceType:
case raatFramedProtocol:
case raatFramedRouting:
case raatFramedMTU:
case raatFramedCompression:
case raatLoginIPHost:
case raatLoginService:
case raatLoginTCPPort:
case raatFramedIPXNetwork:
case raatSessionTimeout:
case raatIdleTimeout:
case raatTerminationAction:
case raatFramedAppleTalkLink:
case raatFramedAppleTalkNetwork:
case raatNASPortType:
case raatPortLimit:
case raatTunnelType:
case raatTunnelMediumType:
case raatAcctStatusType:
case raatAcctDelayTime:
case raatAcctInputOctets:
case raatAcctOutputOctets:
case raatAcctAuthentic:
case raatAcctSessionTime:
case raatAcctInputPackets:
case raatAcctOutputPackets:
case raatAcctTerminateCause:
case raatAcctLinkCount:
case raatFramedIPAddress:
case raatFramedIPNetmask:
case raatPrompt:
case raatPasswordRetry:
case raatARAPZoneAccess:
case raatARAPSecurity:
case raatAcctInterimInterval:
case raatAcctEventTimeStamp:
case raatPEAPFastRoamedSession:
case raatPEAPEmbeddedEAPTypeId:
switch( prgRouter->dwLength )
{
case 1:
*((LPBYTE)(prgRadius+1)) = (BYTE)prgRouter->Value;
break;
case 2:
HostToWireFormat16U( (WORD)prgRouter->Value,
(LPBYTE)(prgRadius+1) );
break;
case 4:
HostToWireFormat32( PtrToUlong(prgRouter->Value),
(LPBYTE)(prgRadius+1) );
break;
default:
break;
}
prgRadius->bLength += sizeof(RADIUS_ATTRIBUTE);
(*pAttrLength) += prgRadius->bLength;
break;
case raatNASIPAddress:
RTASSERT( 4 == prgRouter->dwLength );
if ( pRadiusServer->nboNASIPAddress != INADDR_NONE )
{
CopyMemory( (LPBYTE)(prgRadius+1),
(LPBYTE)&(pRadiusServer->nboNASIPAddress),
4 );
}
else if( pRadiusServer->nboBestIf != INADDR_NONE)
{
CopyMemory( (LPBYTE)(prgRadius+1),
(LPBYTE)&(pRadiusServer->nboBestIf),
4 );
}
else
{
HostToWireFormat32( PtrToUlong(prgRouter->Value),
(LPBYTE)(prgRadius+1) );
}
prgRadius->bLength += sizeof(RADIUS_ATTRIBUTE);
(*pAttrLength) += prgRadius->bLength;
break;
}
prgRadius = (PRADIUS_ATTRIBUTE)
((PBYTE) prgRadius + prgRadius->bLength);
prgRouter++;
}
}while( FALSE );
if ( dwError != NO_ERROR )
{
(*pAttrLength) = 0;
}
else
{
if ( ( ( bSubCode == atInvalid )
? pRadiusServer->fSendSignature
: FALSE ) || ( fEAPMessage ) )
{
//
// Add a signature attribute as well. Zero this out for now.
//
*ppSignature = (BYTE *)prgRadius;
prgRadius->bType = (BYTE)raatSignature;
prgRadius->bLength = (BYTE)18;
ZeroMemory( prgRadius+1, 16 );
(*pAttrLength) += prgRadius->bLength;
}
}
return( dwError );
}
//**
//
// Call: Radius2Router
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Converts RADIUS attribute array to RAS_AUTH_ATTRIBUTE array
//
DWORD
Radius2Router(
IN RADIUS_PACKETHEADER UNALIGNED * pRecvHeader,
IN RADIUSSERVER UNALIGNED * pRadiusServer,
IN PBYTE pRequestAuthenticator,
IN DWORD dwNumAttributes,
OUT DWORD * pdwExtError,
OUT PRAS_AUTH_ATTRIBUTE * pprgRouter,
OUT BOOL * fEapMessageReceived
)
{
LONG cbLength;
DWORD dwRetCode = NO_ERROR;
BOOL fEAPMessage = FALSE;
BOOL fSignature = FALSE;
PBYTE pEAPMessage = NULL;
DWORD cbEAPMessage = 0;
RADIUS_ATTRIBUTE UNALIGNED * prgRadius
= (PRADIUS_ATTRIBUTE)(pRecvHeader + 1);
*pdwExtError = 0;
*pprgRouter = NULL;
*fEapMessageReceived = FALSE;
*pprgRouter = RasAuthAttributeCreate( dwNumAttributes );
if ( *pprgRouter == NULL )
{
return( GetLastError() );
}
dwNumAttributes = 0;
cbLength = ntohs( pRecvHeader->wLength ) - sizeof(RADIUS_PACKETHEADER);
while( cbLength > 0 )
{
switch( (RAS_AUTH_ATTRIBUTE_TYPE)prgRadius->bType )
{
case raatNASPort:
case raatServiceType:
case raatFramedProtocol:
case raatFramedRouting:
case raatFramedMTU:
case raatFramedCompression:
case raatLoginIPHost:
case raatLoginService:
case raatLoginTCPPort:
case raatFramedIPXNetwork:
case raatSessionTimeout:
case raatIdleTimeout:
case raatTerminationAction:
case raatFramedAppleTalkLink:
case raatFramedAppleTalkNetwork:
case raatNASPortType:
case raatPortLimit:
case raatTunnelType:
case raatTunnelMediumType:
case raatAcctStatusType:
case raatAcctDelayTime:
case raatAcctInputOctets:
case raatAcctOutputOctets:
case raatAcctAuthentic:
case raatAcctSessionTime:
case raatAcctInputPackets:
case raatAcctOutputPackets:
case raatAcctTerminateCause:
case raatAcctLinkCount:
case raatFramedIPAddress:
case raatFramedIPNetmask:
case raatNASIPAddress:
case raatPrompt:
case raatPasswordRetry:
case raatARAPZoneAccess:
case raatARAPSecurity:
case raatAcctInterimInterval:
case raatAcctEventTimeStamp:
case raatPEAPFastRoamedSession:
case raatPEAPEmbeddedEAPTypeId:
{
DWORD dwIntegralValue;
DWORD dwLength = prgRadius->bLength - sizeof(RADIUS_ATTRIBUTE);
if ( dwLength == 1 )
{
dwIntegralValue = (DWORD)(*(LPBYTE)(prgRadius+1));
}
else if ( dwLength == 2 )
{
dwIntegralValue=(DWORD)WireToHostFormat16U(
(PBYTE)(prgRadius+1));
}
else if ( dwLength == 4 )
{
dwIntegralValue=(DWORD)WireToHostFormat32(
(PBYTE)(prgRadius+1));
}
else
{
//
// Drop bad attribute
//
break;
}
dwRetCode = RasAuthAttributeInsert(
dwNumAttributes++,
*pprgRouter,
(RAS_AUTH_ATTRIBUTE_TYPE)prgRadius->bType,
FALSE,
prgRadius->bLength-sizeof(RADIUS_ATTRIBUTE),
(LPVOID)ULongToPtr(dwIntegralValue) );
}
break;
case raatSignature:
//
// Check the signature
//
{
BYTE MD5d[MD5_LEN];
HmacContext HmacMD5c;
BYTE Signature[16];
HmacMD5Init( &HmacMD5c,
(PBYTE)(pRadiusServer->szSecret),
pRadiusServer->cbSecret);
//
// Zero out the signature attribute before calculating it
//
if ( prgRadius->bLength != 18 )
{
RADIUS_TRACE("Received invalid signature length in packet");
*pdwExtError = ERROR_INVALID_SIGNATURE_LENGTH;
dwRetCode = ERROR_INVALID_RADIUS_RESPONSE;
break;
}
CopyMemory( Signature, (prgRadius+1), 16 );
ZeroMemory( (PBYTE)(prgRadius+1), 16 );
CopyMemory( (PBYTE)(pRecvHeader->rgAuthenticator),
pRequestAuthenticator,
16 );
HmacMD5Update( &HmacMD5c,
(PBYTE)pRecvHeader,
ntohs(pRecvHeader->wLength) );
HmacMD5Final( MD5d, &HmacMD5c );
if ( memcmp( Signature, MD5d, 16 ) != 0 )
{
RADIUS_TRACE("Received invalid signature in packet");
*pdwExtError = ERROR_INVALID_SIGNATURE;
dwRetCode = ERROR_INVALID_RADIUS_RESPONSE;
break;
}
fSignature = TRUE;
}
//
// Fall thru
//
case raatUserName:
case raatUserPassword:
case raatMD5CHAPPassword:
case raatFilterId:
case raatReplyMessage:
case raatCallbackNumber:
case raatCallbackId:
case raatFramedRoute:
case raatState:
case raatClass:
case raatCalledStationId:
case raatCallingStationId:
case raatNASIdentifier:
case raatProxyState:
case raatLoginLATService:
case raatLoginLATNode:
case raatLoginLATGroup:
case raatFramedAppleTalkZone:
case raatAcctSessionId:
case raatAcctMultiSessionId:
case raatMD5CHAPChallenge:
case raatLoginLATPort:
case raatTunnelClientEndpoint:
case raatTunnelServerEndpoint:
case raatARAPPassword:
case raatARAPFeatures:
case raatARAPSecurityData:
case raatConnectInfo:
case raatConfigurationToken:
case raatARAPChallengeResponse:
case raatCertificateOID:
dwRetCode = RasAuthAttributeInsert(
dwNumAttributes++,
*pprgRouter,
(RAS_AUTH_ATTRIBUTE_TYPE)prgRadius->bType,
FALSE,
prgRadius->bLength-sizeof(RADIUS_ATTRIBUTE),
(LPVOID)(prgRadius+1) );
break;
case raatVendorSpecific:
if ( WireToHostFormat32( (PBYTE)(prgRadius+1) ) == 311 )
{
BYTE abTemp[34];
PBYTE pVSAWalker = (PBYTE)(prgRadius+1)+4;
DWORD cbVSALength = prgRadius->bLength -
sizeof( RADIUS_ATTRIBUTE ) - 4;
while( cbVSALength > 1 )
{
if ( *pVSAWalker == 12 )
{
if ( *(pVSAWalker+1) != 34 )
{
RADIUS_TRACE("Recvd invalid MPPE key packet");
}
else
{
//
// We don't want to modify whatever data we got
// from RADIUS (to keep the signature valid).
//
CopyMemory( abTemp, pVSAWalker, 34 );
//
// Decrypt the MPPE session keys.
//
dwRetCode = DecryptMPPEKeys( pRadiusServer,
pRequestAuthenticator,
abTemp+2 );
if ( dwRetCode != NO_ERROR )
{
break;
}
dwRetCode = RasAuthAttributeInsertVSA(
dwNumAttributes++,
*pprgRouter,
311,
*(pVSAWalker+1),
abTemp );
}
}
else if ( ( *pVSAWalker == 16 )
|| ( *pVSAWalker == 17 ) )
{
DWORD dwLength;
BYTE* pbTemp;
dwLength = *(pVSAWalker+1);
if ( ( dwLength <= 4 )
|| ( ( dwLength - 4 ) % 16 != 0 ) )
{
RADIUS_TRACE("Recvd invalid MPPE key packet");
}
else
{
pbTemp = LocalAlloc( LPTR, dwLength );
if ( NULL == pbTemp )
{
dwRetCode = GetLastError();
RADIUS_TRACE("Out of memory");
break;
}
//
// We don't want to modify whatever data we got
// from RADIUS (to keep the signature valid).
//
CopyMemory( pbTemp, pVSAWalker, dwLength );
//
// Decrypt the MPPE Send/Recv keys.
//
dwRetCode = DecryptMPPESendRecvKeys(
pRadiusServer,
pRequestAuthenticator,
dwLength,
pbTemp+2 );
if ( dwRetCode != NO_ERROR )
{
LocalFree( pbTemp );
break;
}
dwRetCode = RasAuthAttributeInsertVSA(
dwNumAttributes++,
*pprgRouter,
311,
*(pVSAWalker+1),
pbTemp );
LocalFree( pbTemp );
}
}
else
{
dwRetCode = RasAuthAttributeInsertVSA(
dwNumAttributes++,
*pprgRouter,
311,
*(pVSAWalker+1),
pVSAWalker );
}
if ( dwRetCode != NO_ERROR )
{
break;
}
cbVSALength -= *(pVSAWalker+1);
pVSAWalker += *(pVSAWalker+1);
}
}
break;
case raatEAPMessage:
fEAPMessage = TRUE;
{
if ( pEAPMessage == NULL )
{
//
// Nothing has been allocated for EAP yet.
//
pEAPMessage = (PBYTE)LocalAlloc(
LPTR,
prgRadius->bLength
- sizeof( RADIUS_ATTRIBUTE ) );
}
else
{
//
// Need to increase the size of the buffer to hold this
// message
//
PBYTE pReallocEAPMessage =
(PBYTE)LocalReAlloc(
pEAPMessage,
cbEAPMessage
+ prgRadius->bLength
- sizeof( RADIUS_ATTRIBUTE ),
LMEM_MOVEABLE );
if ( pReallocEAPMessage == NULL )
{
LocalFree( pEAPMessage );
pEAPMessage = NULL;
}
else
{
pEAPMessage = pReallocEAPMessage;
}
}
if ( pEAPMessage == NULL )
{
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
break;
}
//
// Copy existing buffer to new buffer
//
CopyMemory( pEAPMessage+cbEAPMessage,
(PBYTE)(prgRadius+1),
prgRadius->bLength - sizeof(RADIUS_ATTRIBUTE) );
//
// Increment the cbEAPMessage so that the size is updated
// properly
//
cbEAPMessage += (prgRadius->bLength - sizeof(RADIUS_ATTRIBUTE));
}
break;
default:
//
// Drop attributes we do not know about.
//
break;
}
if ( dwRetCode != NO_ERROR )
{
RasAuthAttributeDestroy( *pprgRouter );
*pprgRouter = NULL;
if ( pEAPMessage != NULL )
{
LocalFree( pEAPMessage );
}
return( dwRetCode );
}
RADIUS_TRACE1( "Returning attribute type %d", prgRadius->bType );
cbLength -= prgRadius->bLength;
prgRadius = (PRADIUS_ATTRIBUTE)((PBYTE)prgRadius+prgRadius->bLength);
}
if ( dwRetCode == NO_ERROR )
{
if ( fEAPMessage )
{
//
// If we have received an EAP message, make sure we received a valid
// signature as well
//
if ( !fSignature )
{
RADIUS_TRACE("Did not receive signature along auth EAPMessage");
*pdwExtError = ERROR_NO_SIGNATURE;
dwRetCode = ERROR_INVALID_RADIUS_RESPONSE;
}
else
{
dwRetCode = RasAuthAttributeInsert(
dwNumAttributes++,
*pprgRouter,
(RAS_AUTH_ATTRIBUTE_TYPE)raatEAPMessage,
FALSE,
cbEAPMessage,
(LPVOID)pEAPMessage );
*fEapMessageReceived = TRUE;
}
LocalFree( pEAPMessage );
}
}
return( dwRetCode );
}
DWORD
EncryptPassword(
IN RAS_AUTH_ATTRIBUTE * prgRouter,
IN RADIUS_ATTRIBUTE UNALIGNED * prgRadius,
IN RADIUSSERVER UNALIGNED * pRadiusServer,
IN RADIUS_PACKETHEADER UNALIGNED * pHeader,
IN BYTE bSubCode
)
{
MD5_CTX MD5c;
DWORD iIndex, iBlock, cBlocks;
DWORD bLength, AttrLength;
BYTE UNALIGNED *pbValue;
//
// make the password into a 16 octet multiple
//
bLength = ((prgRadius->bLength + 15) / 16) * 16;
if ( bLength == 0 )
{
bLength = 16;
}
prgRadius->bLength = (BYTE)(sizeof(RADIUS_ATTRIBUTE) + bLength);
pbValue = (PBYTE) (prgRadius + 1);
AttrLength = sizeof(RADIUS_ATTRIBUTE);
//
// Zero pad the password
//
ZeroMemory( pbValue, bLength );
//
// Copy the original password
//
CopyMemory( pbValue, (PBYTE)prgRouter->Value, (BYTE)prgRouter->dwLength);
cBlocks = bLength / 16;
for ( iBlock = 0; iBlock < cBlocks; iBlock++ )
{
MD5Init( &MD5c );
MD5Update(&MD5c,(PBYTE)pRadiusServer->szSecret,pRadiusServer->cbSecret);
if (iBlock == 0)
{
MD5Update( &MD5c,
pHeader->rgAuthenticator,
sizeof(pHeader->rgAuthenticator));
}
else
{
MD5Update(&MD5c, (pbValue - 16), 16);
}
MD5Final( &MD5c );
for ( iIndex = 0; iIndex < 16; iIndex++ )
{
*pbValue ^= MD5c.digest[iIndex];
pbValue++;
}
}
return( AttrLength + bLength );
}
DWORD
DecryptMPPEKeys(
IN RADIUSSERVER UNALIGNED * pRadiusServer,
IN PBYTE pRequestAuthenticator,
IN OUT PBYTE pEncryptionKeys
)
{
BYTE * pbValue = (BYTE *)pEncryptionKeys;
MD5_CTX MD5c;
DWORD dwIndex;
DWORD dwBlock;
BYTE abCipherText[16];
//
// Save the cipherText from the first block.
//
CopyMemory(abCipherText, pbValue, sizeof(abCipherText));
//
// Walk thru the 2 blocks
//
for ( dwBlock = 0; dwBlock < 2; dwBlock++ )
{
MD5Init( &MD5c );
MD5Update( &MD5c,
(PBYTE)(pRadiusServer->szSecret),
pRadiusServer->cbSecret);
if ( dwBlock == 0 )
{
//
// Use the Request Authenticator for the first block
//
MD5Update( &MD5c, pRequestAuthenticator, 16 );
}
else
{
//
// Use the first block of cipherText for the second block
//
MD5Update( &MD5c, abCipherText, 16 );
}
MD5Final( &MD5c );
for ( dwIndex = 0; dwIndex < 16; dwIndex ++ )
{
*pbValue ^= MD5c.digest[dwIndex];
pbValue++;
}
}
return( NO_ERROR );
}
DWORD
DecryptMPPESendRecvKeys(
IN RADIUSSERVER UNALIGNED * pRadiusServer,
IN PBYTE pRequestAuthenticator,
IN DWORD dwLength,
IN OUT PBYTE pEncryptionKeys
)
{
BYTE * pbValue = (BYTE *)pEncryptionKeys + 2;
BYTE abCipherText[16];
MD5_CTX MD5c;
DWORD dwIndex;
DWORD dwBlock;
DWORD dwNumBlocks;
dwNumBlocks = ( dwLength - 2 ) / 16;
//
// Walk thru the blocks
//
for ( dwBlock = 0; dwBlock < dwNumBlocks; dwBlock++ )
{
MD5Init( &MD5c );
MD5Update( &MD5c,
(PBYTE)(pRadiusServer->szSecret),
pRadiusServer->cbSecret);
if ( dwBlock == 0 )
{
//
// Use the Request Authenticator and salt for the first block
//
MD5Update( &MD5c, pRequestAuthenticator, 16 );
MD5Update( &MD5c, pEncryptionKeys, 2 );
}
else
{
//
// Use the previous block of cipherText
//
MD5Update( &MD5c, abCipherText, 16 );
}
MD5Final( &MD5c );
//
// Save the cipherText from this block.
//
CopyMemory(abCipherText, pbValue, sizeof(abCipherText));
for ( dwIndex = 0; dwIndex < 16; dwIndex++ )
{
*pbValue ^= MD5c.digest[dwIndex];
pbValue++;
}
}
return( NO_ERROR );
}