|
Packit Service |
384592 |
/*
|
|
Packit Service |
384592 |
* ModSecurity for Apache 2.x, http://www.modsecurity.org/
|
|
Packit Service |
384592 |
* Copyright (c) 2004-2013 Trustwave Holdings, Inc. (http://www.trustwave.com/)
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* You may not use this file except in compliance with
|
|
Packit Service |
384592 |
* the License. You may obtain a copy of the License at
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit Service |
384592 |
*
|
|
Packit Service |
384592 |
* If any of the files related to licensing are missing or if you have any
|
|
Packit Service |
384592 |
* other questions related to licensing please contact Trustwave Holdings, Inc.
|
|
Packit Service |
384592 |
* directly using the email address security@modsecurity.org.
|
|
Packit Service |
384592 |
*/
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#define WIN32_LEAN_AND_MEAN
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#undef inline
|
|
Packit Service |
384592 |
#define inline inline
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// IIS7 Server API header file
|
|
Packit Service |
384592 |
#include <Windows.h>
|
|
Packit Service |
384592 |
#include <sal.h>
|
|
Packit Service |
384592 |
#include <strsafe.h>
|
|
Packit Service |
384592 |
#include "httpserv.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// Project header files
|
|
Packit Service |
384592 |
#include "mymodule.h"
|
|
Packit Service |
384592 |
#include "mymodulefactory.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "api.h"
|
|
Packit Service |
384592 |
#include "moduleconfig.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#include "winsock2.h"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
class REQUEST_STORED_CONTEXT : public IHttpStoredContext
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
public:
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
m_pConnRec = NULL;
|
|
Packit Service |
384592 |
m_pRequestRec = NULL;
|
|
Packit Service |
384592 |
m_pHttpContext = NULL;
|
|
Packit Service |
384592 |
m_pProvider = NULL;
|
|
Packit Service |
384592 |
m_pResponseBuffer = NULL;
|
|
Packit Service |
384592 |
m_pResponseLength = 0;
|
|
Packit Service |
384592 |
m_pResponsePosition = 0;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
~REQUEST_STORED_CONTEXT()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
FinishRequest();
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// virtual
|
|
Packit Service |
384592 |
VOID
|
|
Packit Service |
384592 |
CleanupStoredContext(
|
|
Packit Service |
384592 |
VOID
|
|
Packit Service |
384592 |
)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
FinishRequest();
|
|
Packit Service |
384592 |
delete this;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
void FinishRequest()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if(m_pRequestRec != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
modsecFinishRequest(m_pRequestRec);
|
|
Packit Service |
384592 |
m_pRequestRec = NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
if(m_pConnRec != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
modsecFinishConnection(m_pConnRec);
|
|
Packit Service |
384592 |
m_pConnRec = NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
conn_rec *m_pConnRec;
|
|
Packit Service |
384592 |
request_rec *m_pRequestRec;
|
|
Packit Service |
384592 |
IHttpContext *m_pHttpContext;
|
|
Packit Service |
384592 |
IHttpEventProvider *m_pProvider;
|
|
Packit Service |
384592 |
char *m_pResponseBuffer;
|
|
Packit Service |
384592 |
ULONGLONG m_pResponseLength;
|
|
Packit Service |
384592 |
ULONGLONG m_pResponsePosition;
|
|
Packit Service |
384592 |
};
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//----------------------------------------------------------------------------
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char *GetIpAddr(apr_pool_t *pool, PSOCKADDR pAddr)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
const char *format = "%15[0-9.]:%5[0-9]";
|
|
Packit Service |
384592 |
char ip[16] = { 0 }; // ip4 addresses have max len 15
|
|
Packit Service |
384592 |
char port[6] = { 0 }; // port numbers are 16bit, ie 5 digits max
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
DWORD len = 50;
|
|
Packit Service |
384592 |
char *buf = (char *)apr_palloc(pool, len);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(buf == NULL)
|
|
Packit Service |
384592 |
return "";
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
buf[0] = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
WSAAddressToString(pAddr, sizeof(SOCKADDR), NULL, buf, &len;;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// test for IPV4 with port on the end
|
|
Packit Service |
384592 |
if (sscanf(buf, format, ip, port) == 2) {
|
|
Packit Service |
384592 |
// IPV4 but with port - remove the port
|
|
Packit Service |
384592 |
char* input = ":";
|
|
Packit Service |
384592 |
char* ipv4 = strtok(buf, input);
|
|
Packit Service |
384592 |
return ipv4;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return buf;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_sockaddr_t *CopySockAddr(apr_pool_t *pool, PSOCKADDR pAddr)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
apr_sockaddr_t *addr = (apr_sockaddr_t *)apr_palloc(pool, sizeof(apr_sockaddr_t));
|
|
Packit Service |
384592 |
int adrlen = 16, iplen = 4;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(pAddr->sa_family == AF_INET6)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
adrlen = 46;
|
|
Packit Service |
384592 |
iplen = 16;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
addr->addr_str_len = adrlen;
|
|
Packit Service |
384592 |
addr->family = pAddr->sa_family;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
addr->hostname = "unknown";
|
|
Packit Service |
384592 |
#ifdef WIN32
|
|
Packit Service |
384592 |
addr->ipaddr_len = sizeof(IN_ADDR);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
addr->ipaddr_len = sizeof(struct in_addr);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
addr->ipaddr_ptr = &addr->sa.sin.sin_addr;
|
|
Packit Service |
384592 |
addr->pool = pool;
|
|
Packit Service |
384592 |
addr->port = 80;
|
|
Packit Service |
384592 |
#ifdef WIN32
|
|
Packit Service |
384592 |
memcpy(&addr->sa.sin.sin_addr.S_un.S_addr, pAddr->sa_data, iplen);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
memcpy(&addr->sa.sin.sin_addr.s_addr, pAddr->sa_data, iplen);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
addr->sa.sin.sin_family = pAddr->sa_family;
|
|
Packit Service |
384592 |
addr->sa.sin.sin_port = 80;
|
|
Packit Service |
384592 |
addr->salen = sizeof(addr->sa);
|
|
Packit Service |
384592 |
addr->servname = addr->hostname;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return addr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//----------------------------------------------------------------------------
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char *ZeroTerminate(const char *str, size_t len, apr_pool_t *pool)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
char *_n = (char *)apr_palloc(pool, len + 1);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
memcpy(_n, str, len);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
_n[len] = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return _n;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//----------------------------------------------------------------------------
|
|
Packit Service |
384592 |
// FUNCTION: ConvertUTF16ToUTF8
|
|
Packit Service |
384592 |
// DESC: Converts Unicode UTF-16 (Windows default) text to Unicode UTF-8.
|
|
Packit Service |
384592 |
//----------------------------------------------------------------------------
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char *ConvertUTF16ToUTF8( __in const WCHAR * pszTextUTF16, size_t cchUTF16, apr_pool_t *pool )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// Special case of NULL or empty input string
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if ( (pszTextUTF16 == NULL) || (*pszTextUTF16 == L'\0') || cchUTF16 == 0 )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Return empty string
|
|
Packit Service |
384592 |
return "";
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// Get size of destination UTF-8 buffer, in CHAR's (= bytes)
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
int cbUTF8 = ::WideCharToMultiByte(
|
|
Packit Service |
384592 |
CP_UTF8, // convert to UTF-8
|
|
Packit Service |
384592 |
0, // specify conversion behavior
|
|
Packit Service |
384592 |
pszTextUTF16, // source UTF-16 string
|
|
Packit Service |
384592 |
static_cast<int>( cchUTF16 ), // total source string length, in WCHAR's,
|
|
Packit Service |
384592 |
NULL, // unused - no conversion required in this step
|
|
Packit Service |
384592 |
0, // request buffer size
|
|
Packit Service |
384592 |
NULL, NULL // unused
|
|
Packit Service |
384592 |
);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( cbUTF8 == 0 )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
return "";
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// Allocate destination buffer for UTF-8 string
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int cchUTF8 = cbUTF8; // sizeof(CHAR) = 1 byte
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
char *pszUTF8 = (char *)apr_palloc(pool, cchUTF8 + 1 );
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// Do the conversion from UTF-16 to UTF-8
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
int result = ::WideCharToMultiByte(
|
|
Packit Service |
384592 |
CP_UTF8, // convert to UTF-8
|
|
Packit Service |
384592 |
0, // specify conversion behavior
|
|
Packit Service |
384592 |
pszTextUTF16, // source UTF-16 string
|
|
Packit Service |
384592 |
static_cast<int>( cchUTF16 ), // total source string length, in WCHAR's,
|
|
Packit Service |
384592 |
// including end-of-string \0
|
|
Packit Service |
384592 |
pszUTF8, // destination buffer
|
|
Packit Service |
384592 |
cbUTF8, // destination buffer size, in bytes
|
|
Packit Service |
384592 |
NULL, NULL // unused
|
|
Packit Service |
384592 |
);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( result == 0 )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
return "";
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pszUTF8[cchUTF8] = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return pszUTF8;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
void Log(void *obj, int level, char *str)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
CMyHttpModule *mod = (CMyHttpModule *)obj;
|
|
Packit Service |
384592 |
WORD logcat = EVENTLOG_INFORMATION_TYPE;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
level &= APLOG_LEVELMASK;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(level <= APLOG_ERR)
|
|
Packit Service |
384592 |
logcat = EVENTLOG_ERROR_TYPE;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(level == APLOG_WARNING || strstr(str, "Warning.") != NULL)
|
|
Packit Service |
384592 |
logcat = EVENTLOG_WARNING_TYPE;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
mod->WriteEventViewerLog(str, logcat);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#define NOTE_IIS "iis-tx-context"
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
void StoreIISContext(request_rec *r, REQUEST_STORED_CONTEXT *rsc)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
apr_table_setn(r->notes, NOTE_IIS, (const char *)rsc);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *RetrieveIISContext(request_rec *r)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *msr = NULL;
|
|
Packit Service |
384592 |
request_rec *rx = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* Look in the current request first. */
|
|
Packit Service |
384592 |
msr = (REQUEST_STORED_CONTEXT *)apr_table_get(r->notes, NOTE_IIS);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
//msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If this is a subrequest then look in the main request. */
|
|
Packit Service |
384592 |
if (r->main != NULL) {
|
|
Packit Service |
384592 |
msr = (REQUEST_STORED_CONTEXT *)apr_table_get(r->main->notes, NOTE_IIS);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
//msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
/* If the request was redirected then look in the previous requests. */
|
|
Packit Service |
384592 |
rx = r->prev;
|
|
Packit Service |
384592 |
while(rx != NULL) {
|
|
Packit Service |
384592 |
msr = (REQUEST_STORED_CONTEXT *)apr_table_get(rx->notes, NOTE_IIS);
|
|
Packit Service |
384592 |
if (msr != NULL) {
|
|
Packit Service |
384592 |
//msr->r = r;
|
|
Packit Service |
384592 |
return msr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
rx = rx->prev;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return NULL;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HRESULT CMyHttpModule::ReadFileChunk(HTTP_DATA_CHUNK *chunk, char *buf)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
OVERLAPPED ovl;
|
|
Packit Service |
384592 |
DWORD dwDataStartOffset;
|
|
Packit Service |
384592 |
ULONGLONG bytesTotal = 0;
|
|
Packit Service |
384592 |
BYTE * pIoBuffer = NULL;
|
|
Packit Service |
384592 |
HANDLE hIoEvent = INVALID_HANDLE_VALUE;
|
|
Packit Service |
384592 |
HRESULT hr = S_OK;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pIoBuffer = (BYTE *)VirtualAlloc(NULL,
|
|
Packit Service |
384592 |
1,
|
|
Packit Service |
384592 |
MEM_COMMIT | MEM_RESERVE,
|
|
Packit Service |
384592 |
PAGE_READWRITE);
|
|
Packit Service |
384592 |
if (pIoBuffer == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
Packit Service |
384592 |
goto Done;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hIoEvent = CreateEvent(NULL, // security attr
|
|
Packit Service |
384592 |
FALSE, // manual reset
|
|
Packit Service |
384592 |
FALSE, // initial state
|
|
Packit Service |
384592 |
NULL); // name
|
|
Packit Service |
384592 |
if (hIoEvent == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
Packit Service |
384592 |
goto Done;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
while(bytesTotal < chunk->FromFileHandle.ByteRange.Length.QuadPart)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
DWORD bytesRead = 0;
|
|
Packit Service |
384592 |
int was_eof = 0;
|
|
Packit Service |
384592 |
ULONGLONG offset = chunk->FromFileHandle.ByteRange.StartingOffset.QuadPart + bytesTotal;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ZeroMemory(&ovl, sizeof ovl);
|
|
Packit Service |
384592 |
ovl.hEvent = hIoEvent;
|
|
Packit Service |
384592 |
ovl.Offset = (DWORD)offset;
|
|
Packit Service |
384592 |
dwDataStartOffset = ovl.Offset & (m_dwPageSize - 1);
|
|
Packit Service |
384592 |
ovl.Offset &= ~(m_dwPageSize - 1);
|
|
Packit Service |
384592 |
ovl.OffsetHigh = offset >> 32;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (!ReadFile(chunk->FromFileHandle.FileHandle,
|
|
Packit Service |
384592 |
pIoBuffer,
|
|
Packit Service |
384592 |
m_dwPageSize,
|
|
Packit Service |
384592 |
&bytesRead,
|
|
Packit Service |
384592 |
&ovl))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
DWORD dwErr = GetLastError();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch (dwErr)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
case ERROR_IO_PENDING:
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// GetOverlappedResult can return without waiting for the
|
|
Packit Service |
384592 |
// event thus leaving it signalled and causing problems
|
|
Packit Service |
384592 |
// with future use of that event handle, so just wait ourselves
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
WaitForSingleObject(ovl.hEvent, INFINITE); // == WAIT_OBJECT_0);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (!GetOverlappedResult(
|
|
Packit Service |
384592 |
chunk->FromFileHandle.FileHandle,
|
|
Packit Service |
384592 |
&ovl,
|
|
Packit Service |
384592 |
&bytesRead,
|
|
Packit Service |
384592 |
TRUE))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
dwErr = GetLastError();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch(dwErr)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
case ERROR_HANDLE_EOF:
|
|
Packit Service |
384592 |
was_eof = 1;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(dwErr);
|
|
Packit Service |
384592 |
goto Done;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
case ERROR_HANDLE_EOF:
|
|
Packit Service |
384592 |
was_eof = 1;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(dwErr);
|
|
Packit Service |
384592 |
goto Done;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
bytesRead -= dwDataStartOffset;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (bytesRead > chunk->FromFileHandle.ByteRange.Length.QuadPart)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
bytesRead = (DWORD)chunk->FromFileHandle.ByteRange.Length.QuadPart;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
if ((bytesTotal + bytesRead) > chunk->FromFileHandle.ByteRange.Length.QuadPart)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
bytesRead = chunk->FromFileHandle.ByteRange.Length.QuadPart - bytesTotal;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
memcpy(buf, pIoBuffer + dwDataStartOffset, bytesRead);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
buf += bytesRead;
|
|
Packit Service |
384592 |
bytesTotal += bytesRead;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(was_eof != 0)
|
|
Packit Service |
384592 |
chunk->FromFileHandle.ByteRange.Length.QuadPart = bytesTotal;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
Done:
|
|
Packit Service |
384592 |
if(NULL != pIoBuffer)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
VirtualFree(pIoBuffer, 0, MEM_RELEASE);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(INVALID_HANDLE_VALUE != hIoEvent)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
CloseHandle(hIoEvent);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return hr;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
REQUEST_NOTIFICATION_STATUS
|
|
Packit Service |
384592 |
CMyHttpModule::OnSendResponse(
|
|
Packit Service |
384592 |
IN IHttpContext * pHttpContext,
|
|
Packit Service |
384592 |
IN ISendResponseProvider * pResponseProvider
|
|
Packit Service |
384592 |
)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc = (REQUEST_STORED_CONTEXT *)pHttpContext->GetModuleContextContainer()->GetModuleContext(g_pModuleContext);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
EnterCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// here we must check if response body processing is enabled
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if(rsc == NULL || rsc->m_pRequestRec == NULL || rsc->m_pResponseBuffer != NULL || !modsecIsResponseBodyAccessEnabled(rsc->m_pRequestRec))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
goto Exit;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HRESULT hr = S_OK;
|
|
Packit Service |
384592 |
IHttpResponse *pHttpResponse = NULL;
|
|
Packit Service |
384592 |
HTTP_RESPONSE *pRawHttpResponse = NULL;
|
|
Packit Service |
384592 |
HTTP_BYTE_RANGE *pFileByteRange = NULL;
|
|
Packit Service |
384592 |
HTTP_DATA_CHUNK *pSourceDataChunk = NULL;
|
|
Packit Service |
384592 |
LARGE_INTEGER lFileSize;
|
|
Packit Service |
384592 |
REQUEST_NOTIFICATION_STATUS ret = RQ_NOTIFICATION_CONTINUE;
|
|
Packit Service |
384592 |
ULONGLONG ulTotalLength = 0;
|
|
Packit Service |
384592 |
DWORD c;
|
|
Packit Service |
384592 |
request_rec *r = rsc->m_pRequestRec;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pHttpResponse = pHttpContext->GetResponse();
|
|
Packit Service |
384592 |
pRawHttpResponse = pHttpResponse->GetRawHttpResponse();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// here we must add handling of chunked response
|
|
Packit Service |
384592 |
// apparently IIS 7 calls this handler once per chunk
|
|
Packit Service |
384592 |
// see: http://stackoverflow.com/questions/4385249/how-to-buffer-and-process-chunked-data-before-sending-headers-in-iis7-native-mod
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(pRawHttpResponse->EntityChunkCount == 0)
|
|
Packit Service |
384592 |
goto Exit;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// here we must transfer response headers
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
USHORT ctcch = 0;
|
|
Packit Service |
384592 |
char *ct = (char *)pHttpResponse->GetHeader(HttpHeaderContentType, &ctcch);
|
|
Packit Service |
384592 |
char *ctz = ZeroTerminate(ct, ctcch, r->pool);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// assume HTML if content type not set
|
|
Packit Service |
384592 |
// without this output filter would not buffer response and processing would hang
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if(ctz[0] == 0)
|
|
Packit Service |
384592 |
ctz = "text/html";
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->content_type = ctz;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#define _TRANSHEADER(id,str) if(pRawHttpResponse->Headers.KnownHeaders[id].pRawValue != NULL) \
|
|
Packit Service |
384592 |
{\
|
|
Packit Service |
384592 |
apr_table_setn(r->headers_out, str, \
|
|
Packit Service |
384592 |
ZeroTerminate(pRawHttpResponse->Headers.KnownHeaders[id].pRawValue, pRawHttpResponse->Headers.KnownHeaders[id].RawValueLength, r->pool)); \
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderCacheControl, "Cache-Control");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderConnection, "Connection");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderDate, "Date");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderKeepAlive, "Keep-Alive");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderPragma, "Pragma");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTrailer, "Trailer");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTransferEncoding, "Transfer-Encoding");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderUpgrade, "Upgrade");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderVia, "Via");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderWarning, "Warning");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAllow, "Allow");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLength, "Content-Length");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentType, "Content-Type");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentEncoding, "Content-Encoding");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLanguage, "Content-Language");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLocation, "Content-Location");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentMd5, "Content-Md5");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentRange, "Content-Range");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderExpires, "Expires");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderLastModified, "Last-Modified");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAcceptRanges, "Accept-Ranges");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAge, "Age");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderEtag, "Etag");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderLocation, "Location");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderProxyAuthenticate, "Proxy-Authenticate");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderRetryAfter, "Retry-After");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderServer, "Server");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderSetCookie, "Set-Cookie");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderVary, "Vary");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderWwwAuthenticate, "Www-Authenticate");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#undef _TRANSHEADER
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
for(int i = 0; i < pRawHttpResponse->Headers.UnknownHeaderCount; i++)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
apr_table_setn(r->headers_out,
|
|
Packit Service |
384592 |
ZeroTerminate(pRawHttpResponse->Headers.pUnknownHeaders[i].pName, pRawHttpResponse->Headers.pUnknownHeaders[i].NameLength, r->pool),
|
|
Packit Service |
384592 |
ZeroTerminate(pRawHttpResponse->Headers.pUnknownHeaders[i].pRawValue, pRawHttpResponse->Headers.pUnknownHeaders[i].RawValueLength, r->pool));
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->content_encoding = apr_table_get(r->headers_out, "Content-Encoding");
|
|
Packit Service |
384592 |
//r->content_type = apr_table_get(r->headers_out, "Content-Type"); -- already set above
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
const char *lng = apr_table_get(r->headers_out, "Content-Languages");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(lng != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*(const char **)apr_array_push(r->content_languages) = lng;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// Disable kernel caching for this response
|
|
Packit Service |
384592 |
// Probably we don't have to do it for ModSecurity
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//pHttpContext->GetResponse()->DisableKernelCache(
|
|
Packit Service |
384592 |
// IISCacheEvents::HTTPSYS_CACHEABLE::HANDLER_HTTPSYS_UNFRIENDLY);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
for(c = 0; c < pRawHttpResponse->EntityChunkCount; c++ )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
pSourceDataChunk = &pRawHttpResponse->pEntityChunks[ c ];
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch( pSourceDataChunk->DataChunkType )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
case HttpDataChunkFromMemory:
|
|
Packit Service |
384592 |
ulTotalLength += pSourceDataChunk->FromMemory.BufferLength;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpDataChunkFromFileHandle:
|
|
Packit Service |
384592 |
pFileByteRange = &pSourceDataChunk->FromFileHandle.ByteRange;
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// File chunks may contain by ranges with unspecified length
|
|
Packit Service |
384592 |
// (HTTP_BYTE_RANGE_TO_EOF). In order to send parts of such a chunk,
|
|
Packit Service |
384592 |
// its necessary to know when the chunk is finished, and
|
|
Packit Service |
384592 |
// we need to move to the next chunk.
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if ( pFileByteRange->Length.QuadPart == HTTP_BYTE_RANGE_TO_EOF)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if ( GetFileType( pSourceDataChunk->FromFileHandle.FileHandle ) ==
|
|
Packit Service |
384592 |
FILE_TYPE_DISK )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if ( !GetFileSizeEx( pSourceDataChunk->FromFileHandle.FileHandle,
|
|
Packit Service |
384592 |
&lFileSize ) )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
DWORD dwError = GetLastError();
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(dwError);
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// put the resolved file length in the chunk, replacing
|
|
Packit Service |
384592 |
// HTTP_BYTE_RANGE_TO_EOF
|
|
Packit Service |
384592 |
pFileByteRange->Length.QuadPart =
|
|
Packit Service |
384592 |
lFileSize.QuadPart - pFileByteRange->StartingOffset.QuadPart;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
else
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ulTotalLength += pFileByteRange->Length.QuadPart;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
// TBD: consider implementing HttpDataChunkFromFragmentCache,
|
|
Packit Service |
384592 |
// and HttpDataChunkFromFragmentCacheEx
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc->m_pResponseBuffer = (char *)apr_palloc(rsc->m_pRequestRec->pool, ulTotalLength);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ulTotalLength = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
for(c = 0; c < pRawHttpResponse->EntityChunkCount; c++ )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
pSourceDataChunk = &pRawHttpResponse->pEntityChunks[ c ];
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch( pSourceDataChunk->DataChunkType )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
case HttpDataChunkFromMemory:
|
|
Packit Service |
384592 |
memcpy(rsc->m_pResponseBuffer + ulTotalLength, pSourceDataChunk->FromMemory.pBuffer, pSourceDataChunk->FromMemory.BufferLength);
|
|
Packit Service |
384592 |
ulTotalLength += pSourceDataChunk->FromMemory.BufferLength;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpDataChunkFromFileHandle:
|
|
Packit Service |
384592 |
pFileByteRange = &pSourceDataChunk->FromFileHandle.ByteRange;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(ReadFileChunk(pSourceDataChunk, rsc->m_pResponseBuffer + ulTotalLength) != S_OK)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
DWORD dwErr = GetLastError();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(dwErr);
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ulTotalLength += pFileByteRange->Length.QuadPart;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
// TBD: consider implementing HttpDataChunkFromFragmentCache,
|
|
Packit Service |
384592 |
// and HttpDataChunkFromFragmentCacheEx
|
|
Packit Service |
384592 |
hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc->m_pResponseLength = ulTotalLength;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
// If there's no content-length set, we need to set it to avoid chunked transfer mode
|
|
Packit Service |
384592 |
// We can only do it if there is it's the only response to be sent.
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
DWORD dwFlags = pResponseProvider->GetFlags();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (pResponseProvider->GetHeadersBeingSent() &&
|
|
Packit Service |
384592 |
(dwFlags & HTTP_SEND_RESPONSE_FLAG_MORE_DATA) == 0 &&
|
|
Packit Service |
384592 |
pHttpContext->GetResponse()->GetHeader(HttpHeaderContentLength) == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
CHAR szLength[21]; //Max length for a 64 bit int is 20
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ZeroMemory(szLength, sizeof(szLength));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = StringCchPrintfA(
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
sizeof(szLength) / sizeof(CHAR) - 1, "%d",
|
|
Packit Service |
384592 |
ulTotalLength);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = pHttpContext->GetResponse()->SetHeader(
|
|
Packit Service |
384592 |
HttpHeaderContentLength,
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
(USHORT)strlen(szLength),
|
|
Packit Service |
384592 |
TRUE);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
Finished:
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int status = modsecProcessResponse(rsc->m_pRequestRec);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// the logic here is temporary, needs clarification
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if(status != 0 && status != -1)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
pHttpContext->GetResponse()->Clear();
|
|
Packit Service |
384592 |
pHttpContext->GetResponse()->SetStatus(status, "ModSecurity Action");
|
|
Packit Service |
384592 |
pHttpContext->SetRequestHandled();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc->FinishRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
LeaveCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return RQ_NOTIFICATION_FINISH_REQUEST;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
Exit:
|
|
Packit Service |
384592 |
// temporary hack, in reality OnSendRequest theoretically could possibly come before OnEndRequest
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if(rsc != NULL)
|
|
Packit Service |
384592 |
rsc->FinishRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
LeaveCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return RQ_NOTIFICATION_CONTINUE;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
REQUEST_NOTIFICATION_STATUS
|
|
Packit Service |
384592 |
CMyHttpModule::OnPostEndRequest(
|
|
Packit Service |
384592 |
IN IHttpContext * pHttpContext,
|
|
Packit Service |
384592 |
IN IHttpEventProvider * pProvider
|
|
Packit Service |
384592 |
)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc = (REQUEST_STORED_CONTEXT *)pHttpContext->GetModuleContextContainer()->GetModuleContext(g_pModuleContext);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// only finish request if OnSendResponse have been called already
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if(rsc != NULL && rsc->m_pResponseBuffer != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
EnterCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc->FinishRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
LeaveCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return RQ_NOTIFICATION_CONTINUE;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
REQUEST_NOTIFICATION_STATUS
|
|
Packit Service |
384592 |
CMyHttpModule::OnBeginRequest(
|
|
Packit Service |
384592 |
IN IHttpContext * pHttpContext,
|
|
Packit Service |
384592 |
IN IHttpEventProvider * pProvider
|
|
Packit Service |
384592 |
)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
HRESULT hr = S_OK;
|
|
Packit Service |
384592 |
IHttpRequest* pRequest = NULL;
|
|
Packit Service |
384592 |
MODSECURITY_STORED_CONTEXT* pConfig = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
UNREFERENCED_PARAMETER ( pProvider );
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
EnterCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( pHttpContext == NULL )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = E_UNEXPECTED;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pRequest = pHttpContext->GetRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( pRequest == NULL )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = E_UNEXPECTED;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = MODSECURITY_STORED_CONTEXT::GetConfig(pHttpContext, &pConfig );
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( FAILED( hr ) )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
//hr = E_UNEXPECTED;
|
|
Packit Service |
384592 |
hr = S_OK;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// If module is disabled, dont go any further
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
if( pConfig->GetIsEnabled() == false )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// every 3 seconds we check for changes in config file
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
DWORD ctime = GetTickCount();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(pConfig->m_Config == NULL || (ctime - pConfig->m_dwLastCheck) > 3000)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
char *path;
|
|
Packit Service |
384592 |
USHORT pathlen;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = pConfig->GlobalWideCharToMultiByte(pConfig->GetPath(), wcslen(pConfig->GetPath()), &path, &pathlen);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( FAILED( hr ) )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
hr = E_UNEXPECTED;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
WIN32_FILE_ATTRIBUTE_DATA fdata;
|
|
Packit Service |
384592 |
BOOL ret;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ret = GetFileAttributesEx(path, GetFileExInfoStandard, &fdata);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pConfig->m_dwLastCheck = ctime;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(pConfig->m_Config == NULL || (ret != 0 && (pConfig->m_LastChange.dwLowDateTime != fdata.ftLastWriteTime.dwLowDateTime ||
|
|
Packit Service |
384592 |
pConfig->m_LastChange.dwHighDateTime != fdata.ftLastWriteTime.dwHighDateTime)))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
pConfig->m_LastChange.dwLowDateTime = fdata.ftLastWriteTime.dwLowDateTime;
|
|
Packit Service |
384592 |
pConfig->m_LastChange.dwHighDateTime = fdata.ftLastWriteTime.dwHighDateTime;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pConfig->m_Config = modsecGetDefaultConfig();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
PCWSTR servpath = pHttpContext->GetApplication()->GetApplicationPhysicalPath();
|
|
Packit Service |
384592 |
char *apppath;
|
|
Packit Service |
384592 |
USHORT apppathlen;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = pConfig->GlobalWideCharToMultiByte((WCHAR *)servpath, wcslen(servpath), &apppath, &apppathlen);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( FAILED( hr ) )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
delete path;
|
|
Packit Service |
384592 |
hr = E_UNEXPECTED;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(path[0] != 0)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
const char * err = modsecProcessConfig((directory_config *)pConfig->m_Config, path, apppath);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(err != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
WriteEventViewerLog(err, EVENTLOG_ERROR_TYPE);
|
|
Packit Service |
384592 |
delete apppath;
|
|
Packit Service |
384592 |
delete path;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecReportRemoteLoadedRules();
|
|
Packit Service |
384592 |
if (this->status_call_already_sent == false)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
this->status_call_already_sent = true;
|
|
Packit Service |
384592 |
modsecStatusEngineCall();
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
delete apppath;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
delete path;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
conn_rec *c;
|
|
Packit Service |
384592 |
request_rec *r;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
c = modsecNewConnection();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecProcessConnection(c);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r = modsecNewRequest(c, (directory_config *)pConfig->m_Config);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// on IIS we force input stream inspection flag, because its absence does not add any performance gain
|
|
Packit Service |
384592 |
// it's because on IIS request body must be restored each time it was read
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
modsecSetConfigForIISRequestBody(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = new REQUEST_STORED_CONTEXT();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
rsc->m_pConnRec = c;
|
|
Packit Service |
384592 |
rsc->m_pRequestRec = r;
|
|
Packit Service |
384592 |
rsc->m_pHttpContext = pHttpContext;
|
|
Packit Service |
384592 |
rsc->m_pProvider = pProvider;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pHttpContext->GetModuleContextContainer()->SetModuleContext(rsc, g_pModuleContext);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
StoreIISContext(r, rsc);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HTTP_REQUEST *req = pRequest->GetRawHttpRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->hostname = ConvertUTF16ToUTF8(req->CookedUrl.pHost, req->CookedUrl.HostLength / sizeof(WCHAR), r->pool);
|
|
Packit Service |
384592 |
r->path_info = ConvertUTF16ToUTF8(req->CookedUrl.pAbsPath, req->CookedUrl.AbsPathLength / sizeof(WCHAR), r->pool);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(r->hostname == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
if(req->Headers.KnownHeaders[HttpHeaderHost].pRawValue != NULL)
|
|
Packit Service |
384592 |
r->hostname = ZeroTerminate(req->Headers.KnownHeaders[HttpHeaderHost].pRawValue,
|
|
Packit Service |
384592 |
req->Headers.KnownHeaders[HttpHeaderHost].RawValueLength, r->pool);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int port = 0;
|
|
Packit Service |
384592 |
char *port_str = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(r->hostname != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
int k = 0;
|
|
Packit Service |
384592 |
char *ptr = (char *)r->hostname;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
while(*ptr != 0 && *ptr != ':')
|
|
Packit Service |
384592 |
ptr++;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(*ptr == ':')
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
*ptr = 0;
|
|
Packit Service |
384592 |
port_str = ptr + 1;
|
|
Packit Service |
384592 |
port = atoi(port_str);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(req->CookedUrl.pQueryString != NULL && req->CookedUrl.QueryStringLength > 0)
|
|
Packit Service |
384592 |
r->args = ConvertUTF16ToUTF8(req->CookedUrl.pQueryString + 1, (req->CookedUrl.QueryStringLength / sizeof(WCHAR)) - 1, r->pool);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#define _TRANSHEADER(id,str) if(req->Headers.KnownHeaders[id].pRawValue != NULL) \
|
|
Packit Service |
384592 |
{\
|
|
Packit Service |
384592 |
apr_table_setn(r->headers_in, str, \
|
|
Packit Service |
384592 |
ZeroTerminate(req->Headers.KnownHeaders[id].pRawValue, req->Headers.KnownHeaders[id].RawValueLength, r->pool)); \
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderCacheControl, "Cache-Control");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderConnection, "Connection");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderDate, "Date");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderKeepAlive, "Keep-Alive");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderPragma, "Pragma");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTrailer, "Trailer");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTransferEncoding, "Transfer-Encoding");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderUpgrade, "Upgrade");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderVia, "Via");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderWarning, "Warning");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAllow, "Allow");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLength, "Content-Length");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentType, "Content-Type");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentEncoding, "Content-Encoding");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLanguage, "Content-Language");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentLocation, "Content-Location");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentMd5, "Content-Md5");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderContentRange, "Content-Range");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderExpires, "Expires");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderLastModified, "Last-Modified");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAccept, "Accept");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAcceptCharset, "Accept-Charset");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAcceptEncoding, "Accept-Encoding");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAcceptLanguage, "Accept-Language");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderAuthorization, "Authorization");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderCookie, "Cookie");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderExpect, "Expect");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderFrom, "From");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderHost, "Host");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderIfMatch, "If-Match");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderIfModifiedSince, "If-Modified-Since");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderIfNoneMatch, "If-None-Match");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderIfRange, "If-Range");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderIfUnmodifiedSince, "If-Unmodified-Since");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderMaxForwards, "Max-Forwards");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderProxyAuthorization, "Proxy-Authorization");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderReferer, "Referer");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderRange, "Range");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTe, "TE");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderTranslate, "Translate");
|
|
Packit Service |
384592 |
_TRANSHEADER(HttpHeaderUserAgent, "User-Agent");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#undef _TRANSHEADER
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
for(int i = 0; i < req->Headers.UnknownHeaderCount; i++)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
apr_table_setn(r->headers_in,
|
|
Packit Service |
384592 |
ZeroTerminate(req->Headers.pUnknownHeaders[i].pName, req->Headers.pUnknownHeaders[i].NameLength, r->pool),
|
|
Packit Service |
384592 |
ZeroTerminate(req->Headers.pUnknownHeaders[i].pRawValue, req->Headers.pUnknownHeaders[i].RawValueLength, r->pool));
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->content_encoding = apr_table_get(r->headers_in, "Content-Encoding");
|
|
Packit Service |
384592 |
r->content_type = apr_table_get(r->headers_in, "Content-Type");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
const char *lng = apr_table_get(r->headers_in, "Content-Languages");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(lng != NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
r->content_languages = apr_array_make(r->pool, 1, sizeof(const char *));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*(const char **)apr_array_push(r->content_languages) = lng;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
switch(req->Verb)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
case HttpVerbUnparsed:
|
|
Packit Service |
384592 |
case HttpVerbUnknown:
|
|
Packit Service |
384592 |
case HttpVerbInvalid:
|
|
Packit Service |
384592 |
case HttpVerbTRACK: // used by Microsoft Cluster Server for a non-logged trace
|
|
Packit Service |
384592 |
case HttpVerbSEARCH:
|
|
Packit Service |
384592 |
default:
|
|
Packit Service |
384592 |
r->method = "INVALID";
|
|
Packit Service |
384592 |
r->method_number = M_INVALID;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbOPTIONS:
|
|
Packit Service |
384592 |
r->method = "OPTIONS";
|
|
Packit Service |
384592 |
r->method_number = M_OPTIONS;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbGET:
|
|
Packit Service |
384592 |
case HttpVerbHEAD:
|
|
Packit Service |
384592 |
r->method = "GET";
|
|
Packit Service |
384592 |
r->method_number = M_GET;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbPOST:
|
|
Packit Service |
384592 |
r->method = "POST";
|
|
Packit Service |
384592 |
r->method_number = M_POST;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbPUT:
|
|
Packit Service |
384592 |
r->method = "PUT";
|
|
Packit Service |
384592 |
r->method_number = M_PUT;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbDELETE:
|
|
Packit Service |
384592 |
r->method = "DELETE";
|
|
Packit Service |
384592 |
r->method_number = M_DELETE;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbTRACE:
|
|
Packit Service |
384592 |
r->method = "TRACE";
|
|
Packit Service |
384592 |
r->method_number = M_TRACE;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbCONNECT:
|
|
Packit Service |
384592 |
r->method = "CONNECT";
|
|
Packit Service |
384592 |
r->method_number = M_CONNECT;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbMOVE:
|
|
Packit Service |
384592 |
r->method = "MOVE";
|
|
Packit Service |
384592 |
r->method_number = M_MOVE;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbCOPY:
|
|
Packit Service |
384592 |
r->method = "COPY";
|
|
Packit Service |
384592 |
r->method_number = M_COPY;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbPROPFIND:
|
|
Packit Service |
384592 |
r->method = "PROPFIND";
|
|
Packit Service |
384592 |
r->method_number = M_PROPFIND;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbPROPPATCH:
|
|
Packit Service |
384592 |
r->method = "PROPPATCH";
|
|
Packit Service |
384592 |
r->method_number = M_PROPPATCH;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbMKCOL:
|
|
Packit Service |
384592 |
r->method = "MKCOL";
|
|
Packit Service |
384592 |
r->method_number = M_MKCOL;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbLOCK:
|
|
Packit Service |
384592 |
r->method = "LOCK";
|
|
Packit Service |
384592 |
r->method_number = M_LOCK;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
case HttpVerbUNLOCK:
|
|
Packit Service |
384592 |
r->method = "UNLOCK";
|
|
Packit Service |
384592 |
r->method_number = M_UNLOCK;
|
|
Packit Service |
384592 |
break;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(HTTP_EQUAL_VERSION(req->Version, 0, 9))
|
|
Packit Service |
384592 |
r->protocol = "HTTP/0.9";
|
|
Packit Service |
384592 |
else if(HTTP_EQUAL_VERSION(req->Version, 1, 0))
|
|
Packit Service |
384592 |
r->protocol = "HTTP/1.0";
|
|
Packit Service |
384592 |
else
|
|
Packit Service |
384592 |
r->protocol = "HTTP/1.1";
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->request_time = apr_time_now();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->parsed_uri.scheme = "http";
|
|
Packit Service |
384592 |
r->parsed_uri.path = r->path_info;
|
|
Packit Service |
384592 |
r->parsed_uri.hostname = (char *)r->hostname;
|
|
Packit Service |
384592 |
r->parsed_uri.is_initialized = 1;
|
|
Packit Service |
384592 |
r->parsed_uri.port = port;
|
|
Packit Service |
384592 |
r->parsed_uri.port_str = port_str;
|
|
Packit Service |
384592 |
r->parsed_uri.query = r->args;
|
|
Packit Service |
384592 |
r->parsed_uri.dns_looked_up = 0;
|
|
Packit Service |
384592 |
r->parsed_uri.dns_resolved = 0;
|
|
Packit Service |
384592 |
r->parsed_uri.password = NULL;
|
|
Packit Service |
384592 |
r->parsed_uri.user = NULL;
|
|
Packit Service |
384592 |
r->parsed_uri.fragment = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->unparsed_uri = ZeroTerminate(req->pRawUrl, req->RawUrlLength, r->pool);
|
|
Packit Service |
384592 |
r->uri = r->unparsed_uri;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
r->the_request = (char *)apr_palloc(r->pool, strlen(r->method) + 1 + req->RawUrlLength + 1 + strlen(r->protocol) + 1);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
strcpy(r->the_request, r->method);
|
|
Packit Service |
384592 |
strcat(r->the_request, " ");
|
|
Packit Service |
384592 |
strcat(r->the_request, r->uri);
|
|
Packit Service |
384592 |
strcat(r->the_request, " ");
|
|
Packit Service |
384592 |
strcat(r->the_request, r->protocol);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HTTP_REQUEST_ID httpRequestID;
|
|
Packit Service |
384592 |
char *pszValue = (char *)apr_palloc(r->pool, 24);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
httpRequestID = pRequest->GetRawHttpRequest()->RequestId;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
_ui64toa(httpRequestID, pszValue, 10);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_table_setn(r->subprocess_env, "UNIQUE_ID", pszValue);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
PSOCKADDR pAddr = pRequest->GetRemoteAddress();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
#if AP_SERVER_MAJORVERSION_NUMBER > 1 && AP_SERVER_MINORVERSION_NUMBER < 3
|
|
Packit Service |
384592 |
c->remote_addr = CopySockAddr(r->pool, pAddr);
|
|
Packit Service |
384592 |
c->remote_ip = GetIpAddr(r->pool, pAddr);
|
|
Packit Service |
384592 |
#else
|
|
Packit Service |
384592 |
c->client_addr = CopySockAddr(r->pool, pAddr);
|
|
Packit Service |
384592 |
c->client_ip = GetIpAddr(r->pool, pAddr);
|
|
Packit Service |
384592 |
#endif
|
|
Packit Service |
384592 |
c->remote_host = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
int status = modsecProcessRequest(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(status != DECLINED)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
pHttpContext->GetResponse()->SetStatus(status, "ModSecurity Action");
|
|
Packit Service |
384592 |
pHttpContext->SetRequestHandled();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = E_FAIL;
|
|
Packit Service |
384592 |
goto Finished;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
Finished:
|
|
Packit Service |
384592 |
LeaveCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if ( FAILED( hr ) )
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
return RQ_NOTIFICATION_FINISH_REQUEST;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return RQ_NOTIFICATION_CONTINUE;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_status_t ReadBodyCallback(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*readcnt = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(rsc == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
*is_eos = 1;
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
IHttpContext *pHttpContext = rsc->m_pHttpContext;
|
|
Packit Service |
384592 |
IHttpRequest *pRequest = pHttpContext->GetRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(pRequest->GetRemainingEntityBytes() == 0)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
*is_eos = 1;
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HRESULT hr = pRequest->ReadEntityBody(buf, length, false, (DWORD *)readcnt, NULL);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if (FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// End of data is okay.
|
|
Packit Service |
384592 |
if (ERROR_HANDLE_EOF != (hr & 0x0000FFFF))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Set the error status.
|
|
Packit Service |
384592 |
rsc->m_pProvider->SetErrorStatus( hr );
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*is_eos = 1;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_status_t WriteBodyCallback(request_rec *r, char *buf, unsigned int length)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(rsc == NULL || rsc->m_pRequestRec == NULL)
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
IHttpContext *pHttpContext = rsc->m_pHttpContext;
|
|
Packit Service |
384592 |
IHttpRequest *pHttpRequest = pHttpContext->GetRequest();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
CHAR szLength[21]; //Max length for a 64 bit int is 20
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ZeroMemory(szLength, sizeof(szLength));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HRESULT hr = StringCchPrintfA(
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
sizeof(szLength) / sizeof(CHAR) - 1, "%d",
|
|
Packit Service |
384592 |
length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// not possible
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = pHttpRequest->SetHeader(
|
|
Packit Service |
384592 |
HttpHeaderContentLength,
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
(USHORT)strlen(szLength),
|
|
Packit Service |
384592 |
TRUE);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// possible, but there's nothing we can do
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// since we clean the APR pool at the end of OnSendRequest, we must get IIS-managed memory chunk
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
void *reqbuf = pHttpContext->AllocateRequestMemory(length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
memcpy(reqbuf, buf, length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pHttpRequest->InsertEntityBody(reqbuf, length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_status_t ReadResponseCallback(request_rec *r, char *buf, unsigned int length, unsigned int *readcnt, int *is_eos)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*readcnt = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(rsc == NULL || rsc->m_pResponseBuffer == NULL)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
*is_eos = 1;
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
unsigned int size = length;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(size > rsc->m_pResponseLength - rsc->m_pResponsePosition)
|
|
Packit Service |
384592 |
size = rsc->m_pResponseLength - rsc->m_pResponsePosition;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
memcpy(buf, rsc->m_pResponseBuffer + rsc->m_pResponsePosition, size);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
*readcnt = size;
|
|
Packit Service |
384592 |
rsc->m_pResponsePosition += size;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(rsc->m_pResponsePosition >= rsc->m_pResponseLength)
|
|
Packit Service |
384592 |
*is_eos = 1;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
apr_status_t WriteResponseCallback(request_rec *r, char *buf, unsigned int length)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
REQUEST_STORED_CONTEXT *rsc = RetrieveIISContext(r);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(rsc == NULL || rsc->m_pRequestRec == NULL || rsc->m_pResponseBuffer == NULL)
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
IHttpContext *pHttpContext = rsc->m_pHttpContext;
|
|
Packit Service |
384592 |
IHttpResponse *pHttpResponse = pHttpContext->GetResponse();
|
|
Packit Service |
384592 |
HTTP_RESPONSE *pRawHttpResponse = pHttpResponse->GetRawHttpResponse();
|
|
Packit Service |
384592 |
HTTP_DATA_CHUNK *pDataChunk = (HTTP_DATA_CHUNK *)apr_palloc(rsc->m_pRequestRec->pool, sizeof(HTTP_DATA_CHUNK));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pRawHttpResponse->EntityChunkCount = 0;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// since we clean the APR pool at the end of OnSendRequest, we must get IIS-managed memory chunk
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
void *reqbuf = pHttpContext->AllocateRequestMemory(length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
memcpy(reqbuf, buf, length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pDataChunk->DataChunkType = HttpDataChunkFromMemory;
|
|
Packit Service |
384592 |
pDataChunk->FromMemory.pBuffer = reqbuf;
|
|
Packit Service |
384592 |
pDataChunk->FromMemory.BufferLength = length;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
CHAR szLength[21]; //Max length for a 64 bit int is 20
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
ZeroMemory(szLength, sizeof(szLength));
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
HRESULT hr = StringCchPrintfA(
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
sizeof(szLength) / sizeof(CHAR) - 1, "%d",
|
|
Packit Service |
384592 |
length);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// not possible
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
hr = pHttpResponse->SetHeader(
|
|
Packit Service |
384592 |
HttpHeaderContentLength,
|
|
Packit Service |
384592 |
szLength,
|
|
Packit Service |
384592 |
(USHORT)strlen(szLength),
|
|
Packit Service |
384592 |
TRUE);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
if(FAILED(hr))
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// possible, but there's nothing we can do
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
pHttpResponse->WriteEntityChunkByReference(pDataChunk);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
return APR_SUCCESS;
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
CMyHttpModule::CMyHttpModule()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Open a handle to the Event Viewer.
|
|
Packit Service |
384592 |
m_hEventLog = RegisterEventSource( NULL, "ModSecurity" );
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
SYSTEM_INFO sysInfo;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
GetSystemInfo(&sysInfo);
|
|
Packit Service |
384592 |
m_dwPageSize = sysInfo.dwPageSize;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
this->status_call_already_sent = false;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
InitializeCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecSetLogHook(this, Log);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecSetReadBody(ReadBodyCallback);
|
|
Packit Service |
384592 |
modsecSetReadResponse(ReadResponseCallback);
|
|
Packit Service |
384592 |
modsecSetWriteBody(WriteBodyCallback);
|
|
Packit Service |
384592 |
modsecSetWriteResponse(WriteResponseCallback);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
server_rec *s = modsecInit();
|
|
Packit Service |
384592 |
char *compname = (char *)malloc(128);
|
|
Packit Service |
384592 |
DWORD size = 128;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
GetComputerName(compname, &size);
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
s->server_hostname = compname;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecStartConfig();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecFinalizeConfig();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
modsecInitProcess();
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
CMyHttpModule::~CMyHttpModule()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// ModSecurity registers APR pool cleanups, which interfere with APR pool tear down process
|
|
Packit Service |
384592 |
// this causes crashes and since we are exiting the process here, so this is a temporary solution
|
|
Packit Service |
384592 |
//
|
|
Packit Service |
384592 |
//modsecTerminate();
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
//WriteEventViewerLog("Module deleted.");
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
// Test whether the handle for the Event Viewer is open.
|
|
Packit Service |
384592 |
if (NULL != m_hEventLog)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Close the handle to the Event Viewer.
|
|
Packit Service |
384592 |
DeregisterEventSource( m_hEventLog );
|
|
Packit Service |
384592 |
m_hEventLog = NULL;
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
DeleteCriticalSection(&m_csLock);
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
void CMyHttpModule::Dispose()
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
|
|
Packit Service |
384592 |
BOOL CMyHttpModule::WriteEventViewerLog(LPCSTR szNotification, WORD category)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Test whether the handle for the Event Viewer is open.
|
|
Packit Service |
384592 |
if (NULL != m_hEventLog)
|
|
Packit Service |
384592 |
{
|
|
Packit Service |
384592 |
// Write any strings to the Event Viewer and return.
|
|
Packit Service |
384592 |
return ReportEvent(
|
|
Packit Service |
384592 |
m_hEventLog,
|
|
Packit Service |
384592 |
category, 0, 0x1,
|
|
Packit Service |
384592 |
NULL, 1, 0, &szNotification, NULL );
|
|
Packit Service |
384592 |
}
|
|
Packit Service |
384592 |
return FALSE;
|
|
Packit Service |
384592 |
}
|