305 lines
6.9 KiB
C
305 lines
6.9 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rogue.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the rogue detection interface to DHCP for BINL server.
|
|
|
|
Author:
|
|
|
|
Andy Herron (andyhe) 19-Aug-1998
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "binl.h"
|
|
#pragma hdrstop
|
|
|
|
VOID
|
|
BinlRogueLoop(
|
|
LPVOID Parameter
|
|
);
|
|
|
|
NTSTATUS
|
|
MaybeStartRogueThread (
|
|
VOID
|
|
)
|
|
//
|
|
// Initiate rogue thread. The gcsDHCPBINL should not be held by caller.
|
|
//
|
|
{
|
|
DWORD Error = ERROR_SUCCESS;
|
|
DWORD threadId;
|
|
|
|
EnterCriticalSection(&gcsDHCPBINL);
|
|
|
|
//
|
|
// if we're stopping anyway or if we're already running the rogue stuff
|
|
// or if the DHCP server is up, then we don't bother starting rogue
|
|
// detection.
|
|
//
|
|
|
|
if ((BinlCurrentState == BINL_STOPPED) ||
|
|
(BinlGlobalHaveCalledRogueInit) ||
|
|
(DHCPState != DHCP_STOPPED)) {
|
|
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Let's do rogue detection.. first create the events we need
|
|
//
|
|
|
|
if (BinlRogueTerminateEventHandle == NULL) {
|
|
|
|
BinlRogueTerminateEventHandle = CreateEvent( NULL, FALSE, FALSE, NULL );
|
|
}
|
|
if (RogueUnauthorizedHandle == NULL) {
|
|
|
|
RogueUnauthorizedHandle = CreateEvent( NULL, TRUE, FALSE, NULL );
|
|
}
|
|
if ( BinlRogueTerminateEventHandle == NULL || RogueUnauthorizedHandle == NULL) {
|
|
|
|
Error = GetLastError();
|
|
|
|
BinlPrintDbg( (DEBUG_ROGUE,
|
|
"Initialize(...) CreateEvent returned error %x for rogue\n",
|
|
Error )
|
|
);
|
|
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
return Error;
|
|
}
|
|
|
|
Error = DhcpRogueInit( &DhcpRogueInfo,
|
|
BinlRogueTerminateEventHandle,
|
|
RogueUnauthorizedHandle );
|
|
|
|
if (Error != ERROR_SUCCESS) {
|
|
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
return Error;
|
|
}
|
|
|
|
//
|
|
// create the thread that handles the rogue detection logic in DHCP code.
|
|
//
|
|
|
|
BinlRogueThread = CreateThread( NULL,
|
|
0,
|
|
(LPTHREAD_START_ROUTINE)BinlRogueLoop,
|
|
NULL,
|
|
0,
|
|
&threadId );
|
|
|
|
if ( BinlRogueThread == NULL ) {
|
|
Error = GetLastError();
|
|
BinlPrint((DEBUG_ROGUE, "Can't create rogue Thread, %ld.\n", Error));
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
return Error;
|
|
}
|
|
|
|
BinlGlobalHaveCalledRogueInit = TRUE;
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
StopRogueThread (
|
|
VOID
|
|
)
|
|
//
|
|
// Cleanup all rogue thread resources.
|
|
// The gcsDHCPBINL should not be held by caller.
|
|
//
|
|
{
|
|
HANDLE tempThreadHandle;
|
|
|
|
tempThreadHandle = InterlockedExchangePointer( &BinlRogueThread, NULL );
|
|
|
|
if ( tempThreadHandle != NULL ) {
|
|
|
|
BinlAssert( BinlRogueTerminateEventHandle != NULL );
|
|
SetEvent( BinlRogueTerminateEventHandle );
|
|
|
|
WaitForSingleObject(
|
|
tempThreadHandle,
|
|
THREAD_TERMINATION_TIMEOUT );
|
|
CloseHandle( tempThreadHandle );
|
|
}
|
|
|
|
EnterCriticalSection(&gcsDHCPBINL);
|
|
|
|
if (BinlGlobalHaveCalledRogueInit) {
|
|
|
|
DhcpRogueCleanup( &DhcpRogueInfo );
|
|
BinlGlobalHaveCalledRogueInit = FALSE;
|
|
}
|
|
|
|
if ( BinlRogueTerminateEventHandle ) {
|
|
|
|
CloseHandle( BinlRogueTerminateEventHandle );
|
|
BinlRogueTerminateEventHandle = NULL;
|
|
}
|
|
if ( RogueUnauthorizedHandle ) {
|
|
|
|
CloseHandle( RogueUnauthorizedHandle );
|
|
RogueUnauthorizedHandle = NULL;
|
|
}
|
|
|
|
LeaveCriticalSection(&gcsDHCPBINL);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HandleRogueAuthorized (
|
|
VOID
|
|
)
|
|
{
|
|
BOOL oldState = BinlGlobalAuthorized;
|
|
|
|
BinlGlobalAuthorized = TRUE;
|
|
|
|
if ((BinlGlobalAuthorized != oldState) &&
|
|
(BinlCurrentState != BINL_STOPPED)) {
|
|
|
|
LogCurrentRogueState( FALSE );
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
HandleRogueUnauthorized (
|
|
VOID
|
|
)
|
|
{
|
|
BOOL oldState = BinlGlobalAuthorized;
|
|
|
|
BinlGlobalAuthorized = FALSE;
|
|
|
|
if ((BinlGlobalAuthorized != oldState) &&
|
|
(BinlCurrentState != BINL_STOPPED)) {
|
|
|
|
LogCurrentRogueState( FALSE );
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
LogCurrentRogueState (
|
|
BOOL ResponseToMessage
|
|
)
|
|
{
|
|
//
|
|
// If we're responding to a message and we haven't yet logged that
|
|
// we're unauthorized
|
|
|
|
if ((ResponseToMessage == FALSE) ||
|
|
((BinlGlobalAuthorized == FALSE) &&
|
|
(BinlRogueLoggedState == FALSE)) ) {
|
|
|
|
BinlRogueLoggedState = TRUE;
|
|
|
|
BinlReportEventW( BinlGlobalAuthorized ?
|
|
EVENT_ERROR_DHCP_AUTHORIZED :
|
|
EVENT_ERROR_DHCP_NOT_AUTHORIZED,
|
|
EVENTLOG_INFORMATION_TYPE,
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
BinlRogueLoop(
|
|
LPVOID Parameter
|
|
)
|
|
{
|
|
HANDLE Handles[3];
|
|
ULONG SecondsToSleep, SleepTime, Error;
|
|
ULONG Flag;
|
|
|
|
BinlPrintDbg((DEBUG_ROGUE, "BinlRogue thread has been started.\n" ));
|
|
|
|
Handles[0] = BinlRogueTerminateEventHandle;
|
|
Handles[1] = RogueUnauthorizedHandle;
|
|
Handles[2] = BinlGlobalProcessTerminationEvent;
|
|
|
|
do {
|
|
SecondsToSleep = RogueDetectStateMachine(&DhcpRogueInfo);
|
|
|
|
if( INFINITE == SecondsToSleep ) {
|
|
SleepTime = INFINITE;
|
|
} else {
|
|
SleepTime = SecondsToSleep * 1000;
|
|
}
|
|
|
|
BinlPrintDbg( (DEBUG_ROGUE, "BinlRogue waiting %u milliseconds.\n", SleepTime ));
|
|
|
|
Error = WaitForMultipleObjects(3, Handles, FALSE, SleepTime );
|
|
|
|
//
|
|
// if we got anything but WAIT_TIMEOUT or RogueUnauthorized, we
|
|
// break out. This is per RameshV's sample code.
|
|
//
|
|
|
|
if (Error == WAIT_OBJECT_0+2) {
|
|
|
|
//
|
|
// binl is terminating.
|
|
//
|
|
|
|
BinlPrintDbg((DEBUG_ROGUE, "BinlRogue thread is exiting because BINL shutting down.\n" ));
|
|
return;
|
|
}
|
|
|
|
if (BinlRogueThread == NULL) {
|
|
|
|
//
|
|
// we've been terminated because DHCP has started and is doing
|
|
// it's own rogue detection.
|
|
//
|
|
|
|
BinlPrintDbg((DEBUG_ROGUE, "BinlRogue thread is exiting because rogue thread is null.\n" ));
|
|
return;
|
|
}
|
|
|
|
|
|
// if we ever have to do anything besides just continue when the
|
|
// state machine tells us to exit, do so here.
|
|
|
|
#if 0
|
|
if ((Error == WAIT_OBJECT_0+1) || (Error == WAIT_TIMEOUT)) {
|
|
continue;
|
|
}
|
|
#endif
|
|
//
|
|
// supposedly the state machine resets so we should just continue.
|
|
//
|
|
|
|
BinlPrintDbg((DEBUG_ROGUE, "BinlRogue has error of 0x%x. sleeping a bit\n", Error ));
|
|
Sleep( 1000 ); // we'll sleep to give the dhcp rogue state
|
|
// machine time to reset
|
|
|
|
} while ( TRUE );
|
|
}
|
|
|
|
// rogue.c eof
|
|
|