📄 filters.cpp
字号:
pLog->dwHttpStatus = rgStatus[m_rs].dwStatusNumber;
// don't pass NULL, give 'em empty string on certain cases
if ( ! pLog->pszClientUserName)
pLog->pszClientUserName = cszEmpty;
if ( ! pLog->pszParameters )
pLog->pszParameters = cszEmpty;
*ppStFilterOrg = MyAllocNZ(HTTP_FILTER_LOG);
cleanupFCLog:
if ( !pLog->pszClientUserName || !pLog->pszServerName
|| !pLog->pszOperation || !pLog->pszTarget
|| !pLog->pszParameters || !pLog->pszClientHostName
|| !(*ppStFilterOrg))
{
MyFree((*ppStFilterOrg));
MyFree(pLog->pszClientHostName);
if (pLog->pszServerName != cszEmpty) {
MyFree(pLog->pszServerName);
}
MyFree(pLog);
*ppStFilter = NULL;
myleave(344);
}
memcpy(*ppStFilterOrg,*ppStFilter,sizeof(HTTP_FILTER_LOG));
}
break;
default:
DEBUGCHK(0);
DEBUGMSG(ZONE_ERROR,(L"HTTPD: FillFC received unknown notification type = %d\r\n",dwNotifyType));
*ppStFilterOrg = *ppStFilter = NULL;
myleave(246);
break;
}
// the pfc is always the same regardless of dwNotifyType
pfc->cbSize = sizeof(*pfc);
pfc->Revision = HTTP_FILTER_REVISION;
pfc->ServerContext = (PVOID) this;
pfc->ulReserved = 0;
pfc->fIsSecurePort = m_fIsSecurePort;
// pfc->pFilterContext is filled in calling loop in CallFilter()
pfc->GetServerVariable = ::GetServerVariable;
pfc->AddResponseHeaders = ::AddResponseHeaders;
pfc->WriteClient = ::WriteClient;
pfc->AllocMem = ::AllocMem;
pfc->ServerSupportFunction = ::ServerSupportFunction;
ret = TRUE;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"HTTPD: FillFC failed on mem alloc, GLE = %d, err= %d\r\n",GetLastError(),err));
return ret;
}
// Final fcn called in CallFilter, this frees any unneeded allocated memory
// and sets the last three values, if valid, to whatever the filter changed them to.
BOOL CHttpRequest::CleanupFC(DWORD dwNotifyType, LPVOID* ppStFilter, LPVOID* ppStFilterOrg,
PSTR *ppszBuf1, int *pcbBuf, PSTR *ppszBuf2)
{
BOOL fRet = TRUE;
switch (dwNotifyType)
{
case SF_NOTIFY_END_OF_NET_SESSION:
case SF_NOTIFY_END_OF_REQUEST:
case SF_NOTIFY_PREPROC_HEADERS:
case SF_NOTIFY_SEND_RESPONSE:
break;
case SF_NOTIFY_READ_RAW_DATA:
{
PHTTP_FILTER_RAW_DATA pRawData = (PHTTP_FILTER_RAW_DATA) *ppStFilter;
if (! ppszBuf1) { // Use buffer in CHttpResponse class
m_bufRequest.FilterDataUpdate(pRawData->pvInData,pRawData->cbInData,pRawData->pvInData != m_bufRequest.FilterRawData());
}
else {
*ppszBuf1 = (PSTR) pRawData->pvInData;
*pcbBuf = pRawData->cbInData;
}
}
break;
case SF_NOTIFY_AUTHENTICATION:
{
PHTTP_FILTER_AUTHENT pAuth = (PHTTP_FILTER_AUTHENT) *ppStFilter;
*ppszBuf1 = pAuth->pszUser;
*ppszBuf2 = pAuth->pszPassword;
}
break;
case SF_NOTIFY_SEND_RAW_DATA:
{
PHTTP_FILTER_RAW_DATA pRawData = (PHTTP_FILTER_RAW_DATA) *ppStFilter;
*ppszBuf1 = (PSTR) pRawData->pvInData;
*pcbBuf = pRawData->cbInData;
}
break;
case SF_NOTIFY_URL_MAP:
{
PHTTP_FILTER_URL_MAP pUrlMap = (PHTTP_FILTER_URL_MAP) *ppStFilter ;
PHTTP_FILTER_URL_MAP pUrlMapOrg = (PHTTP_FILTER_URL_MAP) *ppStFilterOrg;
// Case when parsing http headers from a request.
if (NULL == ppszBuf1) {
// since data can be modified in place, always re-copy
MyFree(m_wszPath);
m_wszPath = MySzDupAtoW(pUrlMap->pszPhysicalPath);
MyFree(pUrlMapOrg->pszPhysicalPath);
if (!m_wszPath)
fRet = FALSE;
// note: don't set m_ccWPath here because it will be set in ParseHeaders() anyway.
}
else { // ServerSupportFunction with HSE_MAP_URL call
*ppszBuf1 = (PSTR) pUrlMap->pszURL;
*ppszBuf2 = pUrlMap->pszPhysicalPath;
*pcbBuf = pUrlMap->cbPathBuff;
}
}
break;
case SF_NOTIFY_ACCESS_DENIED:
{
PHTTP_FILTER_ACCESS_DENIED pDeniedOrg = (PHTTP_FILTER_ACCESS_DENIED) *ppStFilterOrg;
// If they change pDenied->pszURL we ignore it. Since the session
// is coming to an end because of access problems, the only thing changing
// pszURL could affect would be logging (which should be set through logging filter)
MyFree(pDeniedOrg->pszPhysicalPath);
}
break;
// We use m_pFInfo->m_pFLog to store changes to the log. When
// we write out the log, we use the web server value by default
// unless a particular value is non-NULL; by default all values
// are NULL in m_pFInfo->m_pFLog unless overwritten by this code.
case SF_NOTIFY_LOG:
{
PHTTP_FILTER_LOG pLog = (PHTTP_FILTER_LOG) *ppStFilter;
PHTTP_FILTER_LOG pLogOrg = (PHTTP_FILTER_LOG ) *ppStFilterOrg;
PHTTP_FILTER_LOG pFLog;
// Free dynamically allocated data.
MyFreeNZ(pLogOrg->pszClientHostName);
if (pLogOrg->pszServerName != cszEmpty)
MyFreeNZ(pLogOrg->pszServerName);
// If no changes were made, break out early.
if ( ! memcmp(pLog, pLogOrg, sizeof(HTTP_FILTER_LOG))) {
break;
}
if (NULL == (pFLog = m_pFInfo->m_pFLog = MyAllocZ(HTTP_FILTER_LOG))) {
// Memory errors just mean we won't bother doing logging, non-fatal.
break;
}
if (pLog->pszClientHostName != pLogOrg->pszClientHostName)
pFLog->pszClientHostName = pLog->pszClientHostName;
if (pLog->pszServerName != pLogOrg->pszServerName)
pFLog->pszServerName = pLog->pszServerName;
if (pLog->pszClientUserName != pLogOrg->pszClientUserName)
pFLog->pszClientUserName = pLog->pszClientUserName;
if (pLog->pszOperation != pLogOrg->pszOperation)
pFLog->pszOperation = pLog->pszOperation;
if (pLog->pszTarget != pLogOrg->pszTarget)
pFLog->pszTarget = pLog->pszTarget;
if (pLog->pszParameters != pLogOrg->pszParameters)
pFLog->pszParameters = pLog->pszParameters ;
pFLog->dwHttpStatus = pLog->dwHttpStatus;
pFLog->dwWin32Status = pLog->dwWin32Status;
pFLog->dwBytesSent = pLog->dwBytesSent;
pFLog->dwBytesRecvd = pLog->dwBytesRecvd ;
pFLog->msTimeForProcessing = pLog->msTimeForProcessing;
}
break;
default:
DEBUGMSG(ZONE_ERROR,(L"HTTPD: CleanupFCs received unknown code = %d\r\n",dwNotifyType));
break;
}
MyFree(*ppStFilterOrg);
MyFree(*ppStFilter);
return fRet;
}
// Initializes buffers for CallFilter with SF_NOTIFY_AUTHENTICATION, and tries
// to authenticate if the filter changes any data.
// Note: Even in the case where security isn't a component or is disabled in
// registry, we make this call because filter may theoretically decide to end
// the session based on the user information it receives.
BOOL CHttpRequest::AuthenticateFilter() {
DEBUG_CODE_INIT;
BOOL ret = FALSE;
// IIS docs promise the filter minimum sized buffers to write password
// and user name into, we provide them
char szUserName[SF_MAX_USERNAME];
char szPassword[SF_MAX_PASSWORD];
PSTR pszNewUserName = szUserName;
PSTR pszNewPassword = szPassword;
// We only make notification if we're using Anonymous or BASIC auth,
// otherwise we don't know how to decode the text/password. Like IIS.
if ( m_pszAuthType && 0 != _stricmp(m_pszAuthType,cszBasic))
return TRUE;
// write existing value, if any, into the new buffers
// In this case we've cracked the user name and password into ANSI already.
if (m_pszRemoteUser) {
// These are safe strcpy's because HandleBasicAuth cracked
// out the strings and made sure their combined len was < MAX_PATH.
DEBUGCHK(strlen(m_pszRemoteUser) < sizeof(szUserName));
DEBUGCHK(strlen(m_pszPassword) < sizeof(szPassword));
StringCbCopyA(szUserName,sizeof(szUserName),m_pszRemoteUser);
StringCbCopyA(szPassword,sizeof(szPassword),m_pszPassword);
}
// We have user user name data but it hasn't been Base64 Decoded yet
else if (m_pszRawRemoteUser) {
DWORD dwLen = sizeof(szUserName);
if (strlen(m_pszRawRemoteUser) >= MAXUSERPASS) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Base64 data > 256 bytes on Basic Auth, failing request\r\n"));
m_rs = STATUS_FORBIDDEN;
return FALSE;
}
if (! svsutil_Base64Decode(m_pszRawRemoteUser,(void*)szUserName,sizeof(szUserName),NULL,TRUE)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Base64 data is invalid, failing request\r\n"));
m_rs = STATUS_BADREQ;
return FALSE;
}
PSTR pszDivider = strchr(szUserName, ':');
if(NULL == pszDivider)
myleave(290);
*pszDivider++ = 0; // seperate user & pass
// We need copies of this data for later in the fcn
m_pszRemoteUser = MySzDupA(szUserName, strlen(szUserName));
if (NULL == m_pszRemoteUser)
myleave(291);
m_pszPassword = MySzDupA(pszDivider);
if (NULL == m_pszPassword)
myleave(292);
strcpy(szPassword, m_pszPassword);
strcpy(szUserName, m_pszRemoteUser);
}
// Otherwise the browser didn't set any user information.
else {
szUserName[0] = '\0';
szPassword[0] = '\0';
}
if ( ! CallFilter(SF_NOTIFY_AUTHENTICATION,&pszNewUserName, NULL, &pszNewPassword))
myleave(293);
// If the filter arbitrarily denied access, then we exit.
// Check if the filter has changed the user name ptr or modified it in place.
if ( pszNewUserName != szUserName || // changed ptr
(m_pszRemoteUser == NULL && szUserName[0] != '\0') || // modified in place
(m_pszRemoteUser && strcmp(szUserName, m_pszRemoteUser) ) // modified in place
)
{
// Update m_pszRemoteUser with what was set in filter because GetServerVariable
// may need it.
ResetString(m_pszRemoteUser, pszNewUserName);
if (! m_pszRemoteUser)
myleave(294);
}
if ( pszNewPassword != szPassword ||
(m_pszPassword == NULL && szPassword[0] != '\0') ||
(m_pszPassword && strcmp(szPassword, m_pszPassword))
)
{
// GetServerVariables with AUTH_PASSWORD might request this.
ResetString(m_pszPassword, pszNewPassword);
if (! m_pszPassword)
myleave(295);
}
ret = TRUE;
done:
DEBUGMSG_ERR(ZONE_ERROR,(L"HTTPD: Authentication for filters failed, err = %d, GLE = %d\r\n",err,GetLastError()));
return ret;
}
// Called on updating data from an ISAPI filter, resets internal structures.
// fModifiedPtr is TRUE when
BOOL CBuffer::FilterDataUpdate(PVOID pvData, DWORD cbData, BOOL fModifiedPtr) {
// a filter can do anything to 2nd HTTP request waiting in buffer, so
// just mark it as invalid to play it safe.
InvalidateNextRequestIfAlreadyRead();
if (fModifiedPtr) {
if ((int) (cbData - UnaccessedCount()) > 0) {
if (! AllocMem(cbData - UnaccessedCount() + 1))
return FALSE;
memcpy(m_pszBuf + m_iNextInFollow, pvData, cbData);
}
}
// It's possible we modified data in place, so we always update the size
// information that the filter passed us in case it changed the # of bytes
// in the request.
m_iNextIn = (int)cbData + m_iNextInFollow;
m_iNextInFollow = m_iNextIn;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -