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.
1075 lines
28 KiB
1075 lines
28 KiB
/********************************************************************/
|
|
/** Copyright(c) 1989 Microsoft Corporation. **/
|
|
/********************************************************************/
|
|
|
|
//***
|
|
//
|
|
// Filename: rascbcp.c
|
|
//
|
|
// Description: This module contains code to implement the PPP Callback
|
|
// Control Protocol.
|
|
//
|
|
// History: April 11,1994. NarenG Created original version
|
|
//
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <ntlsa.h>
|
|
#include <ntmsv1_0.h>
|
|
#include <crypt.h>
|
|
|
|
#include <windows.h>
|
|
#include <lmcons.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <rasman.h>
|
|
#include <pppcp.h>
|
|
#define INCL_PWUTIL
|
|
#define INCL_HOSTWIRE
|
|
#include <ppputil.h>
|
|
#include "rascbcp.h"
|
|
#include <raserror.h>
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPGetInfo
|
|
//
|
|
// Returns: NO_ERROR
|
|
//
|
|
// Description: CbCPGetInfo entry point called by the PPP engine.
|
|
// See RasCpGetInfo interface documentation.
|
|
//
|
|
DWORD
|
|
CbCPGetInfo(
|
|
IN DWORD dwProtocolId,
|
|
OUT PPPCP_INFO* pInfo
|
|
)
|
|
{
|
|
ZeroMemory( pInfo, sizeof(PPPCP_INFO) );
|
|
|
|
pInfo->Protocol = (DWORD)PPP_CBCP_PROTOCOL;
|
|
lstrcpy(pInfo->SzProtocolName, "CBCP");
|
|
pInfo->Recognize = MAX_CBCP_CODE + 1;
|
|
pInfo->RasCpBegin = CbCPBegin;
|
|
pInfo->RasCpEnd = CbCPEnd;
|
|
pInfo->RasApMakeMessage = CbCPMakeMessage;
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPBegin
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero return code - failure
|
|
//
|
|
// Description: RasCpBegin entry point called by the PPP engine thru the
|
|
// passed address. See RasCp interface documentation. This is
|
|
// called by the PPP engine before any other calls to CbCP is
|
|
// made.
|
|
//
|
|
DWORD
|
|
CbCPBegin(
|
|
OUT VOID** ppWorkBuf,
|
|
IN VOID* pInfo
|
|
)
|
|
{
|
|
PPPCB_INPUT * pInput = (PPPCB_INPUT *)pInfo;
|
|
CBCP_WORKBUFFER * pWorkBuf;
|
|
DWORD dwRetCode;
|
|
|
|
//
|
|
// Allocate work buffer.
|
|
//
|
|
|
|
pWorkBuf = (CBCP_WORKBUFFER *)LocalAlloc(LPTR,sizeof(CBCP_WORKBUFFER));
|
|
|
|
if ( pWorkBuf == NULL )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
pWorkBuf->State = CBCP_STATE_INITIAL;
|
|
|
|
pWorkBuf->fServer = pInput->fServer;
|
|
|
|
//
|
|
// If we are the server side then get all the callback information for
|
|
// this user
|
|
//
|
|
|
|
if ( pWorkBuf->fServer )
|
|
{
|
|
pWorkBuf->fCallbackPrivilege = pInput->bfCallbackPrivilege;
|
|
|
|
strcpy( pWorkBuf->szCallbackNumber, pInput->pszCallbackNumber );
|
|
}
|
|
else
|
|
{
|
|
pWorkBuf->CallbackDelay = pInput->CallbackDelay;
|
|
}
|
|
|
|
//
|
|
// Register work buffer with engine.
|
|
//
|
|
|
|
*ppWorkBuf = pWorkBuf;
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPEnd
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
//
|
|
// Description: Called by the PPP engine to notify this Control Protocol to
|
|
// clean up.
|
|
//
|
|
DWORD
|
|
CbCPEnd(
|
|
IN VOID* pWorkBuffer
|
|
)
|
|
{
|
|
CBCP_WORKBUFFER * pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
|
|
|
|
if ( pWorkBuf->pRequest != (PPP_CONFIG *)NULL )
|
|
{
|
|
LocalFree( pWorkBuf->pRequest );
|
|
}
|
|
|
|
if ( pWorkBuf->pResponse != (PPP_CONFIG *)NULL )
|
|
{
|
|
LocalFree( pWorkBuf->pResponse );
|
|
}
|
|
|
|
if ( pWorkBuf != NULL )
|
|
{
|
|
LocalFree( pWorkBuf );
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPMakeMessage
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero return code - failure
|
|
//
|
|
// Description: Called by the PPP engine to process a CbCP event. ie to send
|
|
// a packet, to process a received packet or to process a timeout
|
|
// event.
|
|
//
|
|
DWORD
|
|
CbCPMakeMessage(
|
|
IN VOID* pWorkBuffer,
|
|
IN PPP_CONFIG* pReceiveBuf,
|
|
OUT PPP_CONFIG* pSendBuf,
|
|
IN DWORD cbSendBuf,
|
|
OUT PPPAP_RESULT* pResult,
|
|
IN PPPAP_INPUT* pInput
|
|
)
|
|
{
|
|
CBCP_WORKBUFFER* pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
|
|
|
|
return( (pWorkBuf->fServer)
|
|
|
|
? CbCPSMakeMessage( pWorkBuf,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
(PPPCB_RESULT *)pResult,
|
|
(PPPCB_INPUT *)pInput )
|
|
|
|
: CbCPCMakeMessage( pWorkBuf,
|
|
pReceiveBuf,
|
|
pSendBuf,
|
|
cbSendBuf,
|
|
(PPPCB_RESULT *)pResult,
|
|
(PPPCB_INPUT *)pInput ) );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPCMakeMessage
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero return - failure
|
|
//
|
|
// Description: Called to process the client side of Callback Control
|
|
// Protocol.
|
|
//
|
|
DWORD
|
|
CbCPCMakeMessage(
|
|
IN CBCP_WORKBUFFER * pWorkBuf,
|
|
IN PPP_CONFIG* pReceiveBuf,
|
|
OUT PPP_CONFIG* pSendBuf,
|
|
IN DWORD cbSendBuf,
|
|
OUT PPPCB_RESULT* pResult,
|
|
IN PPPCB_INPUT* pInput
|
|
)
|
|
{
|
|
DWORD dwRetCode;
|
|
DWORD dwLength;
|
|
|
|
switch( pWorkBuf->State )
|
|
{
|
|
|
|
case CBCP_STATE_INITIAL:
|
|
|
|
//
|
|
// Do nothing, wait for request
|
|
//
|
|
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_REQUEST;
|
|
pResult->Action = APA_NoAction;
|
|
pResult->fGetCallbackNumberFromUser = FALSE;
|
|
|
|
break;
|
|
|
|
case CBCP_STATE_WAIT_FOR_REQUEST:
|
|
|
|
//
|
|
// We have received a callback request from the server.
|
|
// Save the callback request.
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pReceiveBuf->Length );
|
|
|
|
if ( ( dwLength < PPP_CONFIG_HDR_LEN ) ||
|
|
( pReceiveBuf->Code != CBCP_CODE_Request ) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
|
|
|
|
if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
memcpy( pWorkBuf->pRequest, pReceiveBuf, dwLength );
|
|
|
|
//
|
|
// Find out what kind of callback privileges we have.
|
|
//
|
|
|
|
dwRetCode = GetCallbackPrivilegeFromRequest(
|
|
pWorkBuf->pRequest,
|
|
&(pWorkBuf->fCallbackPrivilege));
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// If we have user specifiable callback, then we need to get this
|
|
// information from the user.
|
|
//
|
|
|
|
if ( pWorkBuf->fCallbackPrivilege == RASPRIV_CallerSetCallback )
|
|
{
|
|
pResult->fGetCallbackNumberFromUser=TRUE;
|
|
pResult->Action =APA_NoAction;
|
|
pWorkBuf->State =CBCP_STATE_GET_CALLBACK_NUMBER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Otherwise we make a reponse with preset or no callback
|
|
//
|
|
|
|
dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
|
|
(LPSTR)NULL,
|
|
pWorkBuf->CallbackDelay,
|
|
pWorkBuf->pRequest,
|
|
pSendBuf,
|
|
cbSendBuf );
|
|
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// Save the response sent
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
pWorkBuf->pResponse = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
|
|
|
|
if ( pWorkBuf->pResponse == (PPP_CONFIG *)NULL )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout;
|
|
pResult->bIdExpected = pReceiveBuf->Id;
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
|
|
|
|
break;
|
|
|
|
case CBCP_STATE_GET_CALLBACK_NUMBER:
|
|
|
|
//
|
|
// If we have not received any packet when we are called that means
|
|
// that we have got the callback number from the user.
|
|
//
|
|
|
|
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
|
|
{
|
|
//
|
|
// If no callback number was supplied then we do not want to
|
|
// do callback
|
|
//
|
|
|
|
if ( *(pInput->pszCallbackNumber) == (CHAR)NULL )
|
|
{
|
|
pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
|
|
}
|
|
|
|
dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
|
|
pInput->pszCallbackNumber,
|
|
pWorkBuf->CallbackDelay,
|
|
pWorkBuf->pRequest,
|
|
pSendBuf,
|
|
cbSendBuf );
|
|
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// Save the response sent
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
pWorkBuf->pResponse = (PPP_CONFIG*)LocalAlloc( LPTR, dwLength );
|
|
|
|
if ( pWorkBuf->pResponse == NULL )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout;
|
|
pResult->bIdExpected = pWorkBuf->pResponse->Id;
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
|
|
if ( pReceiveBuf->Code == CBCP_CODE_Request )
|
|
{
|
|
//
|
|
// If we received another callback request, just save the id.
|
|
// If the current request is different than the previous one
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
|
|
|
|
if (( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
|
|
( memcmp( ((PBYTE)(pWorkBuf->pRequest))+PPP_CONFIG_HDR_LEN,
|
|
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
|
|
dwLength - PPP_CONFIG_HDR_LEN ) ) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
pWorkBuf->pRequest->Id = pReceiveBuf->Id;
|
|
}
|
|
else
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
}
|
|
|
|
pResult->Action = APA_NoAction;
|
|
pResult->fGetCallbackNumberFromUser = FALSE;
|
|
|
|
break;
|
|
|
|
case CBCP_STATE_WAIT_FOR_ACK:
|
|
|
|
//
|
|
// If the receive buffer is NULL, then we have a timeout event,
|
|
// resend the response
|
|
//
|
|
|
|
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
|
|
{
|
|
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
|
|
|
|
if ( dwLength > cbSendBuf )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If we received another request then simply respond with
|
|
// the same response except change the id.
|
|
//
|
|
|
|
if ( pReceiveBuf->Code == CBCP_CODE_Request )
|
|
{
|
|
//
|
|
// If the current request is different than the previous one
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
|
|
|
|
if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
|
|
( memcmp( ((PBYTE)(pWorkBuf->pRequest)) + PPP_CONFIG_HDR_LEN,
|
|
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
|
|
dwLength - PPP_CONFIG_HDR_LEN ) ) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
if ( dwLength > cbSendBuf )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pWorkBuf->pRequest->Id = pReceiveBuf->Id;
|
|
pWorkBuf->pResponse->Id = pReceiveBuf->Id;
|
|
pResult->bIdExpected = pReceiveBuf->Id;
|
|
pResult->Action = APA_SendWithTimeout;
|
|
|
|
memcpy( pSendBuf,
|
|
pWorkBuf->pResponse,
|
|
WireToHostFormat16( pWorkBuf->pResponse->Length ) );
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If this is an ACK, then validate it and then prepare for callback
|
|
//
|
|
|
|
if ( pReceiveBuf->Code == CBCP_CODE_Ack )
|
|
{
|
|
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
|
|
|
|
if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
|
|
( memcmp( ((PBYTE)(pWorkBuf->pResponse)) + PPP_CONFIG_HDR_LEN,
|
|
((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
|
|
dwLength - PPP_CONFIG_HDR_LEN ) ) )
|
|
{
|
|
|
|
//
|
|
// If this Ack is invalid then we resend the response.
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
|
|
|
|
if ( dwLength > cbSendBuf )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// We are done
|
|
//
|
|
|
|
pResult->Action = APA_Done;
|
|
pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
|
|
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
default:
|
|
|
|
pResult->Action = APA_NoAction;
|
|
pResult->fGetCallbackNumberFromUser = FALSE;
|
|
|
|
break;
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: CbCPSMakeMessage
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// non-zero return - failure
|
|
//
|
|
// Description: Will be called to process and server side Callback Control
|
|
// Protocol event.
|
|
//
|
|
DWORD
|
|
CbCPSMakeMessage(
|
|
IN CBCP_WORKBUFFER * pWorkBuf,
|
|
IN PPP_CONFIG* pReceiveBuf,
|
|
OUT PPP_CONFIG* pSendBuf,
|
|
IN DWORD cbSendBuf,
|
|
OUT PPPCB_RESULT* pResult,
|
|
IN PPPCB_INPUT* pInput
|
|
)
|
|
{
|
|
DWORD dwRetCode;
|
|
DWORD dwLength;
|
|
|
|
switch( pWorkBuf->State )
|
|
{
|
|
|
|
case CBCP_STATE_INITIAL:
|
|
|
|
//
|
|
// Make the request based on the user's callback privelege
|
|
//
|
|
|
|
dwRetCode = MakeRequest( pWorkBuf->fCallbackPrivilege,
|
|
pSendBuf,
|
|
cbSendBuf );
|
|
|
|
if ( dwRetCode != NO_ERROR )
|
|
{
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// Set the Id of the first request to 1
|
|
//
|
|
|
|
pSendBuf->Id = 1;
|
|
|
|
//
|
|
// Save the request
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pSendBuf->Length );
|
|
|
|
pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
|
|
|
|
if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
|
|
{
|
|
return( GetLastError() );
|
|
}
|
|
|
|
memcpy( pWorkBuf->pRequest, pSendBuf, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout2;
|
|
pResult->bIdExpected = pWorkBuf->pRequest->Id;
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
|
|
|
|
break;
|
|
|
|
case CBCP_STATE_WAIT_FOR_RESPONSE:
|
|
|
|
//
|
|
// If the Receive buffer is NULL that means that we got a timeout.
|
|
// So resend the request.
|
|
//
|
|
|
|
if ( pReceiveBuf == (PPP_CONFIG *)NULL )
|
|
{
|
|
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
//
|
|
// Increment the request id
|
|
//
|
|
|
|
(pWorkBuf->pRequest->Id)++;
|
|
|
|
memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout2;
|
|
pResult->bIdExpected = pWorkBuf->pRequest->Id;
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
case CBCP_STATE_DONE:
|
|
|
|
if ( pReceiveBuf == NULL )
|
|
{
|
|
//
|
|
// If we receive a timeout in the DONE state, we just ignore it.
|
|
//
|
|
|
|
pResult->Action = APA_NoAction;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If we have received a response from the client, then validate
|
|
// it and send an ACK or another request.
|
|
//
|
|
|
|
if ( pReceiveBuf->Code == CBCP_CODE_Response )
|
|
{
|
|
//
|
|
// Check the id of the response packet. If the Id is bad then
|
|
// silently discard it
|
|
//
|
|
|
|
if ( pReceiveBuf->Id != pWorkBuf->pRequest->Id )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
dwRetCode = ValidateResponse( pReceiveBuf, pWorkBuf );
|
|
|
|
if ( dwRetCode == ERROR_PPP_INVALID_PACKET )
|
|
{
|
|
//
|
|
// If the response received was invalid, resend the request
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
//
|
|
// Increment the request id
|
|
//
|
|
|
|
(pWorkBuf->pRequest->Id)++;
|
|
|
|
memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
|
|
|
|
pResult->Action = APA_SendWithTimeout2;
|
|
pResult->bIdExpected = pWorkBuf->pRequest->Id;
|
|
pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
|
|
|
|
break;
|
|
}
|
|
else if ( dwRetCode != NO_ERROR )
|
|
{
|
|
return( dwRetCode );
|
|
}
|
|
|
|
//
|
|
// Send the Ack
|
|
//
|
|
|
|
dwLength = WireToHostFormat16( pReceiveBuf->Length );
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
memcpy( pSendBuf, pReceiveBuf, dwLength );
|
|
pSendBuf->Code = CBCP_CODE_Ack;
|
|
pSendBuf->Id = pReceiveBuf->Id;
|
|
|
|
pWorkBuf->State = CBCP_STATE_DONE;
|
|
pResult->Action = APA_SendAndDone;
|
|
pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
|
|
pResult->CallbackDelay = pWorkBuf->CallbackDelay;
|
|
|
|
strcpy( pResult->szCallbackNumber, pWorkBuf->szCallbackNumber );
|
|
}
|
|
else
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: MakeRequest
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// ERROR_BUFFER_TOO_SMALL - failure
|
|
//
|
|
// Description: Will make a callback request packet based on the user's
|
|
// callback privilege. The Id will be filled in by the caller.
|
|
//
|
|
static DWORD
|
|
MakeRequest(
|
|
IN DWORD fCallbackPrivilege,
|
|
IN OUT PPP_CONFIG * pSendBuf,
|
|
IN DWORD cbSendBuf
|
|
)
|
|
{
|
|
PPP_OPTION * pOption;
|
|
DWORD dwLength = PPP_CONFIG_HDR_LEN;
|
|
|
|
if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption = (PPP_OPTION *)(pSendBuf->Data);
|
|
|
|
pSendBuf->Code = CBCP_CODE_Request;
|
|
|
|
if ( ( fCallbackPrivilege & RASPRIV_NoCallback ) ||
|
|
( fCallbackPrivilege & RASPRIV_CallerSetCallback ) )
|
|
{
|
|
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_NO_CALLBACK;
|
|
pOption->Length = PPP_OPTION_HDR_LEN;
|
|
|
|
dwLength += pOption->Length;
|
|
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
|
|
}
|
|
|
|
if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
|
|
{
|
|
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 2 )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_CALLER_SET;
|
|
pOption->Length = PPP_OPTION_HDR_LEN + 3;
|
|
|
|
*(pOption->Data) = 0; // Callback Delay
|
|
*(pOption->Data+1) = CBCP_PSTN_NUMBER; // Callback Address type
|
|
*(pOption->Data+2) = 0; // Callback Address terminating NULL
|
|
|
|
dwLength += pOption->Length;
|
|
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
|
|
}
|
|
|
|
if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
|
|
{
|
|
if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 1)
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_CALLEE_SET;
|
|
pOption->Length = PPP_OPTION_HDR_LEN + 1;
|
|
|
|
*(pOption->Data) = 0; // Callback Delay
|
|
|
|
dwLength += pOption->Length;
|
|
}
|
|
|
|
HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: GetCallbackPrivilegeFromRequest
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
//
|
|
// Description: Will parse the callback request from the server and translate
|
|
// the PPP callback privilege to what RAS understands.
|
|
//
|
|
DWORD
|
|
GetCallbackPrivilegeFromRequest(
|
|
IN PPP_CONFIG * pRequest,
|
|
IN OUT DWORD * lpdwCallbackPriv
|
|
)
|
|
{
|
|
PPP_OPTION * pOption = (PPP_OPTION *)(pRequest->Data);
|
|
DWORD dwRequestLength = WireToHostFormat16( pRequest->Length )
|
|
- PPP_CONFIG_HDR_LEN;
|
|
|
|
*lpdwCallbackPriv = 0;
|
|
|
|
//
|
|
// Walk the options
|
|
//
|
|
|
|
while( dwRequestLength > 0 )
|
|
{
|
|
if ( dwRequestLength < PPP_OPTION_HDR_LEN )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
switch( pOption->Type )
|
|
{
|
|
case CBCP_TYPE_NO_CALLBACK:
|
|
|
|
*lpdwCallbackPriv |= RASPRIV_NoCallback;
|
|
break;
|
|
|
|
case CBCP_TYPE_CALLEE_SET:
|
|
|
|
*lpdwCallbackPriv |= RASPRIV_AdminSetCallback;
|
|
break;
|
|
|
|
case CBCP_TYPE_CALLER_SET:
|
|
|
|
*lpdwCallbackPriv |= RASPRIV_CallerSetCallback;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Ignore anything else.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
dwRequestLength = dwRequestLength - pOption->Length;
|
|
pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
|
|
}
|
|
|
|
//
|
|
// We accept Callback privleges in the following order.
|
|
// 1) Caller settable.
|
|
// 2) Admin settable
|
|
// 3) No callback
|
|
//
|
|
|
|
if ( *lpdwCallbackPriv & RASPRIV_CallerSetCallback )
|
|
{
|
|
*lpdwCallbackPriv = RASPRIV_CallerSetCallback;
|
|
}
|
|
else if ( *lpdwCallbackPriv & RASPRIV_AdminSetCallback )
|
|
{
|
|
*lpdwCallbackPriv = RASPRIV_AdminSetCallback;
|
|
}
|
|
else if ( *lpdwCallbackPriv & RASPRIV_NoCallback )
|
|
{
|
|
*lpdwCallbackPriv = RASPRIV_NoCallback;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If we could not translate to any RAS callback privlege we simply drop
|
|
// this packet.
|
|
//
|
|
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: MakeResponse
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
//
|
|
// Description:
|
|
//
|
|
DWORD
|
|
MakeResponse(
|
|
IN DWORD fCallbackPrivilege,
|
|
IN LPSTR szCallbackNumber,
|
|
IN DWORD CallbackDelay,
|
|
IN PPP_CONFIG * pRequest,
|
|
IN OUT PPP_CONFIG * pSendBuf,
|
|
IN DWORD cbSendBuf
|
|
)
|
|
{
|
|
PPP_OPTION * pOption;
|
|
DWORD dwLength;
|
|
|
|
if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption = (PPP_OPTION *)(pSendBuf->Data);
|
|
|
|
pSendBuf->Code = CBCP_CODE_Response;
|
|
pSendBuf->Id = pRequest->Id;
|
|
|
|
if ( fCallbackPrivilege & RASPRIV_NoCallback )
|
|
{
|
|
dwLength = PPP_OPTION_HDR_LEN;
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_NO_CALLBACK;
|
|
pOption->Length = (BYTE)dwLength;
|
|
|
|
}
|
|
else if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
|
|
{
|
|
dwLength = (DWORD)(PPP_OPTION_HDR_LEN + 3 + strlen( szCallbackNumber ));
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_CALLER_SET;
|
|
pOption->Length = (BYTE)dwLength;
|
|
|
|
*(pOption->Data) = (BYTE)CallbackDelay; // Callback Delay
|
|
*(pOption->Data+1) = (BYTE)CBCP_PSTN_NUMBER; // Number Type
|
|
strcpy( pOption->Data+2, szCallbackNumber ); // Callback Address
|
|
}
|
|
else if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
|
|
{
|
|
dwLength = PPP_OPTION_HDR_LEN + 1;
|
|
|
|
if ( cbSendBuf < dwLength )
|
|
{
|
|
return( ERROR_BUFFER_TOO_SMALL );
|
|
}
|
|
|
|
pOption->Type = CBCP_TYPE_CALLEE_SET;
|
|
pOption->Length = (BYTE)dwLength;
|
|
|
|
*(pOption->Data)= (BYTE)CallbackDelay; // Callback Delay
|
|
}
|
|
else
|
|
{
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
dwLength += PPP_CONFIG_HDR_LEN;
|
|
|
|
HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
//**
|
|
//
|
|
// Call: ValidateResponse
|
|
//
|
|
// Returns: NO_ERROR - success
|
|
// ERROR_PPP_INVALID_PACKET - failure
|
|
//
|
|
// Description: Will validate the reponse from the client. If the response
|
|
// is valid, then the callback information is returned in the
|
|
// CbCPWorkBuf.
|
|
//
|
|
DWORD
|
|
ValidateResponse(
|
|
IN PPP_CONFIG * pReceiveBuf,
|
|
IN CBCP_WORKBUFFER * pWorkBuf
|
|
)
|
|
{
|
|
PPP_OPTION * pOption = (PPP_OPTION *)(pReceiveBuf->Data);
|
|
|
|
if ( WireToHostFormat16( pReceiveBuf->Length ) !=
|
|
pOption->Length + PPP_CONFIG_HDR_LEN )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
switch( pOption->Type )
|
|
{
|
|
case CBCP_TYPE_NO_CALLBACK:
|
|
|
|
if ( !( ( pWorkBuf->fCallbackPrivilege & RASPRIV_NoCallback ) ||
|
|
( pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback ) ) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
|
|
|
|
break;
|
|
|
|
case CBCP_TYPE_CALLEE_SET:
|
|
|
|
if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_AdminSetCallback) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
pWorkBuf->fCallbackPrivilege = RASPRIV_AdminSetCallback;
|
|
|
|
pWorkBuf->CallbackDelay = *(pOption->Data);
|
|
|
|
break;
|
|
|
|
case CBCP_TYPE_CALLER_SET:
|
|
|
|
if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback) )
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
pWorkBuf->fCallbackPrivilege = RASPRIV_CallerSetCallback;
|
|
|
|
pWorkBuf->CallbackDelay = *(pOption->Data);
|
|
|
|
if ( strlen( pWorkBuf->szCallbackNumber ) <= MAX_CALLBACKNUMBER_SIZE )
|
|
{
|
|
strcpy( pWorkBuf->szCallbackNumber, pOption->Data+2 );
|
|
}
|
|
else
|
|
{
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return( ERROR_PPP_INVALID_PACKET );
|
|
|
|
break;
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|