mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 05:45:59 +03:00
652 lines
16 KiB
C++
652 lines
16 KiB
C++
/*
|
||
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
||
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
||
*
|
||
* You may not use this file except in compliance with
|
||
* the License. You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* If any of the files related to licensing are missing or if you have any
|
||
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
||
* directly using the email address security@modsecurity.org.
|
||
*/
|
||
|
||
#define WIN32_LEAN_AND_MEAN
|
||
|
||
#undef inline
|
||
#define inline inline
|
||
|
||
// IIS7 Server API header file
|
||
#include "httpserv.h"
|
||
|
||
// Project header files
|
||
#include "mymodule.h"
|
||
#include "mymodulefactory.h"
|
||
#include "moduleconfig.h"
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::Initialize(
|
||
IHttpContext * pW3Context,
|
||
IAppHostConfigException ** ppException
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
IAppHostAdminManager *pAdminManager = NULL;
|
||
IAppHostElement *pSessionTrackingElement = NULL;
|
||
IAppHostPropertyException *pPropertyException = NULL;
|
||
|
||
PCWSTR pszConfigPath = pW3Context->GetMetadata()->GetMetaPath();
|
||
BSTR bstrUrlPath = SysAllocString( pszConfigPath );
|
||
|
||
pAdminManager = g_pHttpServer->GetAdminManager();
|
||
|
||
if ( ( FAILED( hr ) ) || ( pAdminManager == NULL ) )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get a handle to the section:
|
||
hr = pAdminManager->GetAdminSection(
|
||
MODSECURITY_SECTION,
|
||
bstrUrlPath,
|
||
&pSessionTrackingElement );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
if ( pSessionTrackingElement == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the property object for the 'enabled' attribute:
|
||
hr = GetBooleanPropertyValue(
|
||
pSessionTrackingElement,
|
||
MODSECURITY_SECTION_ENABLED,
|
||
&pPropertyException,
|
||
&m_bIsEnabled);
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// If there is a config failure, we cannot continue execution:
|
||
if ( pPropertyException != NULL )
|
||
{
|
||
|
||
ppException = ( IAppHostConfigException** ) &pPropertyException;
|
||
goto Failure;
|
||
}
|
||
|
||
if ( m_bIsEnabled == FALSE )
|
||
{
|
||
// There is no point in reading any more of the config associated with the session
|
||
// tracking section, since this feature is not enabled for the current URL
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the property object for the 'configfile' attribute:
|
||
hr = GetStringPropertyValue(
|
||
pSessionTrackingElement,
|
||
MODSECURITY_SECTION_CONFIGFILE,
|
||
&pPropertyException,
|
||
&m_pszPath);
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// If there is a config failure, we cannot continue execution:
|
||
if ( pPropertyException != NULL )
|
||
{
|
||
|
||
ppException = ( IAppHostConfigException** ) &pPropertyException;
|
||
goto Failure;
|
||
}
|
||
|
||
Failure:
|
||
SysFreeString( bstrUrlPath );
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::GetBooleanPropertyValue(
|
||
IAppHostElement* pElement,
|
||
WCHAR* pszPropertyName,
|
||
IAppHostPropertyException** pException,
|
||
BOOL* pBoolValue )
|
||
{
|
||
HRESULT hr = S_OK;
|
||
IAppHostProperty *pProperty = NULL;
|
||
VARIANT vPropertyValue;
|
||
|
||
if (
|
||
( pElement == NULL ) ||
|
||
( pszPropertyName == NULL ) ||
|
||
( pException == NULL ) ||
|
||
( pBoolValue == NULL )
|
||
)
|
||
{
|
||
hr = E_INVALIDARG;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the property object for the BOOLEAN attribute:
|
||
hr = pElement->GetPropertyByName(
|
||
pszPropertyName,
|
||
&pProperty );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
if ( pProperty == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the attribute value:
|
||
VariantInit( &vPropertyValue );
|
||
|
||
hr = pProperty->get_Value( &vPropertyValue );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// See it there is an exception that might be due to the actual value in the
|
||
// config not meeting validation criteria
|
||
*pException = NULL;
|
||
|
||
hr = pProperty->get_Exception( pException );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// No need to continue if we got an exception...
|
||
if ( ( *pException ) != NULL )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// Finally, get the value:
|
||
*pBoolValue = ( vPropertyValue.boolVal == VARIANT_TRUE ) ? TRUE : FALSE;
|
||
|
||
|
||
Failure:
|
||
VariantClear( &vPropertyValue );
|
||
|
||
if ( pProperty != NULL )
|
||
{
|
||
pProperty->Release();
|
||
pProperty = NULL;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::GetDWORDPropertyValue(
|
||
IAppHostElement* pElement,
|
||
WCHAR* pszPropertyName,
|
||
IAppHostPropertyException** pException,
|
||
DWORD* pnValue )
|
||
{
|
||
HRESULT hr = S_OK;
|
||
IAppHostProperty *pProperty = NULL;
|
||
VARIANT vPropertyValue;
|
||
|
||
if (
|
||
( pElement == NULL ) ||
|
||
( pszPropertyName == NULL ) ||
|
||
( pException == NULL ) ||
|
||
( pnValue == NULL )
|
||
)
|
||
{
|
||
hr = E_INVALIDARG;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the property object for the INT attribute:
|
||
hr = pElement->GetPropertyByName(
|
||
pszPropertyName,
|
||
&pProperty );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
if ( pProperty == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the attribute value:
|
||
VariantInit( &vPropertyValue );
|
||
|
||
hr = pProperty->get_Value( &vPropertyValue );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// See it there is an exception that might be due to the actual value in the
|
||
// config not meeting validation criteria
|
||
*pException = NULL;
|
||
|
||
hr = pProperty->get_Exception( pException );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// No need to continue if we got an exception...
|
||
if ( ( *pException ) != NULL )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// Finally, get the value:
|
||
*pnValue = vPropertyValue.ulVal;
|
||
|
||
Failure:
|
||
VariantClear( &vPropertyValue );
|
||
|
||
if ( pProperty != NULL )
|
||
{
|
||
pProperty->Release();
|
||
pProperty = NULL;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::GetTimeSpanPropertyValue(
|
||
IAppHostElement* pElement,
|
||
WCHAR* pszPropertyName,
|
||
IAppHostPropertyException** pException,
|
||
ULONGLONG* pnValue )
|
||
{
|
||
HRESULT hr = S_OK;
|
||
IAppHostProperty *pProperty = NULL;
|
||
VARIANT vPropertyValue;
|
||
|
||
if (
|
||
( pElement == NULL ) ||
|
||
( pszPropertyName == NULL ) ||
|
||
( pException == NULL ) ||
|
||
( pnValue == NULL )
|
||
)
|
||
{
|
||
hr = E_INVALIDARG;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the property object for the INT attribute:
|
||
hr = pElement->GetPropertyByName(
|
||
pszPropertyName,
|
||
&pProperty );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
if ( pProperty == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the attribute value:
|
||
VariantInit( &vPropertyValue );
|
||
|
||
hr = pProperty->get_Value( &vPropertyValue );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// See it there is an exception that might be due to the actual value in the
|
||
// config not meeting validation criteria
|
||
*pException = NULL;
|
||
|
||
hr = pProperty->get_Exception( pException );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// No need to continue if we got an exception...
|
||
if ( ( *pException ) != NULL )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// Finally, get the value:
|
||
*pnValue = vPropertyValue.ullVal;
|
||
|
||
Failure:
|
||
VariantClear( &vPropertyValue );
|
||
|
||
if ( pProperty != NULL )
|
||
{
|
||
pProperty->Release();
|
||
pProperty = NULL;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::GetStringPropertyValue(
|
||
IAppHostElement* pElement,
|
||
WCHAR* pszPropertyName,
|
||
IAppHostPropertyException** pException,
|
||
WCHAR** ppszValue )
|
||
{
|
||
HRESULT hr = S_OK;
|
||
IAppHostProperty *pProperty = NULL;
|
||
DWORD dwLength;
|
||
VARIANT vPropertyValue;
|
||
|
||
if (
|
||
( pElement == NULL ) ||
|
||
( pszPropertyName == NULL ) ||
|
||
( pException == NULL ) ||
|
||
( ppszValue == NULL )
|
||
)
|
||
{
|
||
hr = E_INVALIDARG;
|
||
goto Failure;
|
||
}
|
||
|
||
*ppszValue = NULL;
|
||
|
||
// Get the property object for the string attribute:
|
||
hr = pElement->GetPropertyByName(
|
||
pszPropertyName,
|
||
&pProperty );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
if ( pProperty == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
goto Failure;
|
||
}
|
||
|
||
// Get the attribute value:
|
||
VariantInit( &vPropertyValue );
|
||
|
||
hr = pProperty->get_Value( &vPropertyValue );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// See it there is an exception that might be due to the actual value in the
|
||
// config not meeting validation criteria
|
||
*pException = NULL;
|
||
|
||
hr = pProperty->get_Exception( pException );
|
||
|
||
if ( FAILED( hr ) )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// No need to continue if we got an exception...
|
||
if ( ( *pException ) != NULL )
|
||
{
|
||
goto Failure;
|
||
}
|
||
|
||
// Finally, get the value:
|
||
dwLength = SysStringLen( vPropertyValue.bstrVal );
|
||
*ppszValue = new WCHAR[ dwLength + 1 ];
|
||
|
||
if ( (*ppszValue) == NULL )
|
||
{
|
||
hr = E_OUTOFMEMORY;
|
||
goto Failure;
|
||
}
|
||
|
||
wcsncpy(
|
||
*ppszValue,
|
||
vPropertyValue.bstrVal,
|
||
dwLength );
|
||
|
||
(*ppszValue)[ dwLength ] = L'\0';
|
||
|
||
Failure:
|
||
VariantClear( &vPropertyValue );
|
||
|
||
if ( pProperty != NULL )
|
||
{
|
||
pProperty->Release();
|
||
pProperty = NULL;
|
||
}
|
||
|
||
return hr;
|
||
}
|
||
|
||
MODSECURITY_STORED_CONTEXT::~MODSECURITY_STORED_CONTEXT()
|
||
{
|
||
if ( m_pszPath != NULL )
|
||
{
|
||
delete [] m_pszPath;
|
||
m_pszPath = NULL;
|
||
}
|
||
}
|
||
|
||
MODSECURITY_STORED_CONTEXT::MODSECURITY_STORED_CONTEXT():
|
||
m_bIsEnabled ( FALSE ),
|
||
m_pszPath( NULL ),
|
||
m_Config( NULL )
|
||
{
|
||
}
|
||
|
||
DWORD
|
||
MODSECURITY_STORED_CONTEXT::GlobalWideCharToMultiByte(
|
||
WCHAR* pSource,
|
||
DWORD dwLengthSource,
|
||
CHAR** ppszDestination,
|
||
USHORT* pdwLengthDestination )
|
||
{
|
||
DWORD dwResult = NULL;
|
||
DWORD dwCount = 0;
|
||
|
||
if (
|
||
( pSource == NULL ) ||
|
||
( ppszDestination == NULL ) ||
|
||
( pdwLengthDestination == NULL )
|
||
)
|
||
{
|
||
dwResult = ERROR_INVALID_PARAMETER;
|
||
goto Exit;
|
||
}
|
||
|
||
// Initialize result length
|
||
*pdwLengthDestination = 0;
|
||
*ppszDestination = NULL;
|
||
|
||
dwCount = WideCharToMultiByte(
|
||
CP_ACP,
|
||
0,
|
||
pSource,
|
||
dwLengthSource + 1,
|
||
*ppszDestination,
|
||
0,
|
||
NULL,
|
||
NULL );
|
||
|
||
if ( 0 == dwCount )
|
||
{
|
||
dwResult = GetLastError ();
|
||
|
||
if ( dwResult == 0 )
|
||
{
|
||
dwResult = ERROR_INVALID_DATA;
|
||
}
|
||
|
||
goto Exit;
|
||
}
|
||
|
||
*ppszDestination = new CHAR[ dwCount + 1 ];
|
||
|
||
if ( NULL == ( *ppszDestination ) )
|
||
{
|
||
dwResult = ERROR_OUTOFMEMORY;
|
||
goto Exit;
|
||
}
|
||
|
||
// Make sure the memory is 'clean':
|
||
SecureZeroMemory(
|
||
( *ppszDestination ),
|
||
( dwCount + 1 ) * sizeof ( CHAR ) );
|
||
|
||
if (
|
||
0 == WideCharToMultiByte(
|
||
CP_ACP,
|
||
0,
|
||
pSource,
|
||
dwLengthSource + 1,
|
||
*ppszDestination,
|
||
dwCount,
|
||
NULL,
|
||
NULL )
|
||
)
|
||
{
|
||
dwResult = GetLastError();
|
||
|
||
goto Exit;
|
||
}
|
||
|
||
*pdwLengthDestination = ( USHORT )dwCount;
|
||
|
||
Exit:
|
||
if ( dwResult != 0 )
|
||
{
|
||
// Make sure we do the proper cleanup in the error case:
|
||
if ( pdwLengthDestination != NULL )
|
||
{
|
||
*pdwLengthDestination = 0;
|
||
}
|
||
|
||
if ( ppszDestination != NULL )
|
||
{
|
||
if ( ( *ppszDestination ) != NULL )
|
||
{
|
||
delete [] ( *ppszDestination );
|
||
( *ppszDestination ) = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
return dwResult;
|
||
}
|
||
|
||
HRESULT
|
||
MODSECURITY_STORED_CONTEXT::GetConfig(
|
||
IHttpContext * pContext,
|
||
MODSECURITY_STORED_CONTEXT ** ppModuleConfig
|
||
)
|
||
{
|
||
HRESULT hr = S_OK;
|
||
MODSECURITY_STORED_CONTEXT * pModuleConfig = NULL;
|
||
IHttpModuleContextContainer * pMetadataContainer = NULL;
|
||
IAppHostConfigException * pException = NULL;
|
||
|
||
pMetadataContainer = pContext->GetMetadata()->GetModuleContextContainer();
|
||
|
||
if ( pMetadataContainer == NULL )
|
||
{
|
||
hr = E_UNEXPECTED;
|
||
return hr;
|
||
}
|
||
|
||
pModuleConfig = (MODSECURITY_STORED_CONTEXT *)pMetadataContainer->GetModuleContext( g_pModuleContext );
|
||
if ( pModuleConfig != NULL )
|
||
{
|
||
//
|
||
// We found stored data for this module for the metadata
|
||
// object which is different for unique configuration path
|
||
//
|
||
*ppModuleConfig = pModuleConfig;
|
||
return S_OK;
|
||
}
|
||
|
||
//
|
||
// If we reach here, that means this is first request or first
|
||
// request after a configuration change IIS core will throw stored context away
|
||
// if a change notification arrives for this metadata path
|
||
//
|
||
pModuleConfig = new MODSECURITY_STORED_CONTEXT();
|
||
if ( pModuleConfig == NULL )
|
||
{
|
||
return E_OUTOFMEMORY;
|
||
}
|
||
|
||
//
|
||
// Read module configuration data and store in MODSECURITY_STORED_CONTEXT
|
||
//
|
||
hr = pModuleConfig->Initialize( pContext, &pException );
|
||
if ( FAILED( hr ) || pException != NULL )
|
||
{
|
||
pModuleConfig->CleanupStoredContext();
|
||
|
||
pModuleConfig = NULL;
|
||
hr = E_UNEXPECTED;
|
||
|
||
return hr;
|
||
}
|
||
|
||
//
|
||
// Store MODSECURITY_STORED_CONTEXT data as metadata stored context
|
||
//
|
||
hr = pMetadataContainer->SetModuleContext( pModuleConfig,
|
||
g_pModuleContext );
|
||
if ( FAILED( hr ) )
|
||
{
|
||
pModuleConfig->CleanupStoredContext();
|
||
pModuleConfig = NULL;
|
||
|
||
//
|
||
// It is possible that some other thread stored context before this thread
|
||
// could do. Check returned hr and return context stored by other thread
|
||
//
|
||
if ( hr == HRESULT_FROM_WIN32( ERROR_ALREADY_ASSIGNED ) )
|
||
{
|
||
*ppModuleConfig = (MODSECURITY_STORED_CONTEXT *)pMetadataContainer->GetModuleContext( g_pModuleContext );
|
||
return S_OK;
|
||
}
|
||
}
|
||
|
||
*ppModuleConfig = pModuleConfig;
|
||
return hr;
|
||
}
|