PRB: ISAPI Filter AuthFilt Sample Causes Access Violation (239738)



The information in this article applies to:

  • Microsoft Internet Information Server 4.0
  • Microsoft Internet Information Services 5.0
  • Microsoft Internet Information Services version 5.1

This article was previously published under Q239738

SYMPTOMS

The Microsoft Internet Information Server SDK contains an Internet Server Application Programming Interface (ISAPI) AuthFilt filter sample in the \InterPub\Iissamples\Sdk\Isapi\Filters\AuthFilt folder. When you use the AuthFilt sample directly, an access violation occurs.

CAUSE

The AuthFilt sample allocates a buffer on the SF_NOTIFY_AUTHENTICATION notification with AllocMem:
pfc->pFilterContext = pfc->AllocMem( pfc, 2 * SF_MAX_USERNAME + 4, 0 );
				
Then, the AuthFilt sample has string concatenations within the SF_NOTIFY_LOG event:
pch  = pfc->pFilterContext;
pLog = (HTTP_FILTER_LOG *) pvData;

strcat( pch, " (" );
strcat( pch, pLog->pszClientUserName );
strcat( pch, ")" );
				
NOTE: Multiple requests occur on the same network session if the connection is keep-alive (authentication occurs only once per session). The filter is called multiple times in the SF_NOTIFY_LOG event within the same session. Because the pFilterContext buffer is maintained for the entire session, having a fixed size of 2 * SF_MAX_USERNAME + 4, an access violation occurs.

RESOLUTION

To work around this behavior, perform the following:
  1. Define a struct:
    typedef struct
    {
        int	iLength;
        CHAR szUsername[ 2 * SF_MAX_USERNAME + 4 ];
    } USERID;
    					
  2. Define a new pointer at the beginning of the HttpFilterProc function:
    USERID *   pUser;
    					
  3. Allocate a buffer to store the unmapped username and its length in SF_NOTIFY_AUTHENTICATION:
    if ( !pfc->pFilterContext )
    {
       pfc->pFilterContext = pfc->AllocMem( pfc, sizeof ( USERID ), 0 );
       if ( !pfc->pFilterContext )
       {
          SetLastError( ERROR_NOT_ENOUGH_MEMORY );
          return SF_STATUS_REQ_ERROR;
       }
    }
    pUser = pfc->pFilterContext;
    strcpy(pUser->szUsername, achUser );
    pUser->iLength = strlen ( achUser );
    
    return SF_STATUS_REQ_HANDLED_NOTIFICATION;
    					
  4. In the SF_NOTIFY_LOG event, set a NULL char at the end of the unmapped username. (This allows the strcat to append the mapped username to the unmapped username.)
    if ( pfc->pFilterContext )
    {
       pUser = pfc->pFilterContext;
       pUser->szUsername [ pUser->iLength ] = 0;
    
       pch  =  pUser->szUsername;
       pLog = ( HTTP_FILTER_LOG* ) pvData;
    
       strcat( pch, " (" );
       strcat( pch, pLog->pszClientUserName );
       strcat( pch, ")" );
    
       pLog->pszClientUserName = pch;
    }
    					

MORE INFORMATION

There is an unrelated problem in the AuthFilt sample. The AuthFilt sample is called with a non-NULL lpvContext to terminate the cache and the user database on the case of DLL_PROCESS_DETACH in the DllMain. Because ISAPI is unloaded with the FreeLibrary, lpvContext is a non-NULL for ISAPI and the cache and the user database are not cleaned up at all.
BOOL
WINAPI
DllMain(
     IN HINSTANCE hinstDll,
     IN DWORD     fdwReason,
     IN LPVOID    lpvContext OPTIONAL
     )
{
    BOOL fReturn = TRUE;

    switch (fdwReason )
    {
    case DLL_PROCESS_ATTACH:
	...
	break;

    case DLL_PROCESS_DETACH:
        {
            if ( lpvContext != NULL)
            {
                 TerminateCache();
                 TerminateUserDatabase();            
            }

           break;
        } /* case DLL_PROCESS_DETACH */ 

    default:
        break;
    }   /* switch */ 

    return ( fReturn );
}  /* DllLibMain() */ 
				
Remove the "if ( lpvContext != NULL)" statement on the case of DLL_PROCESS_DETACH in DllMain so that the cache and the user database terminate when the filter is unloaded.

Modification Type:MajorLast Reviewed:6/29/2004
Keywords:kbFilter kbprb KB239738