📄 isapiflt.cpp
字号:
CHAR lpvBuffer[256];
urlMap.cbPathBuff = sizeof(lpvBuffer);
strncpy( lpvBuffer, urlMap.pszPhysicalPath, strlen(urlMap.pszPhysicalPath) + 1);
urlMap.pszPhysicalPath = lpvBuffer;
};
/* ---
Authentication phase mapped to SF_NOTIFY_AUTHENTICATION
--- */
if ( !nType && ( iPhase == PH_CHECKAUTH ) && ( pContext->tVer.dwFlags & SF_NOTIFY_AUTHENTICATION )
// don't notify internal redirects again!
&& ( pPIHTTP->iStatus != ST_UNAUTHORIZED ))
{
CHAR lpvUserBuff[SF_MAX_USERNAME] = "";
CHAR lpvPasswBuff[SF_MAX_PASSWORD] = "";
/*
** Get browser authentication string
*/
const char *pAuthenticate = (const char *)PIDB_lookup(
pPIHTTP->pRequestDB, PIDBTYPE_RFC822, KEY_HTTP_AUTHORIZATION, 0 );
if ( pAuthenticate )
{
/*
** Check authentication string
*/
if ( !strncmp( pAuthenticate, "Basic ", 6 ) )
{
/*
** Check to see if this is an acceptable base64 encoding
*/
const char *pBase64 = &( pAuthenticate[6] );
CHAR auth[256];
Base64Decode( pBase64, auth, sizeof( auth ));
char *tok = strtok( auth, ":" );
if ( tok != NULL )
{
strncpy( lpvUserBuff, tok, strlen(tok) + 1);
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING,
KEY_INT_REMOTEUSER, tok, 0 );
tok = strtok( NULL, ":" );
if ( tok != NULL )
{
strncpy( lpvPasswBuff, tok, strlen(tok) + 1);
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING,
KEY_INT_AUTHPASS, tok, 0 );
};
};
};
};
nType = SF_NOTIFY_AUTHENTICATION;
HTTP_FILTER_AUTHENT Auth;
pvNotification = &Auth;
Auth.cbUserBuff = sizeof(lpvUserBuff);
Auth.pszUser = lpvUserBuff;
Auth.cbPasswordBuff = sizeof(lpvPasswBuff);
Auth.pszPassword = lpvPasswBuff;
};
/* ---
CheckPath phase mapped to SF_NOTIFY_ACCESS_DENIED if HTTP state is 401 || 403
--- */
if ( !nType && ( iPhase == PH_CHECKPATH ) && (( pPIHTTP->iStatus == ST_UNAUTHORIZED ) || ( pPIHTTP->iStatus == ST_FORBIDDEN ))
&& ( pContext->tVer.dwFlags & SF_NOTIFY_ACCESS_DENIED ))
{
nType = SF_NOTIFY_ACCESS_DENIED;
HTTP_FILTER_ACCESS_DENIED Accs;
pvNotification = &Accs;
Accs.pszURL = (const char *)PIDB_lookup( pPIHTTP->pRequestDB,
PIDBTYPE_STRING, KEY_HTTP_URI, 0 );
/*
** if Status is 403, the original path is stored in KEY_INT_OLDPATH
*/
if ( pPIHTTP->iStatus == ST_FORBIDDEN )
{
PIDB_getFastKey( KEY_INT_OLDPATH, PIDBTYPE_STRING );
}
else
{
PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING );
};
Accs.pszPhysicalPath = (const char *)PIDB_lookup( pPIHTTP->pResponseDB,
PIDBTYPE_STRING, pFKPath, PIDBFLAG_FASTKEY );
Accs.dwReason = ( pPIHTTP->iStatus == ST_UNAUTHORIZED ) ? SF_DENIED_LOGON : SF_DENIED_RESOURCE;
};
/* ---
Handle phase mapped to SF_NOTIFY_SEND_RESPONSE
--- */
/* Not implemented in filter version 2.1
if ( !nType && ( iPhase == PH_HANDLE ) && ( pContext->tVer.dwFlags & SF_NOTIFY_SEND_RESPONSE ))
{
nType = SF_NOTIFY_SEND_RESPONSE;
HTTP_FILTER_SEND_RESPONSE Resp;
pvNotification = &Resp;
Resp.GetHeader = fnGetHeader;
Resp.SetHeader = fnSetHeader;
Resp.AddHeader = fnAddHeader;
Resp.HttpStatus = pPIHTTP->iStatus;
};
*/
/* ---
Log phase mapped to SF_NOTIFY_LOG
--- */
if ( !nType && ( iPhase == PH_LOG ) && ( pContext->tVer.dwFlags & SF_NOTIFY_LOG ))
{
nType = SF_NOTIFY_LOG;
HTTP_FILTER_LOG Log;
pvNotification = &Log;
Log.pszClientHostName = (const char *)PIDB_lookup( pPIHTTP->pConnectionDB, PIDBTYPE_STRING, KEY_INT_REMOTEHOST, 0 );
Log.pszClientUserName = (const char *)PIDB_lookup( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_REMOTEUSER, 0 );
Log.pszServerName = (const char *)PIDB_lookup( pPIHTTP->pHostDB, PIDBTYPE_RFC822, KEY_INT_HOSTNAME, 0 );
Log.pszOperation = (const char *)PIDB_lookup( pPIHTTP->pRequestDB, PIDBTYPE_STRING, KEY_HTTP_METHOD, 0 );
Log.pszTarget = (const char *)PIDB_lookup( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_SCRIPTNAME, 0 );
Log.pszParameters = (const char *)PIDB_lookup( pPIHTTP->pRequestDB, PIDBTYPE_STRING, KEY_HTTP_QUERYSTRING, 0 );
Log.dwHttpStatus = pPIHTTP->iStatus;
Log.dwWin32Status = ::GetLastError();
/* ---
Not implemented in filter version 2.1
--- */
// Log.dwBytesSent = pPIHTTP->GetIOBuffer().GetBytesSent();
// Log.dwBytesRecvd = 0;
// long lSeconds;
// long lMicroSeconds;
// PITimer_elapsed( pPIHTTP->pTimer, &lSeconds, &lMicroSeconds );
// Log.msTimeForProcessing = ( 1000 * lSeconds ) + (lMicroSeconds % 1000 ));
};
/* ---
Nothing to do!
--- */
if ( !nType ) return FALSE;
/* ---
Fire off filter function
--- */
iFilterRet = (fnHttpFilterProc)( pContext, nType, pvNotification );
/* ---
Post processing for handled notifications
--- */
/*
** Change the physical path for phase PH_MAPPING
*/
if (( iPhase == PH_MAPPING ) && ( pContext->tVer.dwFlags & SF_NOTIFY_URL_MAP )
&& ( iFilterRet != SF_STATUS_REQ_ERROR ))
{
const char *pFKPath = PIDB_getFastKey( KEY_INT_PATH, PIDBTYPE_STRING );
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, pFKPath,
((HTTP_FILTER_URL_MAP *)pvNotification)->pszPhysicalPath,
PIDBFLAG_FASTKEY );
};
/*
** Change the authentication uid/pwd in the DB
*/
if (( iPhase == PH_CHECKAUTH ) && ( pContext->tVer.dwFlags & SF_NOTIFY_AUTHENTICATION ))
{
if (( iFilterRet != SF_STATUS_REQ_ERROR ) && ( (DWORD)::GetLastError() != ERROR_ACCESS_DENIED ))
{
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_REMOTEUSER,
((HTTP_FILTER_AUTHENT *)pvNotification)->pszUser, 0 );
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHPASS,
((HTTP_FILTER_AUTHENT *)pvNotification)->pszPassword, 0 );
/*
** If we have finished, try to logon (WindowsNT only)
*/
if ( iFilterRet == SF_STATUS_REQ_HANDLED_NOTIFICATION )
{
/*
** parameter not set or already authenticated
*/
if (!iSystemLogon || pContext->hToken)
{
iResult = PIAPI_COMPLETED;
return pContext->iRc;
};
OSVERSIONINFO VerInfo;
VerInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
// If this fails, something has gone wrong
if ( !GetVersionEx( &VerInfo )) { return PIAPI_ERROR; }
if ( VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
{
if (LogonUser(((HTTP_FILTER_AUTHENT *)pvNotification)->pszUser,
NULL, // lpszDomain
((HTTP_FILTER_AUTHENT *)pvNotification)->pszPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&pContext->hToken ))
{
// If this fails, something has gone wrong
if (!ImpersonateLoggedOnUser( pContext->hToken ))
{
return PIAPI_ERROR;
}
/*
** authenticated and impersonated
*/
iResult = PIAPI_COMPLETED;
return pContext->iRc;
}
}
}
}
else
{
if ((DWORD)::GetLastError() != ERROR_ACCESS_DENIED ) { return PIAPI_ERROR; }
}
/*
** authentication challenge (Basic)
*/
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_STRING, KEY_INT_AUTHTYPE, "Basic", 0 );
const char *pRealm = (const char *)PIDB_lookup( pPIHTTP->pResponseDB,
PIDBTYPE_STRING, KEY_INT_AUTHENTICATIONREALM, 0 );
if (!pRealm) pRealm="default";
char *pAuth = (char *)PIHTTP_allocMem( pPIHTTP, sizeof( "Basic realm=\"\"" )
+ strlen( pRealm ) + 1 );
sprintf( pAuth, "Basic realm=\"%s\"", pRealm );
PIDB_replace( pPIHTTP->pResponseDB, PIDBTYPE_RFC822,
KEY_HTTP_WWW_AUTHENTICATE, pAuth, 0 );
/*
** Redirect because of authentication failure
*/
iResult = HTTPUtil_doHTTPError( pPIHTTP, ST_UNAUTHORIZED );
return pContext->iRc;
};
/*
** if ServerSupportFunction added any extra header
** requested with SF_REQ_ADD_HEADERS_ON_DENIAL
*/
if (( iPhase == PH_CHECKPATH ) && (( pPIHTTP->iStatus == ST_UNAUTHORIZED )
|| ( pPIHTTP->iStatus == ST_FORBIDDEN )) && pContext->pszHeaders )
{
char *pszValue;
char *pszName = strtok( (char *)pContext->pszHeaders, ":" );
while ( pszName )
{
// search for space but also remove CRLF
pszValue = strtok( NULL, "\r\n ");
if ( !(pszName && pszValue) )
{
break;
};
PIDB_add( pPIHTTP->pResponseDB, PIDBTYPE_RFC822, pszName, pszValue, 0 );
// search for double quota but also remove CRLF
pszName = strtok( NULL, "\r\n:" );
};
};
/* ---
Status/Error handling
--- */
switch( iFilterRet )
{
case SF_STATUS_REQ_FINISHED:
/*
** Assume Content-Length could not be set, disable keep open
*/
PIDB_replace( pPIHTTP->pConnectionDB, PIDBTYPE_OPAQUE, KEY_INT_KEEPOPEN, 0, 0 );
pPIHTTP->iStatus = ST_OK;
break;
case SF_STATUS_REQ_FINISHED_KEEP_CONN:
/*
** OK
*/
pPIHTTP->iStatus = ST_OK;
break;
case SF_STATUS_REQ_NEXT_NOTIFICATION:
/*
** OK
*/
break;
case SF_STATUS_REQ_HANDLED_NOTIFICATION:
/*
** OK
*/
iResult = PIAPI_COMPLETED;
break;
case SF_STATUS_REQ_READ_NEXT:
/*
** OK
*/
break;
case SF_STATUS_REQ_ERROR:
default:
pPIHTTP->iStatus = ST_INTERNALERROR;
HTTPCore_logError( pPIHTTP, "ISAPIFLT: ISAPI filter \
'%s' returned SF_STATUS_REQ_ERROR or an unknown return code.", pPath );
};
return pContext->iRc;
};
/* ---
The entry point ...
--- */
int Handle( int iPhase, PIHTTP &tPIHTTP, PIIOBuffer &tB/* tBuffer */ )
{
/*
** The result for this phase depends on preconfigured values
*/
iResult = ( aPhaseMap[iPhase] & iOptions ) ? PIAPI_COMPLETED : PIAPI_CONTINUE;
/*
** Only handle the request if the condition is TRUE
*/
if ( pCondition && !Pi3Expression_write( pCondition, &tPIHTTP, 0, 0, 0 )) return iResult;
int iFilterErr = FALSE;
/*
** Retrieve ISAPI context ...
*/
ISAPIContext *pContext = (ISAPIContext *)PIDB_lookup( tPIHTTP.pConnectionDB,
PIDBTYPE_OPAQUE, pfkIsapiContext, PIDBFLAG_FASTKEY );
/*
** ... or create a new one
*/
if ( !pContext )
{
pContext = new ISAPIContext( this, &tPIHTTP, tVer );
PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, pfkIsapiContext,
(void *)pContext, PIDBFLAG_FASTKEY );
};
/*
** Only handle the request if the current status is a non-error status
*/
if (( !tPIHTTP.iStatus ) || ( tPIHTTP.iStatus == ST_OK )
/* --- Exception: 401, 403 are notified by ISAPI filters! --- */
|| ( tPIHTTP.iStatus == ST_UNAUTHORIZED ) || ( tPIHTTP.iStatus == ST_FORBIDDEN ))
{
/* --- OK, do the filter DLL processing --- */
iFilterErr = RunISAPI( &tPIHTTP, iPhase, pContext );
};
/*
** pContext - explicite destruction
*/
if (( iPhase == PH_DESTROY ) && pContext )
{
delete pContext;
pContext = NULL;
PIDB_replace( tPIHTTP.pConnectionDB, PIDBTYPE_OPAQUE, pfkIsapiContext,
(void *)pContext, PIDBFLAG_FASTKEY);
};
/*
** an error is occured
*/
if ( iFilterErr )
{
HTTPCore_logError( &tPIHTTP, "ISAPIFLT: Call to 'HttpFilterProc' \
failed for ISAPI DLL '%s'. Win32 Error code is %d.", pPath , ::GetLastError() );
return HTTPUtil_doHTTPError( &tPIHTTP, ST_INTERNALERROR );
}
else return iResult;
};
/* ---
Used by the callback function with the same name
--- */
BOOL GetServerVariable( PIHTTP *pPIHTTP, LPSTR lpszVariableName,
LPVOID lpvBuffer, LPDWORD lpdwSize, ISAPIContext *pContext )
{
if ( !lpszVariableName || !lpdwSize )
{
::SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
};
/* ---
Convert variable to upper case
--- */
PIString sTmp( lpszVariableName );
sTmp.ConvertToUpperCase();
Pi3Expression *pExpr = (Pi3Expression *)PIDB_lookup(pTypes, PIDBTYPE_OPAQUE,
(const char *)sTmp, 0);
if (pExpr)
{
UINT iWritten = Pi3Expression_write( pExpr, pPIHTTP, pContext, (char *)lpvBuffer,
*lpdwSize );
if ( iWritten==-1 )
{
*lpdwSize = 0;
::SetLastError( ERROR_INVALID_INDEX );
return 0;
}
/*
** Skip empty variable fields, this allows an environment
** variable to be added conditionally
*/
if ( iWritten>=0 )
{
if ( iWritten>=*lpdwSize )
{
*lpdwSize = iWritten;
::SetLastError( ERROR_INSUFFICIENT_BUFFER );
return 0;
};
((char *)lpvBuffer)[iWritten] = '\0';
*lpdwSize = iWritten;
return 1;
};
}
/* --- no variable found, try to find an extra header --- */
if ( iExtraHeaders )
{
PIDB *pQ = pPIHTTP->pRequestDB;
/* --- loop over all RFC822 headers in request block --- */
PIDBIterator *pIter = PIDB_getIterator( pQ, PIDBTYPE_RFC822, 0, 0 );
if ( !pIter ) { return 0; }
const char *pKey;
const char *pValue;
for(; PIDBIterator_atValidElement( pIter ); PIDBIterator_next( pIter ) )
{
pValue = (const char *)PIDBIterator_current( pIter, &pKey );
assert( pKey && pValue );
if ( !pKey || !pValue ) { /* sanity */ continue; };
if (checkIgnoreList(pKey)) continue;
PIString sTest(sExtraHeadersPrefix);
sTest.Concatenate(pKey);
char *pBuf = (char *)(const char *)sTest;
for( int i=0; i<sTest.Len(); i++ )
{
if ( isalnum( pBuf[i] ) )
{ pBuf[i]=toupper(pBuf[i]); }
else
{ pBuf[i]='_'; };
}
if (!PIUtil_stricmp((const char *)sTest, (const char *)sTmp))
{
strncpy((char *)lpvBuffer, pValue, strlen(pValue));
*lpdwSize = strlen(pValue);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -