|
|
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name : RwpFunctions.cxx
Abstract: Implements the behaviors of the "Rogue Worker Process" -- to test Application Manager
Author:
David Wang ( t-dwang ) 14-Jun-1999 Initial
Project:
Duct-Tape
--*/
/*********************************************************
* Include Headers *********************************************************/ #include "precomp.hxx"
#include "RwpFunctions.hxx"
/*********************************************************
* local functions *********************************************************/ BOOL DoGetPidTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); BOOL DoPingReplyTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); BOOL DoSendCountersTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); BOOL DoHResultTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); BOOL DoWorkerRequestShutdownTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); BOOL DoInvalidOpcodeTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe); void RWP_Write_LONG_to_Registry(const WCHAR* szSubKey, LONG lValue);
// These are for the new RWP tests
LONG OpCodeToTest; LONG DataLength; LONG UseDataLength; LONG DataPointerType; LONG NumberOfCalls; LONG AttackDuration;
LONG TestStarted; LONG TestCompleted;
// These are for old RWP tests
LONG RwpBehaviorExhibited;
LONG PingBehavior, PingCount; LONG ShutdownBehavior, ShutdownCount; LONG RotationBehavior, RotationCount; LONG StartupBehavior, StartupCount; LONG HealthBehavior, HealthCount; LONG RecycleBehavior, RecycleCount; LONG AppPoolBehavior;
LONG RWP_EXTRA_DEBUG;
LONG RWP_AppPoolTest(void) { return AppPoolBehavior == RWP_APPPOOL_BOGUS ? TRUE : FALSE; }
LONG RWP_IPM_BadParamTest(LONG OpCode, HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { BOOL bRet = FALSE; DBGPRINTF((DBG_CONTEXT, "In RWP_IPM_BadParamTest()\n"));
if(OpCode != OpCodeToTest) return FALSE;
bRet = TRUE;
// we need to indicate we have actually gotten to the
// code in w3wp that calls our test
if(OpCodeToTest != RWP_IPM_OP_NONE) RWP_Write_LONG_to_Registry(RWP_CONFIG_TEST_STARTED, 1); switch(OpCodeToTest) { case RWP_IPM_OP_NONE: bRet = FALSE; break; case RWP_IPM_OP_GETPID: bRet = DoGetPidTest(phr, pPipe); break; case RWP_IPM_OP_PING_REPLY: bRet = DoPingReplyTest(phr, pPipe); break; case RWP_IPM_OP_SEND_COUNTERS: bRet = DoSendCountersTest(phr, pPipe); break; case RWP_IPM_OP_HRESULT: bRet = DoHResultTest(phr, pPipe); break; case RWP_IPM_OP_WORKER_REQUESTS_SHUTDOWN: bRet = DoWorkerRequestShutdownTest(phr, pPipe); break; case RWP_IPM_OP_INVALID: bRet = DoInvalidOpcodeTest(phr, pPipe); break; default: bRet = FALSE; break; }
if(bRet) RWP_Write_LONG_to_Registry(RWP_CONFIG_TEST_COMPLETION_STATUS, RWP_TEST_STATUS_COMPLETE); else RWP_Write_LONG_to_Registry(RWP_CONFIG_TEST_COMPLETION_STATUS, RWP_TEST_STATUS_ERROR); return bRet; }
BOOL DoGetPidTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { DWORD dwDataLength; DWORD * pData = NULL;
DBGPRINTF((DBG_CONTEXT, "In DoGetPidTest()\n"));
DWORD dwId = GetCurrentProcessId();
dwDataLength = UseDataLength ? DataLength : sizeof(dwId);
switch(DataPointerType) { default: case RWP_DATA_POINTER_TYPE_VALID: pData = &dwId; break; case RWP_DATA_POINTER_TYPE_NULL: pData = NULL; break; case RWP_DATA_POINTER_TYPE_INVALID: pData = (DWORD*) 1; break; } *phr = pPipe->WriteMessage(IPM_OP_GETPID, dwDataLength, pData);
return TRUE; }
BOOL DoPingReplyTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { DWORD dwDataLength; DWORD * pData = NULL;
DWORD dwData = 42; // just some random data
DBGPRINTF((DBG_CONTEXT, "In DoPingReplyTest()\n"));
dwDataLength = UseDataLength ? DataLength : 0;
switch(DataPointerType) { default: case RWP_DATA_POINTER_TYPE_VALID: pData = &dwData; break; case RWP_DATA_POINTER_TYPE_NULL: pData = NULL; break; case RWP_DATA_POINTER_TYPE_INVALID: pData = (DWORD*) 1; break; } *phr = pPipe->WriteMessage( IPM_OP_PING_REPLY, // ping reply opcode
dwDataLength, pData );
return TRUE; }
BOOL DoSendCountersTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { DWORD dwDataLength; DWORD * pData = NULL;
DWORD dwData = 42; // just some random data
DBGPRINTF((DBG_CONTEXT, "In DoSendCountersTest()\n"));
dwDataLength = UseDataLength ? DataLength : sizeof(dwData);
BYTE* pBuffer = NULL;
switch(DataPointerType) { default: case RWP_DATA_POINTER_TYPE_VALID: if((UseDataLength) && (DataLength > 0)) { pBuffer = new BYTE[DataLength]; pData = (DWORD*) pBuffer; } else { pData = &dwData; } break; case RWP_DATA_POINTER_TYPE_NULL: pData = NULL; break; case RWP_DATA_POINTER_TYPE_INVALID: pData = (DWORD*) 1; break; }
for(int i = 0; i < NumberOfCalls; i++) { *phr = pPipe->WriteMessage( IPM_OP_SEND_COUNTERS, // ping reply opcode
dwDataLength, pData ); }
if(pBuffer) delete [] pBuffer;
return TRUE; }
BOOL DoHResultTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { // Test 67034 needs special processing
DWORD dwDataLength; HRESULT * pData = NULL; DWORD dwTickCount; DWORD dwStopTickCount; DWORD dwAttackDurationMsec;
HRESULT hrToSend = S_OK;
DBGPRINTF((DBG_CONTEXT, "In DoHResultTest()\n"));
dwDataLength = UseDataLength ? DataLength : sizeof(hrToSend);
switch(DataPointerType) { default: case RWP_DATA_POINTER_TYPE_VALID: pData = &hrToSend; break; case RWP_DATA_POINTER_TYPE_NULL: pData = NULL; break; case RWP_DATA_POINTER_TYPE_INVALID: pData = (HRESULT*) 1; break; }
if(AttackDuration == 0) { *phr = pPipe->WriteMessage( IPM_OP_HRESULT, // ping reply opcode
dwDataLength, pData ); } else { // we're doing a DoS attack for some amount of time
dwTickCount = GetTickCount(); // convert duration to msec
dwAttackDurationMsec = AttackDuration * 60 * 1000; dwStopTickCount = dwTickCount + dwAttackDurationMsec; while(dwTickCount < dwStopTickCount) { *phr = pPipe->WriteMessage( IPM_OP_HRESULT, // ping reply opcode
dwDataLength, pData ); dwTickCount = GetTickCount(); } }
return TRUE; }
BOOL DoWorkerRequestShutdownTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { DWORD dwDataLength; IPM_WP_SHUTDOWN_MSG * pData = NULL;
IPM_WP_SHUTDOWN_MSG reason = IPM_WP_RESTART_COUNT_REACHED;
DBGPRINTF((DBG_CONTEXT, "In DoWorkerRequestShutdownTest()\n"));
dwDataLength = UseDataLength ? DataLength : sizeof(reason);
switch(DataPointerType) { default: case RWP_DATA_POINTER_TYPE_VALID: pData = &reason; break; case RWP_DATA_POINTER_TYPE_NULL: pData = NULL; break; case RWP_DATA_POINTER_TYPE_INVALID: pData = (IPM_WP_SHUTDOWN_MSG *) 1; break; case RWP_DATA_POINTER_TYPE_INVALID_REASON: reason = (IPM_WP_SHUTDOWN_MSG) ((IPM_WP_SHUTDOWN_MSG)2*IPM_WP_MAXIMUM); pData = &reason; break; } *phr = pPipe->WriteMessage( IPM_OP_WORKER_REQUESTS_SHUTDOWN, // ping reply opcode
dwDataLength, pData );
return TRUE; }
BOOL DoInvalidOpcodeTest(HRESULT* phr, IPM_MESSAGE_PIPE* pPipe) { // Just use params for a shutdown reply
DWORD dwDataLength; IPM_WP_SHUTDOWN_MSG * pData = NULL;
DBGPRINTF((DBG_CONTEXT, "In DoInvalidOpcodeTest()\n")); IPM_WP_SHUTDOWN_MSG reason = IPM_WP_RESTART_COUNT_REACHED; pData = &reason; dwDataLength = sizeof(reason);
*phr = pPipe->WriteMessage( (IPM_OPCODE) 50, dwDataLength, pData );
return TRUE; }
LONG RWP_Ping_Behavior(HRESULT* hr, IPM_MESSAGE_PIPE* pPipe) { *hr = S_OK; int i = 0; switch (PingBehavior) { //
//Don't respond to pings
//
case RWP_PING_NO_ANSWER: DBGPRINTF((DBG_CONTEXT, "Rogue: Not responding to Ping\n")); break; //
//Responding with n pings
//
case RWP_PING_MULTI_ANSWER: DBGPRINTF((DBG_CONTEXT, "Rogue: Responding to Ping %d times", PingCount)); for (i = 0; i < PingCount; i++) { *hr = pPipe->WriteMessage( IPM_OP_PING_REPLY, // ping reply opcode
0, // no data to send
NULL // pointer to no data
); } break; //
//Respond after n seconds
//
case RWP_PING_DELAY_ANSWER: DBGPRINTF((DBG_CONTEXT, "Rogue: Delay responding to Ping for %d seconds", PingCount)); RWP_Sleep_For(PingCount); //return 0 so that we'll keep going (this is a delay, not fail)
return (RWP_NO_MISBEHAVE); break; default: DBGPRINTF((DBG_CONTEXT, "Rogue: Unknown Ping Behavior = %d\n", PingBehavior)); break; } return (PingBehavior); } // RWP_Ping_Behavior
LONG RWP_Shutdown_Behavior(HRESULT* hr) { *hr = S_OK; switch (ShutdownBehavior) { case RWP_SHUTDOWN_NOT_OBEY: //
//Not shutting down, period
//
DBGPRINTF((DBG_CONTEXT, "Rogue: Not shutting down\n")); break; case RWP_SHUTDOWN_DELAY: //
//Sleeping for n seconds before continuing on
//
DBGPRINTF((DBG_CONTEXT, "Rogue: Sleeping for %d seconds before shutdown\n", ShutdownCount)); RWP_Sleep_For(ShutdownCount); //return 0 so that we'll keep going (this is a delay, not fail)
return (RWP_NO_MISBEHAVE); break; default: DBGPRINTF((DBG_CONTEXT, "Rogue: Unknown Shutdown Behavior\n")); break; } return (ShutdownBehavior); } // RWP_Shutdown_Behavior
LONG RWP_Rotation_Behavior(HRESULT* pHr, IPM_MESSAGE_PIPE* pPipe) { *pHr = S_OK; IPM_WP_SHUTDOWN_MSG reason; switch (RotationBehavior) { case RWP_ROTATION_INVALID_REASON: DBGPRINTF((DBG_CONTEXT, "Rogue: Sending Invalid shut-down reason\n")); reason = IPM_WP_MINIMUM; *pHr = pPipe->WriteMessage( IPM_OP_WORKER_REQUESTS_SHUTDOWN, // sends shut-down message
sizeof(reason), // data to send
(BYTE *)&reason // pointer to data
); break; default: DBGPRINTF((DBG_CONTEXT, "Rogue: Unknown Rotation Behavior\n")); break; } return (RotationBehavior); }
LONG RWP_Startup_Behavior(HRESULT* rc) { //
//modify rc accordingly
//
*rc = NO_ERROR; switch (StartupBehavior) { case RWP_STARTUP_NOT_OBEY: //
//Don't register with WAS
//
DBGPRINTF((DBG_CONTEXT, "Rogue: Not registering with WAS\n")); break; case RWP_STARTUP_DELAY: //
//Delay starting up the thread message loop
//
DBGPRINTF((DBG_CONTEXT, "Rogue: Delay starting up for %d\n", StartupCount)); RWP_Sleep_For(StartupCount); //return 0 so that we'll keep going (this is a delay, not fail)
return (RWP_NO_MISBEHAVE); case RWP_STARTUP_NOT_REGISTER_FAIL: //
//Quit before registering with UL
//
DBGPRINTF((DBG_CONTEXT, "Rogue: Not starting up (unregistered)... shutting down\n")); // BUGBUG - what is this?
//wpContext->IndicateShutdown(SHUTDOWN_REASON_ADMIN);
//return 0 so that it enters (and subsequently exits) the thread loop
return (RWP_NO_MISBEHAVE); //
//It looks like the place to modify is in wpcontext.cxx,
//when it tries to initialize IPM if requested
//
default: break; } return (StartupBehavior); }
LONG RWP_Health_Behavior() { return 0; }
/*
LONG RWP_Recycle_Behavior() { } */
void RWP_Sleep_For(LONG lTime) { SleepEx( (DWORD)lTime * 1000, //sleep for lTimeToSleep * 1000 milliseconds (4 second increments)
FALSE); // not alertable
DBGPRINTF((DBG_CONTEXT, "Done sleeping \n")); }
void RWP_Display_Behavior() { DBGPRINTF((DBG_CONTEXT, "Rogue Behavior Status\n"));
switch(PingBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_PING_MISBEHAVE_MSG)); break; case RWP_PING_NO_ANSWER: DBGPRINTF((DBG_CONTEXT, RWP_PING_NO_ANSWER_MSG)); break; case RWP_PING_MULTI_ANSWER: DBGPRINTF((DBG_CONTEXT, "%s %d\n", RWP_PING_MULTI_ANSWER_MSG, PingCount)); break; case RWP_PING_DELAY_ANSWER: DBGPRINTF((DBG_CONTEXT, "%s %d\n", RWP_PING_DELAY_ANSWER_MSG, PingCount)); break; default: DBGPRINTF((DBG_CONTEXT, "Ping behavior set to unknown value")); break; }
switch(StartupBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_STARTUP_MISBEHAVE_MSG)); break; case RWP_STARTUP_NOT_OBEY: DBGPRINTF((DBG_CONTEXT, RWP_STARTUP_NOT_OBEY_MSG)); break; case RWP_STARTUP_DELAY: DBGPRINTF((DBG_CONTEXT, "%s %d\n", RWP_STARTUP_DELAY_MSG, StartupCount)); break; case RWP_STARTUP_NOT_REGISTER_FAIL: DBGPRINTF((DBG_CONTEXT, RWP_STARTUP_NOT_REGISTER_FAIL_MSG)); break; default: DBGPRINTF((DBG_CONTEXT, "Startup behavior set to unknown value")); break; } switch(ShutdownBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_SHUTDOWN_MISBEHAVE_MSG)); break; case RWP_SHUTDOWN_NOT_OBEY: DBGPRINTF((DBG_CONTEXT, RWP_SHUTDOWN_NOT_OBEY_MSG)); break; case RWP_SHUTDOWN_DELAY: DBGPRINTF((DBG_CONTEXT, RWP_SHUTDOWN_DELAY_MSG, ShutdownCount)); break; default: DBGPRINTF((DBG_CONTEXT, "Shutdown behavior set to unknown value")); break; } switch(RotationBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_ROTATION_MISBEHAVE_MSG)); break; case RWP_ROTATION_INVALID_REASON: DBGPRINTF((DBG_CONTEXT, RWP_ROTATION_INVALID_REASON_MSG)); break; default: DBGPRINTF((DBG_CONTEXT, "Rotation behavior set to unknown value")); break; } switch(RecycleBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_RECYCLE_MISBEHAVE_MSG)); break; case RWP_RECYCLE_NOT_OBEY: DBGPRINTF((DBG_CONTEXT, RWP_RECYCLE_NOT_OBEY_MSG)); break; case RWP_RECYCLE_DELAY: DBGPRINTF((DBG_CONTEXT, "%s %d\n", RWP_RECYCLE_DELAY_MSG, RecycleCount)); break; default: DBGPRINTF((DBG_CONTEXT, "Shutdown behavior set to unknown value")); break; }
switch(HealthBehavior) { case RWP_NO_MISBEHAVE: DBGPRINTF((DBG_CONTEXT, RWP_NO_HEALTH_MISBEHAVE_MSG)); break; case RWP_HEALTH_OK: DBGPRINTF((DBG_CONTEXT, RWP_HEALTH_OK_MSG)); break; case RWP_HEALTH_NOT_OK: DBGPRINTF((DBG_CONTEXT, RWP_HEALTH_NOT_OK_MSG)); break; case RWP_HEALTH_TERMINALLY_ILL: DBGPRINTF((DBG_CONTEXT, RWP_HEALTH_TERMINALLY_ILL_MSG)); break; default: break; }
}
void RWP_Read_LONG_from_Registry(HKEY hkey, const WCHAR* szSubKey, LONG* lValue) { LONG lResult; DWORD dwType; DWORD len = sizeof(lValue); HKEY myKey; lResult = RegQueryValueEx( hkey, szSubKey, 0, &dwType, (LPBYTE)lValue, &len); if (lResult != ERROR_SUCCESS) { //sets default = 0 (no misbehave)
*lValue = RWP_NO_MISBEHAVE; /*
//key does not exist -- try to create it
lResult = RegCreateKeyEx( hkey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &myKey, &dwType); */ } }
void RWP_Write_LONG_to_Registry(const WCHAR* szSubKey, LONG lValue) { LONG lResult; HKEY hkMyKey; lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, //root key
RWP_CONFIG_LOCATION, //sub key
0, //reserved - must be 0
KEY_ALL_ACCESS, //SAM
&hkMyKey); //my pointer to HKEY
if (lResult != ERROR_SUCCESS) { DBGPRINTF((DBG_CONTEXT, "Unable to open configuration key. RegOpenKeyEx returned %d\n", lResult)); return; }
lResult = RegSetValueEx( hkMyKey, szSubKey, 0, REG_DWORD, (LPBYTE)&lValue, sizeof(lValue));
RegCloseKey(hkMyKey);
ASSERT(lResult == ERROR_SUCCESS); return; }
BOOL RWP_Read_Config(const WCHAR* szRegKey) { BOOL bSuccess = FALSE; HKEY hkMyKey; LONG lResult; DWORD dwDisp; DWORD dwLastError = 0;
//
// Initialize to default values
//
// New behavior
OpCodeToTest = RWP_IPM_OP_NONE; DataLength = 0; // 0 means set it to the actual data length
UseDataLength = FALSE; // by default we'll use the valid data length
DataPointerType = RWP_DATA_POINTER_TYPE_VALID; NumberOfCalls = 1; AttackDuration = 0;
PingBehavior = RWP_NO_MISBEHAVE; ShutdownBehavior = RWP_NO_MISBEHAVE; StartupBehavior = RWP_NO_MISBEHAVE; HealthBehavior = RWP_NO_MISBEHAVE; RecycleBehavior = RWP_NO_MISBEHAVE; AppPoolBehavior = RWP_NO_MISBEHAVE; RWP_EXTRA_DEBUG = RWP_DEBUG_OFF;
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, //root key
szRegKey, //sub key
0, //reserved - must be 0
KEY_ALL_ACCESS, //SAM
&hkMyKey); //my pointer to HKEY
if (lResult != ERROR_SUCCESS) { DBGPRINTF((DBG_CONTEXT, "Unable to open configuration key. RegOpenKeyEx returned %d\n", lResult)); } else { //my key exists. Read in config info and validate
DBGPRINTF((DBG_CONTEXT, "Key exists\n"));
RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_OPCODE_TO_TEST, &OpCodeToTest); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_IPM_DATA_LENGTH, &DataLength); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_IPM_USE_DATA_LENGTH, &UseDataLength); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_IPM_POINTER_TYPE, &DataPointerType); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_NUMBER_OF_CALLS, &NumberOfCalls); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_ATTACK_DURATION, &AttackDuration); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_PING_BEHAVIOR, &PingBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_SHUTDOWN_BEHAVIOR, &ShutdownBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_ROTATION_BEHAVIOR, &RotationBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_STARTUP_BEHAVIOR, &StartupBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_HEALTH_BEHAVIOR, &HealthBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_RECYCLE_BEHAVIOR, &RecycleBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_APP_POOL_BEHAVIOR, &AppPoolBehavior); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_PING_COUNT, &PingCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_SHUTDOWN_COUNT, &ShutdownCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_ROTATION_COUNT, &RotationCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_STARTUP_COUNT, &StartupCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_HEALTH_COUNT, &HealthCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_RECYCLE_COUNT, &RecycleCount); RWP_Read_LONG_from_Registry(hkMyKey, RWP_CONFIG_EXTRA_DEBUG, &RWP_EXTRA_DEBUG); } bSuccess = TRUE; RegCloseKey(hkMyKey); //
//Declare our intentions
//
RWP_Display_Behavior(); DBGPRINTF((DBG_CONTEXT, "Finished Configurations\n")); //TODO: Display PID and command line info...
return (bSuccess); }
/*
Methods modified: iiswp.cxx wpipm.cxx (3 places - handleping, handleshutdown, pipedisconnected) */
|