Click here to Skip to main content
15,881,424 members
Articles / Desktop Programming / MFC
Article

ISAPI Filter for Logging using MFC

Rate me:
Please Sign up or sign in to vote.
4.50/5 (4 votes)
9 Aug 20079 min read 52K   590   20   5
Implementing ISAPI Filter in IIS 5.x/6.x for logging HTTP/HTTPS request & response data
Screenshot - 0.gif

Introduction

Having worked with ISAPI Filter (Internet Server Application Programming Interface Filter) for more than a couple of months, I would like to share my experience through the development of such filters from scratch. I believe this would be a good startup tutorial for beginners who wish to work in ISAPI filters.

I would like to walkthrough the path of developing an ISAPI filter for logging all the request and response data to/from IIS. I would be using the MFC framework to get the skeleton of an ISAPI filter, which has the advantage of tight coupling combined with the IIS, as well as an ease of programming compared to the standard STL. I would be focusing on IIS 5.x and IIS 6.x for the development of ISAPI filter. I would also be writing in my next article how to develop such filters using the .NET framework with the help of HTTPModule. Though HTTPModule can be conceptually used to simulate the ISAPI filter functionality, it can only be plugged into a .NET based web applications. Other request/response to non- .NET based web applications (e.g. ASP, CFM, HTML pages) will not be incepted using the HTTPModule. But I guess this would be possible in the future version of IIS (IIS 7.0).

Ok, here we go…

First, let's see some basic concepts of ISAPI Filters.

Concepts

An ISAPI filter is a replaceable dynamic-link library (DLL) that the server calls on every HTTP(S) (Hypertext Transfer Protocol) request/response. When the filter is loaded, it tells the server what sort of notifications it is interested in. After that, whenever the selected events occur in IIS, the filter is called and given the opportunity to process that event. Some of the common functions/situation for which ISAPI filters used are,

  • Custom authentication schemes
  • Compression
  • Encryption
  • Logging
  • Traffic analysis or other request analysis (e.g. Looking for requests to "..\..\etc\password")

Multiple filters can be installed on a single web site in IIS or globally to all web sites present in that IIS. The notification order is based on the priority specified by the filter and the load order in the registry for any ties. Note that once a filter has expressed interest in a request/response, it will receive that data regardless of whether the request/response is for a file, a CGI (Common Gateway Interface, a common HTTP server extension) application, or an ISAPI application.

ISAPI filters can be used to enhance the Microsoft Internet Information Server with custom features such as enhanced logging of HTTP requests/responses, custom encryption, and compression schemes, or new authentication methods. The filter applications sit between the network connection to the clients and the HTTP server. Depending on the options that the filter application chooses, it can act on several server actions, including reading raw data from the client, processing the headers, communications over a secure port (PCT - Private Communication Technology, SSL - Secure Sockets Layer, and so on), or several other stages in the processing of the HTTP request/response.

The setup program that installs the ISAPI filter should add it to the registry under HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\W3Svc\Parameters\Filter DLLs. This value is a comma-separated list. The filter should be added to the end of the list. When uninstalling the filter, remove the string that you added, taking care to handle the situation where other ISAPI filters have been added or removed since your DLL was installed.

Building an ISAPI Filter

An ISAPI filter can easily be built using Microsoft Visual Studio 6. A few easy clicks on MS VS6 produces a skeleton code of an empty ISAPI filter. First, open Microsoft Visual C++ of MS VS6. Open an ISAPI Extension Wizard at File>New>Projects, specifying a project name and location. Here I enter the project name as TryISAPI on the default location (C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\MYPROJECTS\TryISAPI).

Screenshot - 1.jpg

As we're trying to build an ISAPI filter, select "Generate Filter Object" and deselect "Generate Server Extension Object". Change the filter class name and description if needed, else leave it in its default. Also select to build as a "a Shared DLL" for "How would you like to use the MFC library?"

Screenshot - 2.jpg

On the second step, select the notification priority of the filter, the types of port that you're interested in, and the notifications that you need. Here, as we're trying to build a logging filter which would log all the request and response data of HTTP and HTTPS connections, I've subscribed to the "Incoming raw data and headers", "Outgoing raw data and headers" and "Post-processing of the request headers" notifications and set the notification priority to low which is the default.

Screenshot - 3.jpg

That's it. When you finish it, you would get the skeleton of an empty simple ISAPI filter.

When you go through the CPP file (TryISAPI.cpp), you would find some of the important methods,

  • GetFilterVersion
  • OnPreprocHeaders
  • OnReadRawData
  • OnSendRawData

The GetFilterVersion method would be called by the IIS while loading this ISAPI filter for setting up the necessary flags, the notifications, and its priority. The flags that can be set here are:

  • SF_NOTIFY_READ_RAW_DATA flag is set to subscribe for the notification which is triggered when the IIS reads the request data when the IIS receives a HTTP(S) request.
  • SF_NOTIFY_PREPROC_HEADERS flag is set to subscribe for the notification which is triggered by the IIS processes the request headers for the incoming HTTP(S) request from the client.
  • SF_NOTIFY_SEND_RAW_DATA flag is set to subscribe for the notification which is triggered when the IIS sends the response data to the client after processing the request.
  • SF_NOTIFY_AUTHENTICATION flag is set to subscribe for the notification which is triggered by the IIS when it authenticates any HTTP(S) requests.
  • SF_NOTIFY_URL_MAP flag is set to subscribe for the notification which is triggered by the IIS maps the URL to the physical location. When the IIS encounters a HTTP(S) request, it translates the virtual address of the URL to the physical address/location. A notification is triggered when this translation takes when this flag is set.
  • SF_NOTIFY_LOG flag is set to subscribe for the notification which is triggered when the IIS begins to log the request in IIS log.
  • SF_NOTIFY_END_OF_NET_SESSION flag is set to subscribe for the notification which is triggered by the IIS when any client session terminates.
  • SF_NOTIFY_ORDER_LOW flag is used to set the priority of the filter and notifications to low. This is the default setting in MS VS6.
  • SF_NOTIFY_ORDER_MEDIUM flag is used to set the priority of the filter and notifications to medium.
  • SF_NOTIFY_ORDER_HIGH flag is used to set the priority of the filter and notifications to high.
  • SF_NOTIFY_SECURE_PORT flag is set to subscribe for the notification which is triggered by the IIS encounters any HTTP(S) request or response on the secure port. (e.g. 443 for SSL in case of HTTPS)
  • SF_NOTIFY_NONSECURE_PORT flag is set to subscribe for the notification which is triggered by the IIS encounters any HTTP request or response on the non-secure port. (E.g. 80 in case of HTTP)

Here, since we're developing an ISAPI filter of low priority for logging the HTTP & HTTPS request & response data, you would see only some of flags set in GetFilterVersion method.

pVer->dwFlags |= 
SF_NOTIFY_ORDER_LOW|SF_NOTIFY_SECURE_PORT|SF_NOTIFY_NONSECURE_PORT|
SF_NOTIFY_PREPROC_HEADERS|SF_NOTIFY_READ_RAW_DATA|SF_NOTIFY_SEND_RAW_DATA;

Considerations

SF_NOTIFY_READ_RAW_DATA and SF_NOTIFY_SEND_RAW_DATA flags/notifications can be used in the ISAPI filter only when the filter is installed as a global filter in IIS for all web sites and NOT to a specific web site. I would be dealing with installation and un-installation of an ISAPI filter at the end of this article. Also in case of IIS 6.x, in order to use these two notifications/flags, the IIS should be configured to run in "IIS 5.0 Isolation Mode".

In order to configure IIS 6.x in "IIS 5.0 Isolation Mode",

  • Open "Internet Information Services (IIS) Manager". (Goto Start>Run, type inetmgr and say OK)
  • Expand the node with machine name to see the node "Web Sites". Right click and say "Properties"
  • In the "Web Sites Properties", got to "Service" tab and check "Run WWW service in IIS 5.0 Isolation Mode"
Screenshot - 4.jpg

The OnReadRawData method is that which is called by the IIS while reading the raw data of the incoming client request. Since this notification is triggered before SF_NOTIFY_PREPROC_HEADERS notification, we would read and the store the raw data in a global static buffer (CString strRequestRawData).

