mirror of
https://github.com/owasp-modsecurity/ModSecurity.git
synced 2025-08-14 13:56:01 +03:00
320 lines
19 KiB
HTML
320 lines
19 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" >
|
|
<head>
|
|
<title>Creating a Native Module for IIS7</title>
|
|
</head>
|
|
<body>
|
|
<h1>
|
|
Creating a Native Module for IIS7</h1>
|
|
<p>
|
|
To extend the server, IIS7 provides a new (C++) native core server API, which replaces
|
|
ISAPI filter and extension API from previous IIS releases. The new API features
|
|
object-oriented development with an intuitive object model, provides more control
|
|
over request processing, and uses simpler design patterns to help you write robust
|
|
code. Please visit <a target="_new" href="http://www.iis.net/default.aspx?tabid=2&subtabid=25&i=942">Developing a Native Module for IIS7</a> for more information about this sample.<br />
|
|
<br />
|
|
<strong>NOTE</strong>: The IIS7 native (C++) server API is declared in the Platform
|
|
SDK <strong>httpserv.h</strong> header file. <strong>You must obtain this SDK
|
|
and register it with Visual Studio in order to compile this module.</strong></p>
|
|
<p>
|
|
A native module is a Windows DLL that contains an the following:</p>
|
|
<ol>
|
|
<li><strong>RegisterModule</strong> exported function. This function is responsible
|
|
for creating a module factory, and registering the module for one or more server
|
|
events.<br />
|
|
<br />
|
|
<em>
|
|
This function is implemented in <strong>main.cpp</strong>.<br />
|
|
</em>
|
|
</li>
|
|
<li>Implementation of the module class inheriting from the <strong>CHttpModule</strong>
|
|
base class. This class is provides the main functionality of your module.
|
|
<br />
|
|
<br />
|
|
<em>
|
|
This class is declared in <strong>mymodule.h</strong>, with method implementations
|
|
in <strong>mymodule.cpp</strong>.<br />
|
|
</em>
|
|
</li>
|
|
<li>Implementation of the module factory class implementing the <strong>IHttpModuleFactory</strong>
|
|
interface. The class is responsible for creating instances of your module.<br />
|
|
<br />
|
|
<em>
|
|
This class is declared and implemented in <strong>mymodulefactory.h</strong>.</em></li></ol>
|
|
<h2>
|
|
0. Prerequisites</h2>
|
|
<p class="MsoNormal" style="margin: 0in 0in 0pt">
|
|
<span style="font-family: Verdana"><span style="font-size: 9pt">In order to compile
|
|
the module, you will need to install the Windows Platform SDK that contains the
|
|
required IIS header files.
|
|
<br />
|
|
<br />
|
|
After installing the SDK</span></span><span style="font-size: 9pt; font-family: Verdana;
|
|
mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: Arial; mso-ansi-language: EN-US;
|
|
mso-fareast-language: EN-US; mso-bidi-language: AR-SA">, you will need to register
|
|
the SDK with Visual Studio 2005.<span style="mso-spacerun: yes"> </span>You
|
|
can do this via <b style="mso-bidi-font-weight: normal">Start > Programs > Microsoft
|
|
Windows SDK > Visual Studio Registration > Register Windows SDK Directories
|
|
with Visual Studio</b>.</span></p>
|
|
<h2>
|
|
1. Implement RegisterModule entrypoint</h2>
|
|
<p>
|
|
A native module must export the RegisterModule function. This function will
|
|
be invoked by the server when the module DLL is loaded, so that your DLL can register
|
|
for the required server events, and provide a mechanism for the server to create
|
|
instances of your module class.<br />
|
|
<br />
|
|
<span style="font-size: 10pt; font-family: Courier New">__stdcall
|
|
<br />
|
|
HRESULT RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo
|
|
* pModuleInfo, IHttpServer * pHttpServer );<br />
|
|
</span>
|
|
<br />
|
|
<em>This function is implemented for you in the <strong>main.cpp</strong> source file.
|
|
</em>
|
|
<br />
|
|
<br />
|
|
It does the following:</p>
|
|
<ol>
|
|
<li><strong>Create module factory</strong>.<strong> </strong>This is an instance
|
|
of your CMyModuleFactory class that implements
|
|
the IHttpModuleFactory inteface:<br />
|
|
<br />
|
|
<span style="font-family: Courier New"><span style="font-size: 10pt"><span style="color: #009900">
|
|
// step 2: create module factory</span><br />
|
|
pFactory = new CMyHttpModuleFactory();</span></span><br />
|
|
</li>
|
|
<li><strong>Register module factory for desired server events</strong>. This registers
|
|
the module factory for one or more server events that occur during request processing.
|
|
The server will use the factory to create an instance of your module class for each
|
|
request, and call the appropriate event handler method on your module instance for
|
|
each of the requested events:<br />
|
|
<br />
|
|
<span style="color: #000000;"><span style="font-family: Courier New"><span style="font-size: 10pt">
|
|
<span style="color: #009900">
|
|
// step 3: register for server events
|
|
<br />
|
|
// TODO: register for more server events here
|
|
<br />
|
|
</span>hr = pModuleInfo->SetRequestNotifications( pFactory, </span></span><span
|
|
style="font-family: Courier New"><span style="font-size: 10pt"><span style="color: #009900">
|
|
/* module factory */
|
|
<br />
|
|
</span>
|
|
RQ_ACQUIRE_REQUEST_STATE,
|
|
<span style="color: #009900">/* server event mask */</span><br />
|
|
|
|
0 <span style="color: #009900">
|
|
/* server post event mask */</span> );<br />
|
|
<br />
|
|
<span style="font-size: 12pt; font-family: Times New Roman">
|
|
The server event mask is a bit mask of one or more request processing event names
|
|
declared in </span>
|
|
</span></span><span style="font-family: Courier New"><span style="font-size: 10pt">
|
|
<strong><span style="font-size: 12pt; font-family: Times New Roman">httpserv.h:</span><br />
|
|
<br />
|
|
</strong><span style="color: #009900">//
|
|
<br />
|
|
// Request deterministic notifications
|
|
<br />
|
|
//
|
|
<br />
|
|
<br />
|
|
// request is beginning </span>
|
|
<br />
|
|
#define RQ_BEGIN_REQUEST 0x00000001
|
|
<br />
|
|
<span style="color: #009900">// request is being authenticated
|
|
<br />
|
|
</span>#define RQ_AUTHENTICATE_REQUEST 0x00000002
|
|
<br />
|
|
<span style="color: #009900">// request is being authorized </span>
|
|
<br />
|
|
#define RQ_AUTHORIZE_REQUEST 0x00000004
|
|
<br />
|
|
<span style="color: #009900">// satisfy request from cache </span>
|
|
<br />
|
|
#define RQ_RESOLVE_REQUEST_CACHE 0x00000008
|
|
<br />
|
|
<span style="color: #009900">// map handler for request</span>
|
|
<br />
|
|
#define RQ_MAP_REQUEST_HANDLER 0x00000010
|
|
<br />
|
|
<span style="color: #009900">// acquire request state</span>
|
|
<br />
|
|
#define RQ_ACQUIRE_REQUEST_STATE 0x00000020
|
|
<br />
|
|
<span style="color: #009900">// pre-execute handler</span>
|
|
<br />
|
|
#define RQ_PRE_EXECUTE_REQUEST_HANDLER 0x00000040
|
|
<br />
|
|
<span style="color: #009900">// execute handler</span>
|
|
<br />
|
|
#define RQ_EXECUTE_REQUEST_HANDLER 0x00000080
|
|
<br />
|
|
<span style="color: #009900">// release request state</span>
|
|
<br />
|
|
#define RQ_RELEASE_REQUEST_STATE 0x00000100
|
|
<br />
|
|
<span style="color: #009900">// update cache</span>
|
|
<br />
|
|
#define RQ_UPDATE_REQUEST_CACHE 0x00000200
|
|
<br />
|
|
<span style="color: #009900">// log request</span>
|
|
<br />
|
|
#define RQ_LOG_REQUEST 0x00000400
|
|
<br />
|
|
<span style="color: #009900">// end request</span>
|
|
<br />
|
|
#define RQ_END_REQUEST 0x00000800
|
|
<br />
|
|
<br />
|
|
<span style="color: #009900">//
|
|
<br />
|
|
// Request non-deterministic notifications
|
|
<br />
|
|
//</span>
|
|
<br />
|
|
<br />
|
|
<span style="color: #009900">// custom notification</span>
|
|
<br />
|
|
#define RQ_CUSTOM_NOTIFICATION 0x10000000
|
|
<br />
|
|
<span style="color: #009900">// send response</span>
|
|
<br />
|
|
#define RQ_SEND_RESPONSE 0x20000000
|
|
<br />
|
|
<span style="color: #009900">// read entity</span>
|
|
<br />
|
|
#define RQ_READ_ENTITY 0x40000000
|
|
<br />
|
|
<span style="color: #009900">// map a url to a physical path</span>
|
|
<br />
|
|
#define RQ_MAP_PATH 0x80000000<br />
|
|
<br />
|
|
<span style="font-size: 12pt; font-family: Times New Roman">
|
|
The post event mask is a bit mask of the same events, allowing to subscribe
|
|
to the post events for each of the specified events.<br />
|
|
</span>
|
|
</span></span>
|
|
</span></li>
|
|
</ol>
|
|
<h2>
|
|
</h2>
|
|
<h2>
|
|
2. Implement module factory class</h2>
|
|
<p>
|
|
The server requires a module factory class in order to obtain instances of your
|
|
module. The factory class must implement the IHttpModuleFactory interface
|
|
declared in the httpserv.h Windows SDK header file.<br />
|
|
<br />
|
|
<em>This factory is implemented for you in the <strong>mymodulefactory.h</strong> header
|
|
file.<br />
|
|
<br />
|
|
</em>The <strong>GetHttpModule</strong> method of the factory class is called at the beginning of
|
|
each request in order to obtain an instance of your module. The typical implementation
|
|
simply returns a new instance of your module class:<br />
|
|
<br />
|
|
<span style="font-family: Courier New; font-size: 10pt;">class CMyHttpModuleFactory : public IHttpModuleFactory
|
|
<br />
|
|
{
|
|
<br />
|
|
public:
|
|
<br />
|
|
virtual HRESULT GetHttpModule( OUT CHttpModule **ppModule, IN IModuleAllocator
|
|
* )
|
|
<br />
|
|
{ <br />
|
|
...<br />
|
|
pModule = new CMyHttpModule(); <br />
|
|
...<br />
|
|
*ppModule = pModule; <br />
|
|
...<br />
|
|
} <br />
|
|
<br />
|
|
virtual void Terminate() { }<br />
|
|
}</span></p>
|
|
<p>
|
|
The <strong>Terminate</strong> method of the factory class is called during the
|
|
shutdown of the worker process, before your module DLL is unloaded. It typically
|
|
releases any resources you may have initialized inside the <strong>RegisterModule</strong>
|
|
function.</p>
|
|
<h2>
|
|
3. Implement module class</h2>
|
|
<p>
|
|
The module class inherits from the <strong>CHttpModule</strong> base class, which
|
|
defines an event handler method for each of the server events discussed earlier.
|
|
When the server executes each event during the processing of a request, it will
|
|
invoke the associated event handler method on each of the module instances that
|
|
have registered for that event. <br />
|
|
<br />
|
|
<em>This class is declared in the <strong>mymodule.h</strong> header file, and its event
|
|
handler methods are implemented in the <strong>mymodule.cpp</strong> source file.</em><br />
|
|
<br />
|
|
In order to provide processing for each server event, the module class MUST override
|
|
the corresponding method. The signature of each event handler method is the
|
|
following:<br />
|
|
<br />
|
|
<span style="font-size: 10pt; font-family: Courier New">REQUEST_NOTIFICATION_STATUS
|
|
On<EVENT NAME>(
|
|
IN IHttpContext * pHttpContext,
|
|
IN OUT IHttpEventProvider * pProvider
|
|
);
|
|
<br />
|
|
</span>
|
|
<br />
|
|
|
|
Where <EVENT NAME> is one of the server events we listed earlier. For
|
|
example, the module in this project initially overrides only the <strong>OnAcquireRequestState</strong> method since we register only for the <span style="font-size: 10pt;
|
|
font-family: Courier New"><strong>RQ_ACQUIRE_REQUEST_STATE</strong></span> event:<br />
|
|
<br />
|
|
<span style="font-size: 10pt; font-family: Courier New">class CMyHttpModule : public
|
|
CHttpModule
|
|
<br />
|
|
{
|
|
<br />
|
|
public:
|
|
<br />
|
|
<br />
|
|
<span style="color: #009900"> // Implementation of the AcquireRequestState
|
|
event handler method. </span>
|
|
<br />
|
|
REQUEST_NOTIFICATION_STATUS OnAcquireRequestState( IN IHttpContext
|
|
* pHttpContext, IN OUT IHttpEventProvider * pProvider );
|
|
<br />
|
|
<br />
|
|
<span style="color: #009900"> // TODO: override additional event handler
|
|
methods below. </span>
|
|
<br />
|
|
};</span><br />
|
|
<br />
|
|
The implementation of this method provides the module functionality desired for
|
|
processing the request in the appropriate pipeline stage. This project provides
|
|
a dummy implementation in the <strong>mymodule.cpp</strong> source file.</p>
|
|
<h2>
|
|
4. Deploy the module to the server</h2>
|
|
<p>
|
|
After you have compiled your module, you need to deploy it on the server.
|
|
You can do that by compiling the module, and then copying <strong>IIS7NativeModule.dll</strong>
|
|
(and the <strong>IIS7NativeModule.pdb</strong> debugging symbols file if desired)
|
|
to any location on the machine running IIS7.<br />
|
|
<br />
|
|
You can install your module on the server by running the following command from an Elevated command line prompt:<br />
|
|
<br />
|
|
<strong>%systemroot%\system32\inetsrv\APPCMD.EXE install module /name:MyModule /image:<FULL
|
|
PATH TO DLL></strong><br />
|
|
<br />
|
|
Where <strong><FULL_PATH_TO_DLL></strong> is the full path to the module DLL
|
|
file.<br />
|
|
<br />
|
|
You can also install your module using the IIS7 Administration Tool. After installation,
|
|
your module will be loaded and enabled in all application pools on the server.
|
|
To learn ore about installing modules, and selecting modules to execute on your
|
|
server and for specific applications, please visit <a href="http://www.iis.net">www.iis.net</a>.</p>
|
|
<h2>
|
|
Congratulations!</h2>
|
|
<p>
|
|
You have succesfully built and deployed your own IIS7 module. To learn more
|
|
about building IIS7 modules, and to download sample modules, be sure to visit <a href="http://www.iis.net">www.iis.net</a>.</p>
|
|
</body>
|
|
</html> |