📄 request.cpp
字号:
// the http engine no longer directly display the requested page. In this
// case the filter acts like an ISAPI extension, it's responsible for returning
// it's own content. (Like IIS).
// This isn't the same as ASP's concept of having sent headers. ASP's sent headers
// stops script from doing other calls to send headers. If Filter wants to send
// more headers (which will appear in client browser window) fine, we copy IIS.
// This is small enough that it's not worth putting into a stub.
BOOL CHttpRequest::FilterNoResponse(void) {
if (m_pFInfo && m_pFInfo->m_fSentHeaders)
return TRUE;
return FALSE;
}
// Note: This has not been made part of the ISAPI component because we need
// to do checking as to whether the requested operation is valid given our current
// component set.
BOOL CHttpRequest::HandleScript() {
DEBUG_CODE_INIT;
BOOL ret = TRUE; // Is page a ASP/ISAPI?
WCHAR *wszMappedISAPI;
WCHAR *wszExecutePath;
BOOL fMappedASP = FALSE;
BOOL fMappedISAPI = FALSE;
if (g_pVars->m_fExtensions && m_wszExt && MapScriptExtension(m_wszExt,&wszMappedISAPI,&fMappedASP)) {
if (!fMappedASP) {
// If fMappedASP = TRUE we use asp.dll, otherwise wszMappedISAPI points to ISAPI extension.
fMappedISAPI = TRUE;
wszExecutePath = wszMappedISAPI;
}
else
wszExecutePath = m_wszPath;
}
else
wszExecutePath = m_wszPath;
if (fMappedASP || fMappedISAPI) {
// Using a script mapping
if (m_pszPathInfo) {
DEBUGCHK(0); // shouldn't be able to set path info on anything but .asp or .dll m_wszExt.
MyFree(m_pszPathInfo);
}
if (NULL == (m_pszPathInfo = MySzDupA(m_pszURL))) {
m_rs = STATUS_INTERNALERR;
myleave(59);
}
}
// If the file extension is .dll but the permissions flags don't have
// HSE_URL_FLAGS_EXECUTE, we send the dll as a file. Like IIS.
// If the VRoot was not executable we would download the dll, regardless of whether
// extenions are a component or not. Like IIS.
if (GetScriptType() == SCRIPT_TYPE_EXTENSION || fMappedISAPI ||
(m_wszExt && (0==_wcsicmp(m_wszExt, L".DLL")))) {
if (FALSE == g_pVars->m_fExtensions) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Cannot load ISAPI extension because ISAPI is not a component of httpd.dll\r\n"));
m_rs = STATUS_NOTIMPLEM;
myleave(88);
}
if (! IsLocalFile(wszExecutePath)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Cannot load ISAPI extension because it is not on the local device\r\n"));
m_rs = STATUS_FORBIDDEN;
if (g_pVars->m_fFilters)
CallFilter(SF_NOTIFY_ACCESS_DENIED);
myleave(87);
}
if (! TranslateRequestToScript()) {
ret = (m_rs != STATUS_OK); // return TRUE to stop remainder of HandleRequest processing on err
goto done;
}
if (! (GetPerms() & HSE_URL_FLAGS_EXECUTE)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: cannot load ISAPI extension because vroot does not have HSE_URL_FLAGS_EXECUTE set\r\n"));
m_rs = STATUS_FORBIDDEN;
if (g_pVars->m_fFilters)
CallFilter(SF_NOTIFY_ACCESS_DENIED);
myleave(79);
}
if (! SetPathTranslated()) {
m_rs = STATUS_INTERNALERR;
myleave(94);
}
if (! ExecuteISAPI(wszExecutePath)) {
m_rs = STATUS_INTERNALERR;
myleave(53);
}
}
// check if it's an executable ASP. If the appropriate permissions aren't set,
// we send an access denied message. Never download an ASP file's source
// code under any conditions.
else if(GetScriptType() == SCRIPT_TYPE_ASP || fMappedASP ||
m_wszExt && (0==_wcsicmp(m_wszExt, L".ASP"))) {
if (FALSE == g_pVars->m_fASP) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Cannot load ASP interpretter because ASP is not a component of httpd.dll\r\n"));
m_rs = STATUS_NOTIMPLEM;
myleave(89);
}
if (!IsLocalFile(m_wszPath)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Cannot load ASP page because it is not on the local device\r\n"));
m_rs = STATUS_FORBIDDEN;
if (g_pVars->m_fFilters)
CallFilter(SF_NOTIFY_ACCESS_DENIED);
myleave(87);
}
if (! TranslateRequestToScript()) {
ret = (m_rs != STATUS_OK); // return TRUE to stop remainder of HandleRequest processing on err
goto done;
}
if ( ! (GetPerms() & (HSE_URL_FLAGS_EXECUTE | HSE_URL_FLAGS_SCRIPT))) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: cannot load ASP because vroot does not have HSE_URL_FLAGS_EXECUTE | HSE_URL_FLAGS_SCRIPT set\r\n"));
m_rs = STATUS_FORBIDDEN;
if (g_pVars->m_fFilters)
CallFilter(SF_NOTIFY_ACCESS_DENIED);
myleave(79);
}
if (! SetPathTranslated()) {
m_rs = STATUS_INTERNALERR;
myleave(94);
}
if(!ExecuteASP()) {
// ExecuteASP sets m_rs on error.
myleave(92);
}
}
else { // Neither an ASP or ISAPI.
ret = FALSE;
}
done:
DEBUGMSG_ERR(ZONE_REQUEST,(L"HTTPD: HandleScript failed, err = %d, m_rs = %d\r\n",err,m_rs));
return ret;
}
// wszFile is the physical file we're going to try to load. Function returns
// true if file is local and false if it is on a network drive.
// The only ways a file can be non-local on CE are if it has a UNC name
// (\\machineshare\share\file) or if it is mapped under the NETWORK directory.
// However, the Network folder doesn't have to be named "network", so we
// use the offical method to get the name
BOOL IsLocalFile(PWSTR wszFile) {
// Are we requested a UNC name
if ( wcslen(wszFile) >= 2) {
if ( (wszFile[0] == '\\' || wszFile[0] == '/') &&
(wszFile[1] == '\\' || wszFile[1] == '/')) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Extension or ASP requested is not on local file system, access denied\r\n"));
return FALSE;
}
}
CEOIDINFO ceOidInfo;
DWORD dwNetworkLen;
if (!CeOidGetInfo(OIDFROMAFS(AFS_ROOTNUM_NETWORK), &ceOidInfo)) {
return TRUE; // if we can't load it assume that it's not supported in general, so it is local file
}
dwNetworkLen = wcslen(ceOidInfo.infDirectory.szDirName);
if (0 == wcsnicmp(ceOidInfo.infDirectory.szDirName,wszFile,dwNetworkLen)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: Extension or ASP requested is not on local file system, access denied\r\n"));
return FALSE;
}
return TRUE;
}
// dwMaxSizeToRead is HKLM\Comm\Httpd\PostReadSize in typcilac case, or
// is unread data if fInitialPostRead=0, which means that we're handling
// an error condition on keep-alive and need to read remaining post data.
// Note that we do NOT suck in remaining POST data if an ISAPI extension
// ran and had more data than was initially read in because it's the ISAPI's
// job to read all this data off the wire using ReadClient if they're going
// to do a keep-alive; if they don't do this then HTTPD will get parse errors,
// like IIS.
BOOL CHttpRequest::ReadPostData(DWORD dwMaxSizeToRead, BOOL fInitialPostRead, BOOL fSSLRenegotiate) {
BOOL ret = TRUE;
HRINPUT hi;
if ((m_dwContentLength && dwMaxSizeToRead) || fSSLRenegotiate) {
DWORD dwRead = min(m_dwContentLength,dwMaxSizeToRead);
hi = m_bufRequest.RecvBody(m_socket, dwRead, !fInitialPostRead,fInitialPostRead,this,fSSLRenegotiate);
if (m_rs != STATUS_OK) {
// if !STATUS_OK we've set err already, probably SSL forbidden issue.
ret = FALSE;
}
else if ((hi != INPUT_OK) && (hi != INPUT_NOCHANGE)) {
m_rs = STATUS_BADREQ;
ret = FALSE;
}
// If no new data was read (hi = INPUT_NOCHANGE) don't call filter.
else if (g_pVars->m_fFilters &&
hi != INPUT_NOCHANGE &&
! CallFilter(SF_NOTIFY_READ_RAW_DATA)) {
// let filter set error code.
ret = FALSE;
}
}
if (ret == TRUE)
m_dwInitialPostRead = m_bufRequest.m_iNextInFollow = m_bufRequest.m_iNextIn;
return ret;
}
BOOL CHttpRequest::CheckAuth() {
if (CheckAuth(GetAuthReq()))
return TRUE;
DEBUGMSG(ZONE_AUTH,(L"HTTPD: CheckAuth fails. Access required=%d, access granted=%d\r\n",GetAuthReq(),m_AuthLevelGranted));
if (g_pVars->m_fFilters)
CallFilter(SF_NOTIFY_ACCESS_DENIED);
return FALSE;
}
BOOL IsPathScript(WCHAR *szPath, SCRIPT_TYPE scriptType) {
if ((scriptType == SCRIPT_TYPE_EXTENSION) || (scriptType == SCRIPT_TYPE_ASP))
return TRUE;
WCHAR *szISAPI;
BOOL fMappedASP;
WCHAR *szExt = wcsrchr(szPath, '.');
if (!szExt)
return FALSE;
if ((0 == _wcsicmp(szExt,L".dll")) || (0 == _wcsicmp(szExt,L".asp")))
return TRUE;
return (MapScriptExtension(szExt,&szISAPI,&fMappedASP));
}
// Checks to see if we're mapped to an ISAPI/ASP page.
// If fCheckAccess=TRUE, also verifies that required permissions to execute have been granted.
BOOL CHttpRequest::IsScript(BOOL fCheckAccess) {
WCHAR *szISAPI = NULL;
BOOL fMappedASP = FALSE;
BOOL fMappedISAPI = (m_wszExt && MapScriptExtension(m_wszExt,&szISAPI,&fMappedASP) && !fMappedASP);
// script map to an ISAPI, direct request to ISAPI ".dll", or vroot maps to ISAPI
if (fMappedISAPI || (m_wszExt && (0==_wcsicmp(m_wszExt, L".DLL"))) || (GetScriptType() == SCRIPT_TYPE_EXTENSION))
return fCheckAccess ? (GetPerms() & (HSE_URL_FLAGS_EXECUTE | HSE_URL_FLAGS_READ)) : TRUE;
// script map to a ASP, direct request to file named *.asp , or vroot maps to ASP
if (fMappedASP || ((m_wszExt && 0==_wcsicmp(m_wszExt, L".ASP"))) || (GetScriptType() == SCRIPT_TYPE_ASP))
return fCheckAccess ? (GetPerms() & (HSE_URL_FLAGS_EXECUTE | HSE_URL_FLAGS_SCRIPT)) : TRUE;
return FALSE;
}
// Is there a 'translate: f' HTTP header? On return, one of three things can happen.
// 1. There's no translate header, so execute script as always (typical case)
// 2. There is a 'translate: f' header but no HSE_URL_FLAGS_SCRIPT_SOURCE access on vroot.
// Send 403 to client.
// 3. There is a 'translate: f' header and script source access is granted. HandleRequest
// processes remainder of request from then, most likely pushing off to WebDAV.
BOOL CHttpRequest::TranslateRequestToScript(void) {
PSTR szHeader = FindHttpHeader(cszTranslate,ccTranslate);
if (szHeader && (*szHeader == 'f' || *szHeader == 'F')) {
DEBUGMSG(ZONE_REQUEST,(L"HTTPD: \"translate: 'f'\" header sent, will not forward request to script\r\n"));
if (! (GetPerms() & HSE_URL_FLAGS_SCRIPT_SOURCE)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: request to access script source fails,HSE_URL_FLAGS_SCRIPT_SOURCE for this vroot\r\n"));
m_rs = STATUS_FORBIDDEN;
}
if ((GetScriptType() == SCRIPT_TYPE_EXTENSION) || (GetScriptType() == SCRIPT_TYPE_ASP)) {
if ((m_idMethod != VERB_OPTIONS) && (m_idMethod != VERB_PROPFIND)) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: request to skip translatition on script that is mapped directly to VRoot is not supported, returning 403\r\n"));
m_rs = STATUS_FORBIDDEN;
}
}
return FALSE;
}
return TRUE;
}
PSTR CHttpRequest::FindHttpHeader(PCSTR szHeaderName, DWORD ccHeaderName) {
PSTR szTrav = m_bufRequest.Headers();
DEBUGCHK(szHeaderName[ccHeaderName-1] == ':');
DEBUGCHK(strlen(szHeaderName) == ccHeaderName);
DEBUGCHK(!m_fHeadersInvalid); // no temporary \0's in header.
while (*szTrav != '\r') {
if (0 == _strnicmp(szHeaderName,szTrav,ccHeaderName)) {
PSTR szHeaderValue = szTrav + ccHeaderName;
while ( (szHeaderValue)[0] != '\0' && IsNonCRLFSpace((szHeaderValue)[0])) { ++(szHeaderValue); }
return szHeaderValue;
}
if (NULL == (szTrav = strstr(szTrav,"\r\n")))
break;
szTrav += 2;
}
return NULL;
}
// We only call authenticate filter once per session.
BOOL CHttpRequest::CallAuthFilterIfNeeded(void) {
if (g_pVars->m_fFilters && ! (m_dwAuthFlags & AUTH_FILTER_DONE)) {
m_dwAuthFlags |= AUTH_FILTER_DONE;
return AuthenticateFilter();
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -