/********************************************************************/ /** Copyright(c) 1989 Microsoft Corporation. **/ /********************************************************************/ //*** // // Filename: rasccp.c // // Description: Contains entry points to configure CCP. // // History: April 11,1994. NarenG Created original version. // // #include #include #include // needed for winbase.h #include // Win32 base API's #include #include #include #include #include #include #include #include #define INCL_HOSTWIRE #define INCL_ENCRYPT #define INCL_RASAUTHATTRIBUTES #include #define CCPGLOBALS #include //** // // 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 ); }