Creating a ISA filter to replace - Pragma: no-cache - or Cache-Control: no-cache

 

Hello,

 

I'm writing this post to provide you with the basic information and an example in how to create a ISA Filter to replace the Pragma: no-cache - or Cache-Control: no-cache sent by client(IE, ActiveX etc...).

This filter was created by following the Example provided by David Treadwell on July 1997.

https://www.microsoft.com/downloads/details.aspx?familyid=16682c4f-7645-4279-97e4-9a0c73c5162e&displaylang=en

\Microsoft ISA 2006 SDK\samples\WebFilters\webresponsemodifier

I'm doing further testing regarding this filter, but this is a very good and simple startup.

However to develop or alter this filter you need some development skills.

I suggest you to read all the information available at:

https://msdn.microsoft.com/en-us/library/ms828061.aspx

The entry functions for the Filter are:

https://msdn.microsoft.com/en-us/library/ms812622.aspx

• GetFilterVersion

• HttpFilterProc

This means that for each http packet reaching ISA, the filter is called. The functions that are called are:GetFilterVersion and HttpFilterProc.

You need to be careful with what you write because you can stop Microsoft Firewall very easy.

This development should be made in lab environment and fully tested.

During the development I got the following errors caused by incorrect code.

Event Type: Error

Event Source: Microsoft ISA Server 2006

Event ID: 1000

Description:

Faulting application wspsrv.exe, version 5.0.5723.493, stamp 48623ea3, faulting module unknown, version 0.0.0.0, stamp 00000000, debug? 0, fault address 0x110e3b8e.

Event Type: Error

Event Source: Microsoft ISA Server Control

Event ID: 14079

Description:

Due to an unexpected error, the service fwsrv stopped responding to all requests. Stop the service or the corresponding process if it does not respond, and then start it again. Check for related error messages.

What does this example exactly does?

-> For all the request made to ISA and that reached the filter, We check if the website we are accessing is www.ola.com.

if it's www.ola.com I change the Pragma: no-cache - and Cache-Control: no-cache to Pragma: none - and Cache-Control: none.

So this will be ignored by ISA and the information will be cached.

-> All the debug information is being sent to the Debugger. So I suggest you to use DebugView from Sysinternals for troubleshooting purposes.

The function used to send the data to the debugger is:

OutputDebugStringA(LPCWSTR)

Lets go back to the main entry function:

DWORD WINAPI HttpFilterProc (

   PHTTP_FILTER_CONTEXT pfc,

   DWORD NotificationType,__inout

   LPVOID pvNotification)

The entry function HttpFilterProc has 3 arguments:

PHTTP_FILTER_CONTEXT pfc

Pointer to an HTTP_FILTER_CONTEXT structure that is associated with the current, active HTTP transaction

"The HTTP_FILTER_CONTEXT structure is used for passing control and information associated with the current, active HTTP session in event notifications that are sent by the ISA Server Web proxy to Web filters by calling HttpFilterProc and HttpWPXFilterProc."

https://msdn.microsoft.com/en-us/library/ms826756.aspx

DWORD NotificationType

Pointer to a bitmask that indicates the type of notification event that is being processed.

The NotificationType argument, this argument tells you in what situation the function was called.

I wanted to change the header when the information reached ISA for the first time so I believe that this happens when the NotificationType is SF_NOTIFY_PREPROC_HEADERS.

https://msdn.microsoft.com/en-us/library/ms812625.aspx

LPVOID pvNotification

Pointer to a notification-specific structure that contains additional information about the current context of the request. The following table shows the possible notification types and the corresponding structures.

So when you get this notification type the argument pvNotification that is a Void is used to create a catch to the structure of the type: HTTP_FILTER_PREPROC_HEADERS

HTTP_FILTER_PREPROC_HEADERS * pPPH;

pPPH = (HTTP_FILTER_PREPROC_HEADERS*)pvNotification;

Important: Each notification may need a specific catch to be used.

In my code I've:

DWORD WINAPI HttpFilterProc (

   PHTTP_FILTER_CONTEXT pfc,

   DWORD NotificationType,__inout

   LPVOID pvNotification

)

{

pfc->GetServerVariable(pfc,(LPSTR)String_HTTP_HOST,HTTP_HOST,&HTTP_HOST_LEN);

--> This is used to get the HTTP_HOST.

if(NotificationType == SF_NOTIFY_PREPROC_HEADERS && strcmp(HTTP_HOST,"www.ola.com")==0)

{

                -->We will only enter if the HTTP_HOST is www.ola.com and only when the notificationType is SF_NOTIFY_PREPROC_HEADERS.

                --> We then do a catch from the pvNotification to the correct Structure HTTP_FILTER_PREPROC_HEADERS.

                --> These structure included a pointer to the SetHeader function and we can use it.

HTTP_FILTER_PREPROC_HEADERS * pPPH;

                                BOOL fResult;

               

                                pPPH = (HTTP_FILTER_PREPROC_HEADERS*)pvNotification;

                                               

                                fResult = pPPH->SetHeader( pfc, "Cache-Control:", "None" );

                                fResult = pPPH->SetHeader( pfc, "Pragma:", "None" );

                               

}

One more note if you compile the code provided in the SDK you will get Firewall stopped in the first HTTP access with error: 0x80070057

BOOL WINAPI GetFilterVersion ( PHTTP_FILTER_VERSION pVer ){………………………………………………………………………pVer->dwFilterVersion = MAKELONG(0,6);}

I hope this helps.

Best regards to all.

Mywebresponsemodifier.rar