windows-nt/Source/XPSP1/NT/net/rras/ras/ppp/rasccp/rasccp.c

2153 lines
63 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: rasccp.c
//
// Description: Contains entry points to configure CCP.
//
// History: April 11,1994. NarenG Created original version.
//
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h> // needed for winbase.h
#include <windows.h> // Win32 base API's
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <lmcons.h>
#include <raserror.h>
#include <rtutils.h>
#include <rasman.h>
#include <pppcp.h>
#define INCL_HOSTWIRE
#define INCL_ENCRYPT
#define INCL_RASAUTHATTRIBUTES
#include <ppputil.h>
#define CCPGLOBALS
#include <rasccp.h>
//**
//
// Call: TraceCcp
//
// Description:
//
VOID
TraceCcp(
CHAR * Format,
...
)
{
va_list arglist;
va_start(arglist, Format);
TraceVprintfEx( DwCcpTraceId, TRACE_RASCCP, Format, arglist);
va_end(arglist);
}
//**
//
// Call: CcpInit
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD
CcpInit(
IN BOOL fInitialize
)
{
if ( fInitialize )
{
DwCcpTraceId = TraceRegister("RASCCP");
}
else
{
TraceDeregister( DwCcpTraceId );
}
return( NO_ERROR );
}
//**
//
// Call: CcpBegin
//
// Returns: NO_ERROR - Success
// non-zero error - Failure
//
//
// Description: Called once before any other call to CCP is made. Allocate
// a work buffer and initialize it.
//
DWORD
CcpBegin(
IN OUT VOID** ppWorkBuf,
IN VOID* pInfo
)
{
CCPCB * pCcpCb;
DWORD dwRetCode;
RAS_AUTH_ATTRIBUTE * pAttribute;
RAS_AUTH_ATTRIBUTE * pAttributeSend;
RAS_AUTH_ATTRIBUTE * pAttributeRecv;
DWORD fEncryptionTypes = 0;
BOOL fDisableEncryption = FALSE;
DWORD dwConfigMask =
((PPPCP_INIT*)pInfo)->PppConfigInfo.dwConfigMask;
*ppWorkBuf = LocalAlloc( LPTR, sizeof( CCPCB ) );
if ( *ppWorkBuf == NULL )
{
return( GetLastError() );
}
pCcpCb = (CCPCB *)*ppWorkBuf;
pCcpCb->fServer = ((PPPCP_INIT*)pInfo)->fServer;
pCcpCb->hPort = ((PPPCP_INIT*)pInfo)->hPort;
pCcpCb->dwDeviceType = ((PPPCP_INIT*)pInfo)->dwDeviceType;
pCcpCb->fForceEncryption = FALSE;
pCcpCb->fDisableCompression = !( dwConfigMask & PPPCFG_UseSwCompression );
fDisableEncryption = dwConfigMask & PPPCFG_DisableEncryption;
if ( pCcpCb->fServer )
{
if ( RAS_DEVICE_TYPE( pCcpCb->dwDeviceType ) == RDT_Tunnel_L2tp )
{
//
// Allow all types of MPPE, including No Encryption
//
fEncryptionTypes = ( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
}
else
{
//
// Is there an encryption policy attribute
//
pAttribute = RasAuthAttributeGetVendorSpecific(
311,
7,
((PPPCP_INIT *)pInfo)->pAttributes );
if ( pAttribute != NULL )
{
//
// See if we have to force encryption
//
if ( WireToHostFormat32( ((PBYTE)(pAttribute->Value))+6 ) == 2 )
{
fDisableEncryption = FALSE;
pCcpCb->fForceEncryption = TRUE;
TraceCcp("Will force encryption");
}
}
//
// Now find out what type of encryption is
// permitted/disallowed/required
//
pAttribute = RasAuthAttributeGetVendorSpecific(
311,
8,
((PPPCP_INIT *)pInfo)->pAttributes );
if ( pAttribute != NULL )
{
DWORD dwEncryptionTypes =
WireToHostFormat32(((PBYTE)(pAttribute->Value))+6);
if ( dwEncryptionTypes & 0x00000002 )
{
fEncryptionTypes = MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F;
}
if ( dwEncryptionTypes & 0x00000004 )
{
fEncryptionTypes |= MSTYPE_ENCRYPTION_128;
}
if ( dwEncryptionTypes & 0x00000008 )
{
fEncryptionTypes |= MSTYPE_ENCRYPTION_56;
}
if ( fEncryptionTypes == 0 )
{
fDisableEncryption = TRUE;
pCcpCb->fForceEncryption = FALSE;
TraceCcp("Will not force encryption: type not specified");
}
}
else
{
fEncryptionTypes = ( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
}
}
TraceCcp("EncryptionTypes: 0x%x", fEncryptionTypes);
}
else
{
//
// If client is forcing encryption
//
if ( dwConfigMask & PPPCFG_RequireEncryption )
{
fEncryptionTypes |= ( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 );
fDisableEncryption = FALSE;
pCcpCb->fForceEncryption = TRUE;
TraceCcp("Encryption");
}
if ( dwConfigMask & PPPCFG_RequireStrongEncryption )
{
//
// If client is forcing strong encryption
//
fEncryptionTypes |= MSTYPE_ENCRYPTION_128;
fDisableEncryption = FALSE;
pCcpCb->fForceEncryption = TRUE;
TraceCcp("Strong encryption");
}
//
// If we are not disabling encryption and we are not forcing encryption
// either.
//
if ( ( !fDisableEncryption ) && ( fEncryptionTypes == 0 ) )
{
//
// Allow these types
//
fDisableEncryption = FALSE;
pCcpCb->fForceEncryption = FALSE;
fEncryptionTypes = ( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
TraceCcp("Not disabling encryption; Not forcing encryption");
}
}
//
// Now check if we got encryption keys, if not then we disable encryption
//
pAttribute = RasAuthAttributeGetVendorSpecific(
311,
12,
((PPPCP_INIT *)pInfo)->pAttributes );
pAttributeSend = RasAuthAttributeGetVendorSpecific(
311,
16,
((PPPCP_INIT *)pInfo)->pAttributes );
pAttributeRecv = RasAuthAttributeGetVendorSpecific(
311,
17,
((PPPCP_INIT *)pInfo)->pAttributes );
if ( ( pAttribute == NULL )
&& ( ( pAttributeSend == NULL )
|| ( pAttributeRecv == NULL ) ) )
{
TraceCcp("No MPPE keys were obtained");
if ( pCcpCb->fForceEncryption )
{
LocalFree( pCcpCb );
return( ERROR_NO_LOCAL_ENCRYPTION );
}
fDisableEncryption = TRUE;
pCcpCb->fForceEncryption = FALSE;
fEncryptionTypes = ( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
}
//
// Get Send and Recv compression information
//
dwRetCode = RasCompressionGetInfo( pCcpCb->hPort,
&(pCcpCb->Local.Want.CompInfo),
&(pCcpCb->Remote.Want.CompInfo) );
if ( dwRetCode != NO_ERROR )
{
LocalFree( pCcpCb );
return( dwRetCode );
}
TraceCcp("Send capabilites from NDISWAN = 0x%x",
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType );
TraceCcp("Receive capabilites from NDISWAN = 0x%x",
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType );
TraceCcp("Send RCI_MacCompressionType = 0x%x",
pCcpCb->Local.Want.CompInfo.RCI_MacCompressionType );
TraceCcp("Receive RCI_MacCompressionType = 0x%x",
pCcpCb->Remote.Want.CompInfo.RCI_MacCompressionType );
//
// Ignore NT31RAS capability.
//
if ( pCcpCb->Local.Want.CompInfo.RCI_MacCompressionType
== CCP_OPTION_MSNT31RAS )
{
pCcpCb->Local.Want.CompInfo.RCI_MacCompressionType = CCP_OPTION_MAX + 1;
}
if (pCcpCb->Remote.Want.CompInfo.RCI_MacCompressionType
== CCP_OPTION_MSNT31RAS )
{
pCcpCb->Remote.Want.CompInfo.RCI_MacCompressionType = CCP_OPTION_MAX+1;
}
//
// Set up local or send information.
//
pCcpCb->Local.Want.Negotiate = 0;
if ( pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType != 0 )
{
pCcpCb->Local.Want.Negotiate = CCP_N_MSPPC;
}
if ( pCcpCb->Local.Want.CompInfo.RCI_MacCompressionType <= CCP_OPTION_MAX )
{
if ( pCcpCb->Local.Want.CompInfo.RCI_MacCompressionType ==
CCP_OPTION_OUI )
{
pCcpCb->Local.Want.Negotiate |= CCP_N_OUI;
}
else
{
pCcpCb->Local.Want.Negotiate |= CCP_N_PUBLIC;
}
}
if ( pCcpCb->fForceEncryption )
{
//
// Make sure NDISWAN supports the required encryption types
//
if ( !( pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType &
fEncryptionTypes ))
{
LocalFree( pCcpCb );
TraceCcp("Encryption type(s) 0x%x not supported locally",
fEncryptionTypes );
return( ERROR_NO_LOCAL_ENCRYPTION );
}
//
// Turn off everything else
//
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType &=
( fEncryptionTypes |
MSTYPE_HISTORYLESS |
MSTYPE_COMPRESSION );
TraceCcp("Send Encryption is Forced 0x%x",
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType );
pCcpCb->Local.Want.Negotiate &= ~( CCP_N_PUBLIC | CCP_N_OUI );
}
if ( pCcpCb->fDisableCompression )
{
pCcpCb->Local.Want.Negotiate &= ( ~CCP_N_PUBLIC & ~CCP_N_OUI );
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType&=~MSTYPE_COMPRESSION;
TraceCcp("Send Compression is Disabled");
}
if ( fDisableEncryption )
{
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
TraceCcp("Send Encryption is Disabled 0x%x", fEncryptionTypes );
}
//
// If we neither force nor disable any encryption types, then we set the
// types allowed
//
if ( (!fDisableEncryption) && (!pCcpCb->fForceEncryption) )
{
DWORD dwEncryptionTypesAllowed =
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType & fEncryptionTypes;
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType |=
dwEncryptionTypesAllowed;
TraceCcp("Send Encryption is Allowed 0x%x", dwEncryptionTypesAllowed );
}
pCcpCb->Local.Work = pCcpCb->Local.Want;
//
// If we do not want any compression or encryption on the local side
// we do not send, or accept NAKs to, negotiate the MSPPC option
//
if ( ( pCcpCb->Local.Want.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 |
MSTYPE_COMPRESSION ) )
== 0 )
{
pCcpCb->Local.Want.Negotiate &= ~CCP_N_MSPPC;
TraceCcp("We do not want any compression or encryption on the local "
"side");
}
//
// If we do not require encryption locally then do not request for it
//
if ( !( pCcpCb->fForceEncryption ) )
{
pCcpCb->Local.Work.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
TraceCcp("We do not require encryption locally; we won't request for "
"it");
}
//
// Set up remote or receive information
//
pCcpCb->Remote.Want.Negotiate = 0;
if (pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType != 0 )
{
pCcpCb->Remote.Want.Negotiate = CCP_N_MSPPC;
}
if ( pCcpCb->Remote.Want.CompInfo.RCI_MacCompressionType <= CCP_OPTION_MAX )
{
if ( pCcpCb->Remote.Want.CompInfo.RCI_MacCompressionType ==
CCP_OPTION_OUI )
{
pCcpCb->Remote.Want.Negotiate |= CCP_N_OUI;
}
else
{
pCcpCb->Remote.Want.Negotiate |= CCP_N_PUBLIC;
}
}
if ( pCcpCb->fForceEncryption )
{
if ( !( pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType &
fEncryptionTypes ) )
{
TraceCcp("Encryption type(s) 0x%x not supported locally",
fEncryptionTypes );
LocalFree( pCcpCb );
return( ERROR_NO_LOCAL_ENCRYPTION );
}
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType &=
( fEncryptionTypes |
MSTYPE_HISTORYLESS |
MSTYPE_COMPRESSION );
TraceCcp("Receive Encryption is Forced 0x%x",
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType );
pCcpCb->Remote.Want.Negotiate &= ~( CCP_N_PUBLIC | CCP_N_OUI );
}
if ( pCcpCb->fDisableCompression )
{
pCcpCb->Remote.Want.Negotiate &= ( ~CCP_N_PUBLIC & ~CCP_N_OUI );
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType&=~MSTYPE_COMPRESSION;
TraceCcp("Receive Compression is disabled");
}
if ( fDisableEncryption )
{
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
TraceCcp("Receive Encryption is Disabled 0x%x", fEncryptionTypes );
}
//
// If we neither force or disable any encryption types then we set the
// types allowed
//
if ( (!fDisableEncryption) && (!pCcpCb->fForceEncryption) )
{
DWORD dwEncryptionTypesAllowed =
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType & fEncryptionTypes;
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType |=
dwEncryptionTypesAllowed;
TraceCcp("Receive Encryption is Allowed 0x%x", dwEncryptionTypesAllowed );
}
//
// If we do not want to receive any compression or encryption from the
// remote side, we do not ACK, or accept CONFIG-REQs to, negotiate the
// MSPPC option
//
if ( ( pCcpCb->Remote.Want.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 |
MSTYPE_COMPRESSION ) )
== 0 )
{
pCcpCb->Remote.Want.Negotiate &= ~CCP_N_MSPPC;
TraceCcp("We do not want to receive any compression or encryption "
"from the remote side");
}
if ( ( pCcpCb->Remote.Want.Negotiate == 0 ) &&
( pCcpCb->Local.Want.Negotiate == 0 ) )
{
TraceCcp("ERROR_PROTOCOL_NOT_CONFIGURED");
LocalFree( pCcpCb );
return( ERROR_PROTOCOL_NOT_CONFIGURED );
}
if ( pCcpCb->fForceEncryption )
{
TraceCcp("ForceEncryption");
pCcpCb->Local.Want.CompInfo.RCI_Flags = CCP_PAUSE_DATA;
pCcpCb->Remote.Want.CompInfo.RCI_Flags = CCP_PAUSE_DATA;
dwRetCode = RasCompressionSetInfo( pCcpCb->hPort,
&(pCcpCb->Local.Want.CompInfo),
&(pCcpCb->Remote.Want.CompInfo) );
if ( dwRetCode != NO_ERROR )
{
LocalFree( pCcpCb );
return( dwRetCode );
}
}
return( NO_ERROR );
}
//**
//
// Call: CcpEnd
//
// Returns: NO_ERROR - Success
//
// Description: Frees the CCP work buffer.
//
DWORD
CcpEnd(
IN VOID * pWorkBuf
)
{
TraceCcp( "CcpEnd Called" );
if ( pWorkBuf != NULL )
{
LocalFree( pWorkBuf );
}
return( NO_ERROR );
}
//**
//
// Call: CcpReset
//
// Returns: NO_ERROR - Success
//
// Description: Called to reset the state of CCP. Will re-initialize the work
// buffer.
//
DWORD
CcpReset(
IN VOID * pWorkBuf
)
{
return( NO_ERROR );
}
//**
//
// Call: CcpMakeOption
//
// Returns: NO_ERROR - Success
// ERROR_BUFFER_TOO_SMALL - Buffer passed in is not large enough.
// ERROR_INVALID_PARAMETER - Option type not recognized.
//
// Description: This is not an entry point, it is an internal procedure called
// to build a particular option.
//
DWORD
CcpMakeOption(
IN CCP_OPTIONS * pOptionValues,
IN DWORD dwOptionType,
IN PPP_OPTION * pSendOption,
IN DWORD cbSendOption
)
{
if ( cbSendOption < PPP_OPTION_HDR_LEN )
{
return( ERROR_BUFFER_TOO_SMALL );
}
pSendOption->Type = (BYTE)dwOptionType;
switch( dwOptionType )
{
case CCP_OPTION_OUI:
pSendOption->Length = (BYTE)( PPP_OPTION_HDR_LEN +
pOptionValues->CompInfo.RCI_MacCompressionValueLength);
if ( pSendOption->Length > cbSendOption )
{
return( ERROR_BUFFER_TOO_SMALL );
}
CopyMemory( pSendOption->Data,
(PBYTE)&(pOptionValues->CompInfo.RCI_Info.RCI_Proprietary),
pSendOption->Length - PPP_OPTION_HDR_LEN );
break;
case CCP_OPTION_MSPPC:
pSendOption->Length = (BYTE)( PPP_OPTION_HDR_LEN + 4 );
if ( pSendOption->Length > cbSendOption )
{
return( ERROR_BUFFER_TOO_SMALL );
}
HostToWireFormat32( pOptionValues->CompInfo.RCI_MSCompressionType,
pSendOption->Data );
break;
default:
//
// Public compression type
//
pSendOption->Length = (BYTE)( PPP_OPTION_HDR_LEN +
pOptionValues->CompInfo.RCI_MacCompressionValueLength);
if ( pSendOption->Length > cbSendOption )
{
return( ERROR_BUFFER_TOO_SMALL );
}
CopyMemory( pSendOption->Data,
(PBYTE)&(pOptionValues->CompInfo.RCI_Info.RCI_Public),
pSendOption->Length - PPP_OPTION_HDR_LEN );
break;
}
return( NO_ERROR );
}
//**
//
// Call: CcpCheckOption
//
// Returns: NO_ERROR - Success
// ERROR_NO_REMOTE_ENCRYPTION
//
// Description: This is not an entry point. Called to check to see if an option
// value is valid and if it is the new value is saved in the
// work buffer. One of the following is returned in *pdwRetCode:
// CONFIG_ACK, CONFIG_NAK, CONFIG_REJ.
//
DWORD
CcpCheckOption(
IN CCPCB * pCcpCb,
IN CCP_SIDE * pCcpSide,
IN PPP_OPTION * pOption,
OUT DWORD * pdwRetCode,
IN BOOL fMakingResult
)
{
DWORD fEncryptionTypes = 0;
BOOL fEncryptionRequested = FALSE;
DWORD dwError = NO_ERROR;
*pdwRetCode = CONFIG_ACK;
switch( pOption->Type )
{
case CCP_OPTION_OUI:
if ( pOption->Length < (PPP_OPTION_HDR_LEN + 4) )
{
dwError = ERROR_PPP_INVALID_PACKET;
break;
}
if ( ( pCcpCb->fDisableCompression ) || ( pCcpCb->fForceEncryption ) )
{
*pdwRetCode = CONFIG_REJ;
break;
}
if ( pCcpSide->Want.CompInfo.RCI_MacCompressionType != CCP_OPTION_OUI )
{
*pdwRetCode = CONFIG_REJ;
break;
}
pCcpSide->Work.CompInfo.RCI_MacCompressionType = CCP_OPTION_OUI;
pCcpSide->Work.CompInfo.RCI_MacCompressionValueLength
= pCcpSide->Want.CompInfo.RCI_MacCompressionValueLength;
pCcpSide->Work.CompInfo.RCI_Info = pCcpSide->Want.CompInfo.RCI_Info;
if ( pOption->Length != PPP_OPTION_HDR_LEN +
pCcpSide->Want.CompInfo.RCI_MacCompressionValueLength )
{
*pdwRetCode = CONFIG_NAK;
break;
}
if ( memcmp( pOption->Data,
(PBYTE)&(pCcpSide->Want.CompInfo.RCI_Info.RCI_Proprietary),
pOption->Length - PPP_OPTION_HDR_LEN ) )
{
*pdwRetCode = CONFIG_NAK;
break;
}
break;
case CCP_OPTION_MSPPC:
if ( pOption->Length != (PPP_OPTION_HDR_LEN + 4) )
{
dwError = ERROR_PPP_INVALID_PACKET;
break;
}
pCcpSide->Work.CompInfo.RCI_MSCompressionType =
WireToHostFormat32( pOption->Data );
//
// If remote guy wants compression but we do not want it, we NAK it
//
if ( ( pCcpCb->fDisableCompression ) &&
( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_COMPRESSION ) )
{
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_COMPRESSION;
TraceCcp("Nak - Compression disabled" );
*pdwRetCode = CONFIG_NAK;
}
//
// If remote side wants do historyless, make sure we support it
//
if (pCcpSide->Work.CompInfo.RCI_MSCompressionType & MSTYPE_HISTORYLESS)
{
if ( !( pCcpSide->Want.CompInfo.RCI_MSCompressionType &
MSTYPE_HISTORYLESS))
{
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
(~MSTYPE_HISTORYLESS);
*pdwRetCode = CONFIG_NAK;
}
}
//
// Get the encryption types that are to be forced or allowed
//
fEncryptionTypes = pCcpSide->Want.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
//
// Remember if the remote guy wants encryption or not
//
fEncryptionRequested = pCcpSide->Work.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 );
//
// If we were offered 128 bit encryption
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_ENCRYPTION_128 )
{
//
// If we support it
//
if ( fEncryptionTypes & MSTYPE_ENCRYPTION_128 )
{
//
// If remote side offered any other type
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_56 ) )
{
//
// Turn them off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_56 );
TraceCcp("Nak - Accepting 128 bit");
*pdwRetCode = CONFIG_NAK;
}
}
else
{
//
// we do not support it so turn it off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_ENCRYPTION_128;
TraceCcp("Nak - 128 bit not supported");
*pdwRetCode = CONFIG_NAK;
}
}
//
// If we were offered 40 variable bit encryption and we support it
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_ENCRYPTION_56 )
{
//
// If we support it
//
if ( fEncryptionTypes & MSTYPE_ENCRYPTION_56 )
{
//
// If remote side offered any other type
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40 ) )
{
//
// Turn them off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~( MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_40);
*pdwRetCode = CONFIG_NAK;
}
}
else
{
//
// we do not support it so turn it off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_ENCRYPTION_56;
*pdwRetCode = CONFIG_NAK;
}
}
//
// If we were offered 40 bit encryption
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_ENCRYPTION_40F )
{
//
// If we support it
//
if ( fEncryptionTypes & MSTYPE_ENCRYPTION_40F )
{
//
// If the remote guy requested any other type
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_ENCRYPTION_40 )
{
//
// Turn them off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_ENCRYPTION_40;
TraceCcp("Nak - Accepting 40 bit");
*pdwRetCode = CONFIG_NAK;
}
}
else
{
//
// we do not support it so turn it off
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_ENCRYPTION_40F;
TraceCcp("Nak - 40 bit not supported");
*pdwRetCode = CONFIG_NAK;
}
}
//
// If we were offerred legacy 40 bit encryption
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
MSTYPE_ENCRYPTION_40 )
{
//
// If we don't support it then turn it off
//
if ( !( fEncryptionTypes & MSTYPE_ENCRYPTION_40 ) )
{
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
~MSTYPE_ENCRYPTION_40;
TraceCcp("Nak - legacy 40 bit not supported");
*pdwRetCode = CONFIG_NAK;
}
}
//
// If we have turned all encryption off, or none was offered, but
// we need to force encryption or remote side requested encryption,
// then we we NAK with what we want or what we can do.
//
if ( ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 ) )
== 0 )
{
if ( ( pCcpCb->fForceEncryption ) || ( fEncryptionRequested ) )
{
//
// Make sure we are going to support stuff we NAK
//
if ( fEncryptionTypes != 0 )
{
if ( fMakingResult )
{
//
// If we are NAKing then we can only send one bit.
// Find out the strongest encryption we can NAK with
//
//
// Save the last bit we NAKed with so that in case this
// NAK turns out to be REJECT we can reset to this
// value.
//
pCcpCb->fOldLastEncryptionBitSent =
pCcpCb->fLastEncryptionBitSent;
for(;;)
{
if ( pCcpCb->fLastEncryptionBitSent == 0 )
{
pCcpCb->fLastEncryptionBitSent =
MSTYPE_ENCRYPTION_128;
}
else if ( pCcpCb->fLastEncryptionBitSent ==
MSTYPE_ENCRYPTION_128 )
{
pCcpCb->fLastEncryptionBitSent =
MSTYPE_ENCRYPTION_56;
}
else if ( pCcpCb->fLastEncryptionBitSent ==
MSTYPE_ENCRYPTION_56 )
{
pCcpCb->fLastEncryptionBitSent =
MSTYPE_ENCRYPTION_40F;
}
else if ( pCcpCb->fLastEncryptionBitSent ==
MSTYPE_ENCRYPTION_40F )
{
pCcpCb->fLastEncryptionBitSent =
MSTYPE_ENCRYPTION_40;
}
else
{
//
// Cannot NAK with any encryption
//
pCcpCb->fLastEncryptionBitSent = 0;
if ( !pCcpCb->fForceEncryption )
{
//
// Give up only if we are not forcing
// encryption.
//
*pdwRetCode = CONFIG_NAK;
break;
}
else
{
//
// It is possible that the client did not
// receive our NAK's. Let us restart with
// the strongest encryption we can NAK with
//
}
}
if ( pCcpCb->fLastEncryptionBitSent &
fEncryptionTypes )
{
pCcpSide->Work.CompInfo.RCI_MSCompressionType |=
pCcpCb->fLastEncryptionBitSent;
*pdwRetCode = CONFIG_NAK;
break;
}
}
}
else if ( pCcpCb->fForceEncryption )
{
//
// We require encryption, but there is no common scheme
// that both sides can agree on.
//
return( ERROR_NO_REMOTE_ENCRYPTION );
}
else
{
//
// If we are sending a request then we can send more
// than one bit
//
pCcpSide->Work.CompInfo.RCI_MSCompressionType
|= fEncryptionTypes;
*pdwRetCode = CONFIG_NAK;
}
}
}
}
//
// Turn off any bits that we do not understand
//
if ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
~( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 |
MSTYPE_COMPRESSION |
MSTYPE_HISTORYLESS ) )
{
pCcpSide->Work.CompInfo.RCI_MSCompressionType &=
( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 |
MSTYPE_COMPRESSION |
MSTYPE_HISTORYLESS );
TraceCcp("Nak - unknown bits");
*pdwRetCode = CONFIG_NAK;
}
if ( *pdwRetCode == CONFIG_NAK )
{
if ( ( pCcpSide->Work.CompInfo.RCI_MSCompressionType &
( MSTYPE_ENCRYPTION_40 |
MSTYPE_ENCRYPTION_40F |
MSTYPE_ENCRYPTION_56 |
MSTYPE_ENCRYPTION_128 |
MSTYPE_COMPRESSION ) )
== 0 )
{
TraceCcp("Rej - No bits supported");
*pdwRetCode = CONFIG_REJ;
}
}
break;
default:
if ( pOption->Length < PPP_OPTION_HDR_LEN )
{
dwError = ERROR_PPP_INVALID_PACKET;
break;
}
if ( ( pCcpCb->fDisableCompression ) || ( pCcpCb->fForceEncryption ) )
{
*pdwRetCode = CONFIG_REJ;
break;
}
if ( pOption->Type != pCcpSide->Want.CompInfo.RCI_MacCompressionType )
{
*pdwRetCode = CONFIG_REJ;
break;
}
pCcpSide->Work.CompInfo.RCI_MacCompressionType
= pCcpSide->Want.CompInfo.RCI_MacCompressionType;
pCcpSide->Work.CompInfo.RCI_MacCompressionValueLength
= pCcpSide->Want.CompInfo.RCI_MacCompressionValueLength;
pCcpSide->Work.CompInfo.RCI_Info = pCcpSide->Want.CompInfo.RCI_Info;
if ( pOption->Length != PPP_OPTION_HDR_LEN +
pCcpSide->Want.CompInfo.RCI_MacCompressionValueLength )
{
*pdwRetCode = CONFIG_NAK;
break;
}
if ( memcmp( pOption->Data,
(PBYTE)&(pCcpSide->Want.CompInfo.RCI_Info.RCI_Public),
pOption->Length - PPP_OPTION_HDR_LEN ) )
{
*pdwRetCode = CONFIG_NAK;
break;
}
}
return( dwError );
}
//**
//
// Call: CcpBuildOptionList
//
// Returns: NO_ERROR - Success
// Non-zero returns from CcpMakeOption
//
// Description: This is not an entry point. Will build a list of options
// either for a configure request or a configure result.
//
DWORD
CcpBuildOptionList(
IN OUT BYTE * pOptions,
IN OUT DWORD * pcbOptions,
IN CCP_OPTIONS * CcpOptions,
IN DWORD Negotiate
)
{
DWORD dwRetCode;
DWORD cbOptionLength = *pcbOptions;
if ( Negotiate & CCP_N_OUI )
{
if ( ( dwRetCode = CcpMakeOption( CcpOptions,
CCP_OPTION_OUI,
(PPP_OPTION *)pOptions,
cbOptionLength ) ) != NO_ERROR )
return( dwRetCode );
cbOptionLength -= ((PPP_OPTION*)pOptions)->Length;
pOptions += ((PPP_OPTION*)pOptions)->Length;
}
if ( Negotiate & CCP_N_PUBLIC )
{
if ( ( dwRetCode = CcpMakeOption( CcpOptions,
CCP_OPTION_MAX,
(PPP_OPTION *)pOptions,
cbOptionLength ) ) != NO_ERROR )
return( dwRetCode );
cbOptionLength -= ((PPP_OPTION*)pOptions)->Length;
pOptions += ((PPP_OPTION*)pOptions)->Length;
}
if ( Negotiate & CCP_N_MSPPC )
{
if ( ( dwRetCode = CcpMakeOption( CcpOptions,
CCP_OPTION_MSPPC,
(PPP_OPTION *)pOptions,
cbOptionLength ) ) != NO_ERROR )
return( dwRetCode );
cbOptionLength -= ((PPP_OPTION*)pOptions)->Length;
pOptions += ((PPP_OPTION*)pOptions)->Length;
}
*pcbOptions -= cbOptionLength;
return( NO_ERROR );
}
//**
//
// Call: CcpMakeConfigRequest
//
// Returns: NO_ERROR - Success
// Non-zero returns from CcpBuildOptionList
//
// Description: This is a entry point that is called to make a confifure
// request packet.
//
DWORD
CcpMakeConfigRequest(
IN VOID * pWorkBuffer,
IN PPP_CONFIG * pSendConfig,
IN DWORD cbSendConfig
)
{
CCPCB * pCcpCb = (CCPCB*)pWorkBuffer;
DWORD dwRetCode;
cbSendConfig -= PPP_CONFIG_HDR_LEN;
dwRetCode = CcpBuildOptionList( pSendConfig->Data,
&cbSendConfig,
&(pCcpCb->Local.Work),
pCcpCb->Local.Work.Negotiate );
if ( dwRetCode != NO_ERROR )
return( dwRetCode );
pSendConfig->Code = CONFIG_REQ;
HostToWireFormat16( (WORD)(cbSendConfig + PPP_CONFIG_HDR_LEN),
pSendConfig->Length);
return( NO_ERROR );
}
//**
//
// Call: CcpMakeConfigResult
//
// Returns:
//
// Description:
//
DWORD
CcpMakeConfigResult(
IN VOID * pWorkBuffer,
IN PPP_CONFIG * pRecvConfig,
OUT PPP_CONFIG * pSendConfig,
IN DWORD cbSendConfig,
IN BOOL fRejectNaks
)
{
DWORD OptionListLength;
DWORD NumOptionsInRequest = 0;
DWORD dwRetCode;
DWORD dwError;
CCPCB * pCcpCb = (CCPCB*)pWorkBuffer;
DWORD ResultType = CONFIG_ACK;
PPP_OPTION * pRecvOption = (PPP_OPTION *)(pRecvConfig->Data);
PPP_OPTION * pSendOption = (PPP_OPTION *)(pSendConfig->Data);
LONG lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
LONG lRecvLength = WireToHostFormat16( pRecvConfig->Length )
- PPP_CONFIG_HDR_LEN;
//
// Clear negotiate mask
//
pCcpCb->Remote.Work.Negotiate = 0;
//
// Process options requested by remote host
//
while( lRecvLength > 0 )
{
if ( ( lRecvLength -= pRecvOption->Length ) < 0 )
{
return( ERROR_PPP_INVALID_PACKET );
}
NumOptionsInRequest++;
dwError = CcpCheckOption(pCcpCb, &(pCcpCb->Remote), pRecvOption,
&dwRetCode, TRUE);
if ( NO_ERROR != dwError )
{
return( dwError );
}
//
// If we were building an ACK and we got a NAK or reject OR
// we were building a NAK and we got a reject.
//
if ( (( ResultType == CONFIG_ACK ) && ( dwRetCode != CONFIG_ACK )) ||
(( ResultType == CONFIG_NAK ) && ( dwRetCode == CONFIG_REJ )) )
{
ResultType = dwRetCode;
pSendOption = (PPP_OPTION *)(pSendConfig->Data);
lSendLength = cbSendConfig - PPP_CONFIG_HDR_LEN;
}
//
// Remember that we processed this option
//
if ( ( dwRetCode != CONFIG_REJ ) &&
( pRecvOption->Type <= CCP_OPTION_MAX ) )
{
switch( pRecvOption->Type )
{
case CCP_OPTION_OUI:
pCcpCb->Remote.Work.Negotiate |= CCP_N_OUI;
break;
case CCP_OPTION_MSPPC:
pCcpCb->Remote.Work.Negotiate |= CCP_N_MSPPC;
break;
default:
pCcpCb->Remote.Work.Negotiate |= CCP_N_PUBLIC;
break;
}
}
//
// Add the option to the list.
//
if ( dwRetCode == ResultType )
{
//
// If this option is to be rejected, simply copy the
// rejected option to the send buffer
//
if ( ( dwRetCode == CONFIG_REJ ) ||
( ( dwRetCode == CONFIG_NAK ) && ( fRejectNaks ) ) )
{
CopyMemory( pSendOption, pRecvOption, pRecvOption->Length );
lSendLength -= pSendOption->Length;
pSendOption = (PPP_OPTION *)
( (BYTE *)pSendOption + pSendOption->Length );
}
}
pRecvOption = (PPP_OPTION *)((BYTE*)pRecvOption + pRecvOption->Length);
}
//
// If this was an NAK and we have cannot send any more NAKS then we
// make this a REJECT packet
//
if ( ( ResultType == CONFIG_NAK ) && fRejectNaks )
pSendConfig->Code = CONFIG_REJ;
else
pSendConfig->Code = (BYTE)ResultType;
//
// Remote wants no options, accept this
//
if ( NumOptionsInRequest == 0 )
{
//
// Accept no options only if we are not forcing encryption
//
if ( pCcpCb->fForceEncryption )
{
NumOptionsInRequest = 1;
pCcpCb->Remote.Work.Negotiate = CCP_N_MSPPC;
ResultType = CONFIG_NAK;
}
}
//
// If we are responding to the request with a NAK or an ACK then we make
// that we choose only one option.
//
if ( ( ( ResultType == CONFIG_ACK ) || ( ResultType == CONFIG_NAK ) )
&& ( NumOptionsInRequest > 0 ) )
{
if ( pCcpCb->Remote.Work.Negotiate & CCP_N_MSPPC )
{
pCcpCb->Remote.Work.Negotiate = CCP_N_MSPPC;
if ( ( dwRetCode = CcpMakeOption( &(pCcpCb->Remote.Work),
CCP_OPTION_MSPPC,
pSendOption,
lSendLength ) ) != NO_ERROR )
return( dwRetCode );
}
else if ( pCcpCb->Remote.Work.Negotiate & CCP_N_OUI )
{
pCcpCb->Remote.Work.Negotiate = CCP_N_OUI;
if ( ( dwRetCode = CcpMakeOption( &(pCcpCb->Remote.Work),
CCP_OPTION_OUI,
pSendOption,
lSendLength ) ) != NO_ERROR )
return( dwRetCode );
}
else
{
pCcpCb->Remote.Work.Negotiate = CCP_N_PUBLIC;
if ( ( dwRetCode = CcpMakeOption( &(pCcpCb->Remote.Work),
CCP_OPTION_MAX,
pSendOption,
lSendLength ) ) != NO_ERROR )
return( dwRetCode );
}
if ( ( NumOptionsInRequest > 1 ) && ( ResultType == CONFIG_ACK ) )
{
pSendConfig->Code = CONFIG_NAK;
}
else
{
pSendConfig->Code = (BYTE)ResultType;
}
lSendLength -= pSendOption->Length;
}
//
// If we are rejecting then we reset the current value to the old value
//
if ( pSendConfig->Code == CONFIG_REJ )
{
pCcpCb->fLastEncryptionBitSent = pCcpCb->fOldLastEncryptionBitSent;
}
else
{
pCcpCb->fOldLastEncryptionBitSent = pCcpCb->fLastEncryptionBitSent;
}
HostToWireFormat16( (WORD)(cbSendConfig - lSendLength),
pSendConfig->Length );
return( NO_ERROR );
}
//**
//
// Call: CcpConfigAckReceived
//
// Returns:
//
// Description:
//
DWORD
CcpConfigAckReceived(
IN VOID * pWorkBuffer,
IN PPP_CONFIG * pRecvConfig
)
{
DWORD dwRetCode;
BYTE ConfigReqSent[500];
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
DWORD cbConfigReqSent = sizeof( ConfigReqSent );
DWORD dwLength = WireToHostFormat16( pRecvConfig->Length )
- PPP_CONFIG_HDR_LEN;
//
// Get a copy of last request we sent
//
dwRetCode = CcpBuildOptionList( ConfigReqSent,
&cbConfigReqSent,
&(pCcpCb->Local.Work),
pCcpCb->Local.Work.Negotiate );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
//
// Overall buffer length should match
//
if ( dwLength != cbConfigReqSent )
{
return( ERROR_PPP_INVALID_PACKET );
}
//
// Each byte should match
//
if ( memcmp( ConfigReqSent, pRecvConfig->Data, dwLength ) != 0 )
{
return( ERROR_PPP_INVALID_PACKET );
}
return( NO_ERROR );
}
//**
//
// Call: CcpConfigNakReceived
//
// Returns:
//
// Description:
//
DWORD
CcpConfigNakReceived(
IN VOID * pWorkBuffer,
IN PPP_CONFIG * pRecvConfig
)
{
DWORD fAcceptableOptions = 0;
DWORD dwResult;
DWORD dwError;
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
PPP_OPTION * pOption = (PPP_OPTION*)(pRecvConfig->Data);
DWORD dwLastOption = 0;
LONG lcbRecvConfig = WireToHostFormat16( pRecvConfig->Length )
- PPP_CONFIG_HDR_LEN;
//
// First, process in order. Then, process extra "important" options
//
while ( lcbRecvConfig > 0 )
{
if ( ( lcbRecvConfig -= pOption->Length ) < 0 )
{
return( ERROR_PPP_INVALID_PACKET );
}
//
// Our requests are always sent out in order of increasing option type
// values.
//
if ( pOption->Type < dwLastOption )
{
return( ERROR_PPP_INVALID_PACKET );
}
dwLastOption = pOption->Type;
dwError = CcpCheckOption( pCcpCb, &(pCcpCb->Local), pOption,
&dwResult, FALSE);
if ( NO_ERROR != dwError )
{
return( dwError );
}
//
// Update the negotiation status. If we cannot accept this option,
// then we will not send it again.
//
switch( pOption->Type )
{
case CCP_OPTION_OUI:
if ( dwResult == CONFIG_REJ )
{
pCcpCb->Local.Work.Negotiate &= ~CCP_N_OUI;
}
if ( dwResult == CONFIG_ACK )
{
fAcceptableOptions |= CCP_N_OUI;
}
break;
case CCP_OPTION_MSPPC:
if ( dwResult == CONFIG_REJ )
{
pCcpCb->Local.Work.Negotiate &= ~CCP_N_MSPPC;
}
if ( dwResult == CONFIG_ACK )
{
fAcceptableOptions |= CCP_N_MSPPC;
}
break;
default:
if ( dwResult == CONFIG_REJ )
{
pCcpCb->Local.Work.Negotiate &= ~CCP_N_PUBLIC;
}
if ( dwResult == CONFIG_ACK )
{
fAcceptableOptions |= CCP_N_PUBLIC;
}
break;
}
pOption = (PPP_OPTION *)( (BYTE *)pOption + pOption->Length );
}
if ( pCcpCb->Local.Work.Negotiate == 0 )
{
if ( pCcpCb->fForceEncryption )
{
fAcceptableOptions = CCP_N_MSPPC;
}
else
{
fAcceptableOptions = 0;
}
}
//
// If there was more than one option that was acceptable give
// preference to OUI, then to PUBLIC, then to MSPPC
//
if ( fAcceptableOptions & CCP_N_OUI )
{
pCcpCb->Local.Work.Negotiate = CCP_N_OUI;
}
else if ( fAcceptableOptions & CCP_N_PUBLIC )
{
pCcpCb->Local.Work.Negotiate = CCP_N_PUBLIC;
}
else if ( fAcceptableOptions & CCP_N_MSPPC )
{
pCcpCb->Local.Work.Negotiate = CCP_N_MSPPC;
}
return( NO_ERROR );
}
//**
//
// Call: CcpConfigRejReceived
//
// Returns:
//
// Description:
//
DWORD
CcpConfigRejReceived(
IN VOID * pWorkBuffer,
IN PPP_CONFIG * pRecvConfig
)
{
DWORD dwRetCode;
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
PPP_OPTION * pOption = (PPP_OPTION*)(pRecvConfig->Data);
DWORD dwLastOption = 0;
BYTE ReqOption[500];
LONG lcbRecvConfig = WireToHostFormat16( pRecvConfig->Length )
- PPP_CONFIG_HDR_LEN;
//
// Process in order, checking for errors
//
while ( lcbRecvConfig > 0 )
{
if ( ( lcbRecvConfig -= pOption->Length ) < 0 )
{
return( ERROR_PPP_INVALID_PACKET );
}
//
// The option should not have been modified in any way
//
if ( ( dwRetCode = CcpMakeOption( &(pCcpCb->Local.Work),
pOption->Type,
(PPP_OPTION *)ReqOption,
sizeof( ReqOption ) ) ) != NO_ERROR )
return( dwRetCode );
if ( memcmp( ReqOption, pOption, pOption->Length ) != 0 )
{
return( ERROR_PPP_INVALID_PACKET );
}
dwLastOption = pOption->Type;
//
// The next configure request should not contain this option
//
if ( pOption->Type <= CCP_OPTION_MAX )
{
switch( pOption->Type )
{
case CCP_OPTION_OUI:
pCcpCb->Local.Work.Negotiate &= ~CCP_N_OUI;
break;
case CCP_OPTION_MSPPC:
pCcpCb->Local.Work.Negotiate &= ~CCP_N_MSPPC;
break;
default:
pCcpCb->Local.Work.Negotiate &= ~CCP_N_PUBLIC;
break;
}
}
pOption = (PPP_OPTION *)( (BYTE *)pOption + pOption->Length );
}
if ( pCcpCb->Local.Work.Negotiate == 0 )
{
return( ERROR_PPP_NOT_CONVERGING );
}
return( NO_ERROR );
}
//**
//
// Call: CcpThisLayerStarted
//
// Returns:
//
// Description:
//
DWORD
CcpThisLayerStarted(
IN VOID * pWorkBuffer
)
{
return( NO_ERROR );
}
//**
//
// Call: CcpThisLayerFinished
//
// Returns:
//
// Description:
//
DWORD
CcpThisLayerFinished(
IN VOID * pWorkBuffer
)
{
return( NO_ERROR );
}
//**
//
// Call: CcpThisLayerUp
//
// Returns: None
//
// Description: Sets the framing parameters to what was negotiated.
//
DWORD
CcpThisLayerUp(
IN VOID * pWorkBuffer
)
{
DWORD dwRetCode = NO_ERROR;
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
RAS_COMPRESSION_INFO RasCompInfoSend;
RAS_COMPRESSION_INFO RasCompInfoRecv;
if ( pCcpCb->Local.Work.Negotiate == CCP_N_MSPPC )
{
TraceCcp("CCP Send MSPPC bits negotiated = 0x%x",
pCcpCb->Local.Work.CompInfo.RCI_MSCompressionType );
pCcpCb->Local.Work.CompInfo.RCI_MacCompressionType = CCP_OPTION_MAX + 1;
}
else if ( pCcpCb->Local.Work.Negotiate == CCP_N_PUBLIC )
{
TraceCcp("CCP Send PUBLIC");
pCcpCb->Local.Work.CompInfo.RCI_MSCompressionType = 0;
}
else if ( pCcpCb->Local.Work.Negotiate == CCP_N_OUI )
{
TraceCcp("CCP Send OUI");
pCcpCb->Local.Work.CompInfo.RCI_MSCompressionType = 0;
}
if ( pCcpCb->Remote.Work.Negotiate == CCP_N_MSPPC )
{
TraceCcp("CCP Recv MSPPC bits negotiated = 0x%x",
pCcpCb->Remote.Work.CompInfo.RCI_MSCompressionType );
pCcpCb->Remote.Work.CompInfo.RCI_MacCompressionType = CCP_OPTION_MAX+1;
}
else if ( pCcpCb->Remote.Work.Negotiate == CCP_N_PUBLIC )
{
TraceCcp("CCP Recv PUBLIC");
pCcpCb->Remote.Work.CompInfo.RCI_MSCompressionType = 0;
}
else if ( pCcpCb->Remote.Work.Negotiate == CCP_N_OUI )
{
TraceCcp("CCP Recv OUI");
pCcpCb->Remote.Work.CompInfo.RCI_MSCompressionType = 0;
}
dwRetCode = RasCompressionGetInfo( pCcpCb->hPort,
&RasCompInfoSend,
&RasCompInfoRecv );
if ( dwRetCode != NO_ERROR )
{
return( dwRetCode );
}
CopyMemory( pCcpCb->Local.Work.CompInfo.RCI_LMSessionKey,
RasCompInfoSend.RCI_LMSessionKey,
MAX_SESSIONKEY_SIZE );
CopyMemory( pCcpCb->Local.Work.CompInfo.RCI_UserSessionKey,
RasCompInfoSend.RCI_UserSessionKey,
MAX_USERSESSIONKEY_SIZE );
CopyMemory( pCcpCb->Local.Work.CompInfo.RCI_Challenge,
RasCompInfoSend.RCI_Challenge,
MAX_CHALLENGE_SIZE );
CopyMemory( pCcpCb->Local.Work.CompInfo.RCI_NTResponse,
RasCompInfoSend.RCI_NTResponse,
MAX_NT_RESPONSE_SIZE );
pCcpCb->Local.Work.CompInfo.RCI_Flags = CCP_SET_COMPTYPE;
CopyMemory( pCcpCb->Remote.Work.CompInfo.RCI_LMSessionKey,
RasCompInfoRecv.RCI_LMSessionKey,
MAX_SESSIONKEY_SIZE );
CopyMemory( pCcpCb->Remote.Work.CompInfo.RCI_UserSessionKey,
RasCompInfoRecv.RCI_UserSessionKey,
MAX_USERSESSIONKEY_SIZE );
CopyMemory( pCcpCb->Remote.Work.CompInfo.RCI_Challenge,
RasCompInfoRecv.RCI_Challenge,
MAX_CHALLENGE_SIZE );
CopyMemory( pCcpCb->Remote.Work.CompInfo.RCI_NTResponse,
RasCompInfoRecv.RCI_NTResponse,
MAX_NT_RESPONSE_SIZE );
pCcpCb->Remote.Work.CompInfo.RCI_Flags = CCP_SET_COMPTYPE;
if ( pCcpCb->fServer )
{
pCcpCb->Local.Work.CompInfo.RCI_Flags |= CCP_IS_SERVER;
pCcpCb->Remote.Work.CompInfo.RCI_Flags |= CCP_IS_SERVER;
}
dwRetCode = RasCompressionSetInfo( pCcpCb->hPort,
&(pCcpCb->Local.Work.CompInfo),
&(pCcpCb->Remote.Work.CompInfo) );
return( dwRetCode );
}
//**
//
// Call: CcpThisLayerDown
//
// Returns: NO_ERROR - Success
// Non-zero return from RasPortSetFraming - Failure
//
// Description: Simply sets the framing parameters to the default values,
// ie. ACCM = 0xFFFFFFFF, everything else is zeros.
//
DWORD
CcpThisLayerDown(
IN VOID * pWorkBuffer
)
{
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
RAS_COMPRESSION_INFO CompInfo;
ZeroMemory( &CompInfo, sizeof( CompInfo ) );
CompInfo.RCI_Flags = CCP_SET_COMPTYPE;
CompInfo.RCI_MSCompressionType = 0;
CompInfo.RCI_MacCompressionType = CCP_OPTION_MAX + 1;
CopyMemory( CompInfo.RCI_LMSessionKey,
pCcpCb->Local.Want.CompInfo.RCI_LMSessionKey,
sizeof( CompInfo.RCI_LMSessionKey ) );
CopyMemory( CompInfo.RCI_UserSessionKey,
pCcpCb->Local.Want.CompInfo.RCI_UserSessionKey,
sizeof( CompInfo.RCI_UserSessionKey ) );
CopyMemory( CompInfo.RCI_Challenge,
pCcpCb->Local.Want.CompInfo.RCI_Challenge,
sizeof( CompInfo.RCI_Challenge ) );
if ( pCcpCb->fForceEncryption )
{
pCcpCb->Local.Work.CompInfo.RCI_Flags |= CCP_PAUSE_DATA;
pCcpCb->Remote.Work.CompInfo.RCI_Flags |= CCP_PAUSE_DATA;
}
RasCompressionSetInfo( pCcpCb->hPort, &CompInfo, &CompInfo );
return( NO_ERROR );
}
//**
//
// Call: CcpGetNegotiatedInfo
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will return the type of compression and associated date
// negotiated for both directions.
//
DWORD
CcpGetNegotiatedInfo(
IN VOID * pWorkBuffer,
OUT PPP_CCP_RESULT * pCcpResult
)
{
CCPCB * pCcpCb = (CCPCB *)pWorkBuffer;
if ( pCcpCb->Local.Work.Negotiate == CCP_N_MSPPC )
{
pCcpResult->dwSendProtocol = CCP_OPTION_MSPPC;
pCcpResult->dwSendProtocolData =
pCcpCb->Local.Work.CompInfo.RCI_MSCompressionType;
}
else
{
pCcpResult->dwSendProtocol =
pCcpCb->Local.Work.CompInfo.RCI_MacCompressionType;
}
if ( pCcpCb->Remote.Work.Negotiate == CCP_N_MSPPC )
{
pCcpResult->dwReceiveProtocol = CCP_OPTION_MSPPC;
pCcpResult->dwReceiveProtocolData =
pCcpCb->Remote.Work.CompInfo.RCI_MSCompressionType;
}
else
{
pCcpResult->dwReceiveProtocol =
pCcpCb->Remote.Work.CompInfo.RCI_MacCompressionType;
}
return( NO_ERROR );
}
//**
//
// Call: CcpGetInfo
//
// Returns: NO_ERROR - Success
// ERROR_INVALID_PARAMETER - Protocol id is unrecogized
//
// Description: This entry point is called for get all information for the
// control protocol in this module.
//
DWORD
CcpGetInfo(
IN DWORD dwProtocolId,
OUT PPPCP_INFO* pCpInfo
)
{
if ( dwProtocolId != PPP_CCP_PROTOCOL )
{
return( ERROR_INVALID_PARAMETER );
}
ZeroMemory( pCpInfo, sizeof( PPPCP_INFO ) );
pCpInfo->Protocol = PPP_CCP_PROTOCOL;
lstrcpy(pCpInfo->SzProtocolName, "CCP");
pCpInfo->Recognize = CODE_REJ + 1;
pCpInfo->RasCpInit = CcpInit;
pCpInfo->RasCpBegin = CcpBegin;
pCpInfo->RasCpEnd = CcpEnd;
pCpInfo->RasCpReset = CcpReset;
pCpInfo->RasCpThisLayerStarted = CcpThisLayerStarted;
pCpInfo->RasCpThisLayerFinished = CcpThisLayerFinished;
pCpInfo->RasCpThisLayerUp = CcpThisLayerUp;
pCpInfo->RasCpThisLayerDown = CcpThisLayerDown;
pCpInfo->RasCpMakeConfigRequest = CcpMakeConfigRequest;
pCpInfo->RasCpMakeConfigResult = CcpMakeConfigResult;
pCpInfo->RasCpConfigAckReceived = CcpConfigAckReceived;
pCpInfo->RasCpConfigNakReceived = CcpConfigNakReceived;
pCpInfo->RasCpConfigRejReceived = CcpConfigRejReceived;
pCpInfo->RasCpGetNegotiatedInfo = CcpGetNegotiatedInfo;
return( NO_ERROR );
}