C++
char *Data;
Data = (char *) pRawData->pvInData;    
strRequestRawData = Data;
return SF_STATUS_REQ_NEXT_NOTIFICATION;

The OnPreprocHeaders method is that which is called when the IIS processes the header information of the HTTP(S) requests. So, here we'll be extracting header information such as client IP address, URL and request type (e.g. GET, POST). We would be logging this information and the request raw data into a file.

C++
// Reading client URL
pHeaderInfo->GetHeader(pCtxt->m_pFC, "url", buffer, &buffsize)
   strURL = buffer;

// Reading client IP address
pCtxt->GetServerVariable("REMOTE_ADDR", buffer, &buffsize)
   strIP = buffer;

// Reading request type
pCtxt->GetServerVariable("REQUEST_METHOD", buffer, &buffsize)
   strCmd = buffer;

where buffer is char buffer[4096] and strURL, strIP, strCmd are global static CString.

The OnSendRawData method would be called by the IIS when it sends the response data to the client after it has finished its processing. Here, we would be extracting the response raw data and writing into the file.

C++
// Reading response raw data
CString strResponseRawData;
strResponseRawData.Format("%s", pRawData->pvInData);

Creating, writing and closing a file can be achieved as follows.

C++
// Creating the log file
CFile LogFile;
char *cpFileName = (char *)(LPCTSTR)strFileName;
LogFile.Open(cpFileName, CFile::modeCreate | 
    CFile::modeNoTruncate |CFile::modeWrite | CFile::shareDenyWrite, NULL);

// Writing to the log file
LogFile.Write(strURL, strURL.GetLength());

// Closing the log file
LogFile.Close();

Installation and Un-Installation of ISAPI Filter

ISAPI filter can be installed for a particular web site or as a global filter for all web sites in the IIS. I would be guiding through the process of installing the ISAPI filter in IIS 6.x through this process, which is similar in IIS 5.x (with minor changes).

In order to install the ISAPI filter in IIS 6.0 as a global filter for all web sites present in the IIS,

  • Open "Internet Information Services (IIS) Manager"
  • Expand the node with machine name to see the node "Web Sites". Right click and say "Properties". To install to a particular web site, go to the properties of that web sites.
  • In the "Web Sites Properties", got to "ISAPI Filters" tab and add the ISAPI filter DLL (TryISAPI.dll) specifying the filter name and the physical location.
Screenshot - 5.jpg Screenshot - 6.jpg

You can also modify the order in which the ISAPI filters are executed if there are more than one registered filters by moving any registered filter up/down using the "Move Up" or "Move Down" buttons here.

In order to remove an ISAPI filter from IIS, select the filter in the "ISAPI Filters" tab and click "Remove"

History

August 03, 2007 - Baseline (Version 1.0)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Technical Lead HCL Technologies
India India
Paramesh Gunasekaran is currently working as a Software Engineer in HCL Technologies, India. He obtained his Bachelor's degree in Information Technology from Anna University, India. His research areas include Computational Biology, Artificial Neural Networks and Network Engineering. He has also received international acclaim for authoring industry papers in these areas. He is a Microsoft Certified Professional in ASP.NET/C# and has also been working in .NET technologies for more than 8 years.

Web: http://www.paramg.com

Comments and Discussions

 
QuestionHow does it behave in HTTPS? Pin
Ravishankar MN17-Jul-09 23:47
Ravishankar MN17-Jul-09 23:47 
QuestionCan we get the POST details in ISAPI Filter? Pin
Ravishankar MN17-Jul-09 23:44
Ravishankar MN17-Jul-09 23:44 
Generalinstall problem Pin
caall18-Nov-07 23:53
caall18-Nov-07 23:53 
On XP development machine the filter works good but when I try to install on a 2003 Server I cannot load neither register filter DLL. It seems that it depends to several others dll like mfc71.dll and msvcr71.dll and more. Why?
I don't want to install other component on the server so how can I do?
Is it possible to use a different and less invasive method to create the isapi filter?
Thank you.

QuestionA newbie query Pin
NovaNuker4-Nov-07 18:26
NovaNuker4-Nov-07 18:26 
AnswerRe: A newbie query Pin
Paramesh Gunasekaran6-Nov-07 19:48
Paramesh Gunasekaran6-Nov-07 19:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.