mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1863 lines
53 KiB
1863 lines
53 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
basereq.hxx
|
|
|
|
Abstract:
|
|
|
|
This file declares the class for http base request, that is used
|
|
by the w3 information service.
|
|
|
|
Author:
|
|
|
|
Murali R. Krishnan ( MuraliK ) 16-Oct-1995
|
|
|
|
Environment:
|
|
|
|
Win32 -- User Mode
|
|
|
|
Project:
|
|
|
|
W3 Server DLL
|
|
|
|
Revision History:
|
|
Murali R. Krishnan (MuraliK) 22-Jan-1996
|
|
make impersonation/revert function virtual
|
|
|
|
--*/
|
|
|
|
# ifndef _BASEREQ_HXX_
|
|
# define _BASEREQ_HXX_
|
|
|
|
/************************************************************
|
|
* Include Headers
|
|
************************************************************/
|
|
|
|
# include "string.hxx"
|
|
# include "httphdr.hxx"
|
|
# include "tssec.hxx"
|
|
# include "w3type.hxx"
|
|
# include "filter.hxx"
|
|
# include "redirect.hxx"
|
|
|
|
extern BOOL ReadEntireFile(
|
|
CHAR *pszFileName,
|
|
TSVC_CACHE &Cache,
|
|
HANDLE User,
|
|
BUFFER *pBuf,
|
|
DWORD *pdwBytesRead
|
|
);
|
|
|
|
// Forward References
|
|
class CLIENT_CONN;
|
|
class HTTP_FILTER;
|
|
class HTTP_FILTER_DLL;
|
|
class W3_SERVER_INSTANCE;
|
|
|
|
/************************************************************
|
|
* Symbolic Constants
|
|
************************************************************/
|
|
|
|
//
|
|
// HTTP Server response status codes
|
|
//
|
|
|
|
#define HT_OK 200
|
|
#define HT_CREATED 201
|
|
//#define HT_ACCEPTED 202
|
|
//#define HT_PARTIAL 203
|
|
#define HT_NO_CONTENT 204
|
|
#define HT_RANGE 206
|
|
|
|
//#define HT_MULT_CHOICE 300
|
|
#define HT_MOVED 301
|
|
#define HT_REDIRECT 302
|
|
#define HT_REDIRECT_METHOD 303
|
|
#define HT_NOT_MODIFIED 304
|
|
|
|
#define HT_BAD_REQUEST 400
|
|
#define HT_DENIED 401
|
|
//#define HT_PAYMENT_REQ 402
|
|
#define HT_FORBIDDEN 403
|
|
#define HT_NOT_FOUND 404
|
|
#define HT_METHOD_NOT_ALLOWED 405
|
|
#define HT_NONE_ACCEPTABLE 406
|
|
#define HT_PROXY_AUTH_REQ 407
|
|
//#define HT_REQUEST_TIMEOUT 408
|
|
//#define HT_CONFLICT 409
|
|
//#define HT_GONE 410
|
|
#define HT_LENGTH_REQUIRED 411
|
|
#define HT_PRECOND_FAILED 412
|
|
#define HT_URL_TOO_LONG 414
|
|
#define HT_RANGE_NOT_SATISFIABLE 416
|
|
|
|
#define HT_SERVER_ERROR 500
|
|
#define HT_NOT_SUPPORTED 501
|
|
#define HT_BAD_GATEWAY 502
|
|
#define HT_SVC_UNAVAILABLE 503
|
|
#define HT_GATEWAY_TIMOUT 504
|
|
|
|
//
|
|
// Special invalid HTTP response code used to indicate a request should not
|
|
// be logged
|
|
//
|
|
|
|
#define HT_DONT_LOG 000
|
|
|
|
//
|
|
// The versioning string for responses
|
|
//
|
|
#define HTTP_VERSION_STR PSZ_HTTP_VERSION_STR
|
|
|
|
//
|
|
// Flags for network communications over this request
|
|
//
|
|
|
|
#define IO_FLAG_ASYNC 0x00000010 // Call is async
|
|
#define IO_FLAG_SYNC 0x00000020 // Call is synchronous
|
|
#define IO_FLAG_SEND 0x00000040 // Call is a send
|
|
#define IO_FLAG_RECV 0x00000080 // Call is a recv
|
|
#define IO_FLAG_NO_FILTER 0x00000100 // Don't go through filters
|
|
#define IO_FLAG_AND_RECV 0x00000400 // Add recv operation to IO
|
|
#define IO_FLAG_NO_RECV 0x00000800 // Don't do auto-recv after TransmitFile
|
|
#define IO_FLAG_NO_DELAY 0x00001000 // Disable Nagling on the socket
|
|
|
|
|
|
// Flags for header generation
|
|
|
|
#define HTTPH_SEND_GLOBAL_EXPIRE 0x00000001
|
|
#define HTTPH_NO_DATE 0x00000002
|
|
#define HTTPH_NO_CONNECTION 0x00000004
|
|
#define HTTPH_NO_CUSTOM 0x00000008
|
|
|
|
#define MIN_BUFFER_SIZE_FOR_HEADERS 384
|
|
#define MAX_CUSTOM_ERROR_FILE_SIZE (48 * 1024)
|
|
|
|
#define MD_AUTH_ALL (MD_AUTH_ANONYMOUS|MD_AUTH_BASIC|MD_AUTH_MD5|MD_AUTH_MAPBASIC)
|
|
|
|
#define MAX_CERT_FIELD_SIZE 4096
|
|
|
|
#define MAX_ALLOW_SIZE (sizeof("Allow: OPTIONS, TRACE, PUT, DELETE, HEAD, GET\r\n") - 1)
|
|
|
|
#define MAX_URI_LENGTH 255
|
|
|
|
//
|
|
// Back trace configuration
|
|
//
|
|
|
|
#define MAX_BACKTRACE_FRAMES 10
|
|
|
|
/************************************************************
|
|
* Type Definitions
|
|
************************************************************/
|
|
|
|
enum HTTP_VERB
|
|
{
|
|
HTV_GET = 0,
|
|
HTV_HEAD,
|
|
HTV_TRACE,
|
|
HTV_PUT,
|
|
HTV_DELETE,
|
|
HTV_TRACECK,
|
|
HTV_POST,
|
|
HTV_OPTIONS,
|
|
HTV_UNKNOWN
|
|
};
|
|
|
|
//
|
|
// Class of a custom error entry.
|
|
//
|
|
class CUSTOM_ERROR_ENTRY
|
|
{
|
|
public:
|
|
|
|
CUSTOM_ERROR_ENTRY( DWORD dwErr,
|
|
DWORD dwSubError,
|
|
BOOL bWildcard,
|
|
CHAR *pszPath,
|
|
BOOL bFileError
|
|
)
|
|
{
|
|
m_dwErr = dwErr;
|
|
m_dwSubError = dwSubError;
|
|
m_bIsFileError = bFileError;
|
|
m_bIsWildcard = bWildcard;
|
|
|
|
if (bFileError)
|
|
{
|
|
m_pszNames.ErrorFileName = pszPath;
|
|
}
|
|
else
|
|
{
|
|
m_pszNames.ErrorURL = pszPath;
|
|
}
|
|
}
|
|
|
|
~CUSTOM_ERROR_ENTRY( VOID )
|
|
{
|
|
CHAR *pszTemp;
|
|
|
|
if (m_bIsFileError)
|
|
{
|
|
pszTemp = m_pszNames.ErrorFileName;
|
|
}
|
|
else
|
|
{
|
|
pszTemp = m_pszNames.ErrorURL;
|
|
}
|
|
|
|
if (pszTemp != NULL)
|
|
{
|
|
TCP_FREE(pszTemp);
|
|
}
|
|
}
|
|
|
|
BOOL IsFileError( VOID )
|
|
{ return m_bIsFileError; }
|
|
|
|
CHAR *QueryErrorFileName( VOID )
|
|
{ return m_pszNames.ErrorFileName; }
|
|
|
|
CHAR *QueryErrorURL( VOID )
|
|
{ return m_pszNames.ErrorURL; }
|
|
|
|
DWORD QueryError( VOID )
|
|
{ return m_dwErr; }
|
|
|
|
DWORD QuerySubError( VOID )
|
|
{ return m_dwSubError; }
|
|
|
|
DWORD QueryWildcard( VOID )
|
|
{ return m_bIsWildcard; }
|
|
|
|
LIST_ENTRY _ListEntry;
|
|
|
|
private:
|
|
BOOL m_bIsFileError;
|
|
BOOL m_bIsWildcard;
|
|
DWORD m_dwErr;
|
|
DWORD m_dwSubError;
|
|
union
|
|
{
|
|
CHAR *ErrorFileName;
|
|
CHAR *ErrorURL;
|
|
|
|
} m_pszNames;
|
|
};
|
|
|
|
typedef CUSTOM_ERROR_ENTRY *PCUSTOM_ERROR_ENTRY;
|
|
|
|
//
|
|
// The structure of the server's pre-digested meta data.
|
|
//
|
|
|
|
#define W3MD_CREATE_PROCESS_AS_USER 0x00000001
|
|
#define W3MD_CREATE_PROCESS_NEW_CONSOLE 0x00000002
|
|
|
|
#define EXPIRE_MODE_NONE 0
|
|
#define EXPIRE_MODE_STATIC 1
|
|
#define EXPIRE_MODE_DYNAMIC 2
|
|
#define EXPIRE_MODE_OFF 3
|
|
|
|
class W3_METADATA : public COMMON_METADATA {
|
|
|
|
public:
|
|
|
|
//
|
|
// Hmmm, since most of these values aren't getting initialized, if
|
|
// somebody went and deleted all the metadata items from the tree, then
|
|
// bad things could happen. We should initialize with defaults things
|
|
// that might mess us
|
|
//
|
|
|
|
W3_METADATA(VOID) :
|
|
m_dwAuthentication ( MD_AUTH_ANONYMOUS ),
|
|
m_dwAuthenticationPersistence( MD_AUTH_SINGLEREQUESTIFPROXY ),
|
|
m_fAnyExtAllowedOnReadDir( FALSE ),
|
|
m_pRBlob ( NULL ),
|
|
m_dwFooterLength ( 0 ),
|
|
m_pszFooter ( NULL ),
|
|
m_bFooterEnabled ( TRUE ),
|
|
m_bHaveNoCache ( FALSE ),
|
|
m_bHaveMaxAge ( FALSE ),
|
|
m_bSSIExecDisabled ( FALSE ),
|
|
m_dwCGIScriptTimeout ( DEFAULT_SCRIPT_TIMEOUT ),
|
|
m_csecPoolIDCTimeout ( 0 ),
|
|
m_dwCreateProcessFlags( W3MD_CREATE_PROCESS_AS_USER ),
|
|
m_fAllowKeepAlives ( TRUE ),
|
|
m_fCacheISAPIApps ( TRUE ),
|
|
m_fDoReverseDns ( FALSE ),
|
|
m_dwExpireMaxLength ( 0 ),
|
|
m_dwExpireMode ( EXPIRE_MODE_NONE ),
|
|
m_pWildcardMapping ( NULL ),
|
|
m_dwNotifyExAuth ( 0 ),
|
|
m_pszCCPointer ( NULL ),
|
|
m_dwUploadReadAhead (DEFAULT_W3_UPLOAD_READ_AHEAD),
|
|
m_dwPutReadSize (8192),
|
|
#if defined(CAL_ENABLED)
|
|
m_dwCalHnd ( INVALID_CAL_EXEMPT_HANDLE ),
|
|
#endif
|
|
m_dwDirBrowseFlags ( MD_DIRBROW_LOADDEFAULT ),
|
|
m_fJobCGIEnabled ( FALSE ),
|
|
m_fIgnoreTranslate ( FALSE ),
|
|
m_fUseDigestSSP ( FALSE ),
|
|
m_dwMaxExtLen (0)
|
|
{
|
|
InitializeListHead( &m_ExtMapHead );
|
|
InitializeListHead( &m_CustomErrorHead );
|
|
|
|
memset( m_apszNTProviders, 0, sizeof(m_apszNTProviders) );
|
|
|
|
if ( g_fIsWindows95 )
|
|
{
|
|
m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_AS_USER;
|
|
}
|
|
|
|
}
|
|
|
|
~W3_METADATA(VOID)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
DestroyCustomErrorTable();
|
|
TerminateExtMap();
|
|
|
|
if (m_pRBlob != NULL )
|
|
{
|
|
delete m_pRBlob;
|
|
m_pRBlob = NULL;
|
|
}
|
|
|
|
while ( m_apszNTProviders[i] )
|
|
{
|
|
TCP_FREE( m_apszNTProviders[i++] );
|
|
}
|
|
|
|
#if defined(CAL_ENABLED)
|
|
if ( m_dwCalHnd != INVALID_CAL_EXEMPT_HANDLE )
|
|
{
|
|
CalExemptRelease( m_dwCalHnd );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
BOOL HandlePrivateProperty(
|
|
LPSTR pszURL,
|
|
PIIS_SERVER_INSTANCE pInstance,
|
|
METADATA_GETALL_INTERNAL_RECORD *pMDRecord,
|
|
LPVOID pDataPointer,
|
|
BUFFER *pBuffer,
|
|
DWORD *pdwBytesUsed,
|
|
PMETADATA_ERROR_INFO pMDErrorInfo
|
|
);
|
|
|
|
BOOL FinishPrivateProperties(
|
|
BUFFER *pBuffer,
|
|
DWORD dwBytesUsed,
|
|
BOOL bSucceeded
|
|
);
|
|
|
|
//
|
|
// Query Methods
|
|
//
|
|
|
|
STR * QueryDefaultDocs( VOID )
|
|
{ return &m_strDefaultDocs; }
|
|
|
|
STR * QueryHeaders( VOID )
|
|
{ return &m_strHeaders; }
|
|
|
|
BUFFER * QueryMimeMap( VOID )
|
|
{ return &m_bufMimeMap; }
|
|
|
|
DWORD QueryAuthentication( VOID ) const
|
|
{ return m_dwAuthentication; }
|
|
|
|
DWORD QueryAuthenticationPersistence( VOID ) const
|
|
{ return m_dwAuthenticationPersistence; }
|
|
|
|
DWORD QueryScriptTimeout( VOID ) const
|
|
{ return m_dwCGIScriptTimeout; }
|
|
|
|
DWORD QueryDirBrowseFlags( VOID ) const
|
|
{ return m_dwDirBrowseFlags; }
|
|
|
|
BOOL LookupExtMap(
|
|
IN const CHAR * pchExt,
|
|
IN BOOL fNoWildcards,
|
|
OUT STR * pstrGatewayImage,
|
|
OUT GATEWAY_TYPE * pGatewayType,
|
|
OUT DWORD * pcchExt,
|
|
OUT BOOL * pfImageInURL,
|
|
OUT BOOL * pfVerbExcluded,
|
|
OUT DWORD * pdwFlags,
|
|
IN const CHAR *pszVerb,
|
|
IN enum HTTP_VERB Verb,
|
|
IN OUT PVOID * ppvExtMapInfo
|
|
);
|
|
|
|
PTCP_AUTHENT_INFO QueryAuthentInfo(VOID) const
|
|
{ return (const PTCP_AUTHENT_INFO) &m_TCPAuthentInfo; }
|
|
|
|
BOOL
|
|
BuildProviderList(
|
|
CHAR *pszProviders
|
|
);
|
|
|
|
BOOL
|
|
CheckSSPPackage(
|
|
IN LPCSTR pszAuthString
|
|
);
|
|
|
|
PCHAR QueryRealm(VOID) const
|
|
{ return (m_strRealm.IsEmpty() ? NULL : m_strRealm.QueryStr()); }
|
|
|
|
DWORD QueryCreateProcessAsUser(VOID) const
|
|
{ return (m_dwCreateProcessFlags & W3MD_CREATE_PROCESS_AS_USER); }
|
|
|
|
DWORD QueryCreateProcessNewConsole(VOID) const
|
|
{ return (m_dwCreateProcessFlags & W3MD_CREATE_PROCESS_NEW_CONSOLE); }
|
|
|
|
BOOL QueryAnyExtAllowedOnReadDir() const
|
|
{ return m_fAnyExtAllowedOnReadDir; }
|
|
|
|
PREDIRECTION_BLOB QueryRedirectionBlob(VOID) const
|
|
{ return m_pRBlob; }
|
|
|
|
dllexp
|
|
PCUSTOM_ERROR_ENTRY LookupCustomError( DWORD dwErr, DWORD dwSubError )
|
|
{
|
|
LIST_ENTRY *pEntry;
|
|
PCUSTOM_ERROR_ENTRY pCustomErrorItem;
|
|
PCUSTOM_ERROR_ENTRY pCustomErrorWildcard = NULL;
|
|
|
|
for ( pEntry = m_CustomErrorHead.Flink;
|
|
pEntry != &m_CustomErrorHead;
|
|
pEntry = pEntry->Flink )
|
|
{
|
|
pCustomErrorItem = CONTAINING_RECORD( pEntry,
|
|
CUSTOM_ERROR_ENTRY,
|
|
_ListEntry );
|
|
|
|
if ( pCustomErrorItem->QueryError() == dwErr )
|
|
{
|
|
if ( pCustomErrorItem->QuerySubError() == dwSubError )
|
|
{
|
|
return pCustomErrorItem;
|
|
}
|
|
else if ( pCustomErrorItem->QueryWildcard() )
|
|
{
|
|
pCustomErrorWildcard = pCustomErrorItem;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pCustomErrorWildcard;
|
|
|
|
}
|
|
|
|
DWORD QueryFooterLength(VOID) const
|
|
{ return m_dwFooterLength; }
|
|
|
|
CHAR *QueryFooter(VOID) const
|
|
{ return m_pszFooter; }
|
|
|
|
BOOL FooterEnabled(VOID) const
|
|
{ return m_bFooterEnabled; }
|
|
|
|
BOOL SSIExecDisabled(VOID) const
|
|
{ return m_bSSIExecDisabled; }
|
|
|
|
DWORD QueryPoolIDCTimeout( VOID ) const
|
|
{ return m_csecPoolIDCTimeout; }
|
|
|
|
const LPSTR * QueryNTProviders( VOID ) const
|
|
{ return m_apszNTProviders; }
|
|
|
|
BOOL QueryKeepAlives( VOID ) const
|
|
{ return m_fAllowKeepAlives; }
|
|
|
|
BOOL QueryCacheISAPIApps( VOID ) const
|
|
{ return m_fCacheISAPIApps; }
|
|
|
|
BOOL QueryDoReverseDns(VOID) const
|
|
{ return m_fDoReverseDns; }
|
|
|
|
DWORD QueryExpireMaxLength(VOID) const
|
|
{ return m_dwExpireMaxLength;}
|
|
|
|
DWORD QueryExpireDelta(VOID) const
|
|
{ return m_dwExpireDelta;}
|
|
|
|
DWORD QueryExpireMode(VOID) const
|
|
{ return m_dwExpireMode;}
|
|
|
|
LPSTR QueryExpireHeader(VOID) const
|
|
{ return m_strExpireHeader.QueryStr();}
|
|
|
|
DWORD QueryExpireHeaderLength(VOID) const
|
|
{ return m_strExpireHeader.QueryCCH();}
|
|
|
|
LARGE_INTEGER QueryExpireTime(VOID) const
|
|
{ return m_liExpireTime;}
|
|
|
|
PVOID QueryWildcardMapping(VOID) const
|
|
{ return m_pWildcardMapping; }
|
|
|
|
DWORD QueryNotifyExAuth(VOID) const
|
|
{ return m_dwNotifyExAuth; }
|
|
|
|
BOOL QueryConfigNoCache(VOID) const
|
|
{ return m_bHaveNoCache; }
|
|
|
|
BOOL QueryHaveMaxAge(VOID) const
|
|
{ return m_bHaveMaxAge; }
|
|
|
|
LPSTR QueryCacheControlHeader(VOID) const
|
|
{ return m_strCacheControlHeader.QueryStr(); }
|
|
|
|
DWORD QueryCacheControlHeaderLength(VOID) const
|
|
{ return m_strCacheControlHeader.QueryCB(); }
|
|
|
|
STR * QueryRedirectHeaders( VOID )
|
|
{ return &m_strRedirectHeaders; }
|
|
|
|
DWORD QueryUploadReadAhead(VOID) const
|
|
{ return m_dwUploadReadAhead; }
|
|
|
|
DWORD QueryPutReadSize(VOID) const
|
|
{ return m_dwPutReadSize; }
|
|
|
|
BOOL QueryJobCGIEnabled()
|
|
{ return m_fJobCGIEnabled; }
|
|
|
|
BOOL QueryIgnoreTranslate() const
|
|
{ return m_fIgnoreTranslate; }
|
|
|
|
BOOL QueryUseDigestSSP() const
|
|
{ return m_fUseDigestSSP; }
|
|
|
|
//
|
|
// Set Methods
|
|
//
|
|
|
|
BOOL SetAnonUserName(PCHAR AnonUserName)
|
|
{ return m_TCPAuthentInfo.strAnonUserName.Copy( AnonUserName ); }
|
|
|
|
BOOL SetAnonUserPassword(PCHAR AnonUserPassword)
|
|
{ return m_TCPAuthentInfo.strAnonUserPassword.Copy( AnonUserPassword ); }
|
|
|
|
BOOL SetDefaultLogonDomain(PCHAR DefLogonDom)
|
|
{ return m_TCPAuthentInfo.strDefaultLogonDomain.Copy( DefLogonDom ); }
|
|
|
|
VOID SetLogonMethod(DWORD dwLogonMethod)
|
|
{ m_TCPAuthentInfo.dwLogonMethod = dwLogonMethod; }
|
|
|
|
VOID SetUseAnonSubAuth( BOOL fUseAnonSubAuth )
|
|
{ m_TCPAuthentInfo.fDontUseAnonSubAuth = !fUseAnonSubAuth; }
|
|
|
|
VOID SetAuthentication( DWORD dwFlags )
|
|
{
|
|
if (g_fIsWindows95)
|
|
{
|
|
dwFlags &= INET_INFO_AUTH_W95_MASK;
|
|
}
|
|
m_dwAuthentication = dwFlags;
|
|
}
|
|
|
|
VOID SetAuthenticationPersistence( DWORD dwFlags )
|
|
{
|
|
m_dwAuthenticationPersistence = dwFlags;
|
|
}
|
|
|
|
VOID SetCGIScriptTimeout( DWORD dwScriptTimeout )
|
|
{ m_dwCGIScriptTimeout = dwScriptTimeout; }
|
|
|
|
VOID SetDirBrowseFlags( DWORD dwDirBrowseFlags )
|
|
{ m_dwDirBrowseFlags = dwDirBrowseFlags; }
|
|
|
|
BOOL BuildExtMap(CHAR *pszExtMapString);
|
|
|
|
BOOL SetRealm(PCHAR pszRealm)
|
|
{ return m_strRealm.Copy( pszRealm ); }
|
|
|
|
VOID SetCreateProcessAsUser(BOOL fValue)
|
|
{
|
|
if ( fValue )
|
|
{
|
|
if ( !g_fIsWindows95 ) {
|
|
m_dwCreateProcessFlags |= W3MD_CREATE_PROCESS_AS_USER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_AS_USER;
|
|
}
|
|
}
|
|
|
|
VOID SetCreateProcessNewConsole(BOOL fValue)
|
|
{
|
|
if ( fValue )
|
|
{
|
|
m_dwCreateProcessFlags |= W3MD_CREATE_PROCESS_NEW_CONSOLE;
|
|
}
|
|
else
|
|
{
|
|
m_dwCreateProcessFlags &= ~W3MD_CREATE_PROCESS_NEW_CONSOLE;
|
|
}
|
|
}
|
|
|
|
BOOL SetRedirectionBlob( STR & strSource,
|
|
STR & strDestination )
|
|
{
|
|
//
|
|
// If the redirection is nullified, don't allocate a blob
|
|
// and just return success.
|
|
//
|
|
|
|
if ( *( strDestination.QueryStr() ) == '!' )
|
|
{
|
|
return TRUE;
|
|
}
|
|
m_pRBlob = new REDIRECTION_BLOB( strSource, strDestination );
|
|
if (m_pRBlob == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
return m_pRBlob->IsValid();
|
|
}
|
|
|
|
BOOL BuildCustomErrorTable( CHAR *pszErrorList,
|
|
PMETADATA_ERROR_INFO pMDErrorInfo
|
|
);
|
|
|
|
VOID DestroyCustomErrorTable( VOID );
|
|
|
|
BOOL ReadCustomFooter( CHAR *pszFooterString,
|
|
TSVC_CACHE &Cache,
|
|
HANDLE User,
|
|
PMETADATA_ERROR_INFO pMDErrorInfo
|
|
);
|
|
|
|
VOID SetFooter(DWORD dwLength, CHAR *pszFooter)
|
|
{ m_dwFooterLength = dwLength; m_pszFooter = pszFooter; }
|
|
|
|
VOID SetFooterEnabled(BOOL bEnabled)
|
|
{ m_bFooterEnabled = bEnabled; }
|
|
|
|
VOID SetSSIExecDisabled( BOOL bDisabled )
|
|
{ m_bSSIExecDisabled = bDisabled; }
|
|
|
|
VOID SetPoolIDCTimeout( DWORD csecPoolIDCTimeout )
|
|
{ m_csecPoolIDCTimeout = csecPoolIDCTimeout; }
|
|
|
|
VOID SetAllowKeepAlives( BOOL fAllowKeepAlives )
|
|
{ m_fAllowKeepAlives = fAllowKeepAlives; }
|
|
|
|
VOID SetCacheISAPIApps( BOOL fCacheISAPIApps )
|
|
{ m_fCacheISAPIApps = fCacheISAPIApps; }
|
|
|
|
BOOL SetExpire( CHAR* pszExpire,
|
|
PMETADATA_ERROR_INFO pMDErrorInfo
|
|
);
|
|
|
|
VOID SetWildcardMapping(PVOID pMapping)
|
|
{ m_pWildcardMapping = pMapping; }
|
|
|
|
VOID SetConfigNoCache(VOID)
|
|
{ m_bHaveNoCache = TRUE; }
|
|
|
|
VOID SetHaveMaxAge(VOID)
|
|
{ m_bHaveMaxAge = TRUE; }
|
|
|
|
VOID ClearConfigNoCache(VOID)
|
|
{ m_bHaveNoCache = FALSE; }
|
|
|
|
VOID ClearHaveMaxAge(VOID)
|
|
{ m_bHaveMaxAge = FALSE; }
|
|
|
|
BOOL
|
|
SetCCHeader( BOOL bNoCache,
|
|
BOOL bMaxAge,
|
|
DWORD dwMaxAge
|
|
);
|
|
|
|
VOID SetUploadReadAhead(DWORD dwUploadSize)
|
|
{ m_dwUploadReadAhead = dwUploadSize; }
|
|
|
|
VOID SetPutReadSize(DWORD dwSize)
|
|
{ m_dwPutReadSize = dwSize; }
|
|
|
|
//
|
|
// Disable job objects on IIS5.1, original code would read the
|
|
// property from metabase
|
|
//
|
|
VOID SetJobCGIEnabled( BOOL f ) { m_fJobCGIEnabled = FALSE; }
|
|
|
|
VOID SetIgnoreTranslate( BOOL f ) { m_fIgnoreTranslate = f; }
|
|
|
|
VOID SetUseDigestSSP( BOOL f ) { m_fUseDigestSSP = f; }
|
|
|
|
private:
|
|
VOID TerminateExtMap( VOID );
|
|
TCP_AUTHENT_INFO m_TCPAuthentInfo;
|
|
STR m_strDefaultDocs;
|
|
STR m_strHeaders;
|
|
BUFFER m_bufMimeMap;
|
|
STR m_strRealm;
|
|
DWORD m_dwAuthentication;
|
|
DWORD m_dwAuthenticationPersistence;
|
|
DWORD m_dwCGIScriptTimeout;
|
|
DWORD m_dwDirBrowseFlags;
|
|
DWORD m_dwCreateProcessFlags;
|
|
LIST_ENTRY m_ExtMapHead;
|
|
LIST_ENTRY m_CustomErrorHead;
|
|
PREDIRECTION_BLOB m_pRBlob;
|
|
DWORD m_dwFooterLength;
|
|
CHAR *m_pszFooter;
|
|
BUFFER m_bufFooter;
|
|
|
|
BOOL m_fAnyExtAllowedOnReadDir:1;
|
|
BOOL m_bFooterEnabled:1;
|
|
BOOL m_bHaveNoCache:1;
|
|
BOOL m_bHaveMaxAge:1;
|
|
|
|
BOOL m_bSSIExecDisabled:1;
|
|
BOOL m_fAllowKeepAlives:1;
|
|
BOOL m_fCacheISAPIApps:1;
|
|
BOOL m_fDoReverseDns:1;
|
|
|
|
DWORD m_csecPoolIDCTimeout;
|
|
LPSTR m_apszNTProviders[MAX_SSPI_PROVIDERS];
|
|
STR m_strExpireHeader;
|
|
STR m_strCacheControlHeader;
|
|
DWORD m_dwExpireMaxLength;
|
|
DWORD m_dwExpireMode;
|
|
DWORD m_dwExpireDelta;
|
|
LARGE_INTEGER m_liExpireTime;
|
|
PVOID m_pWildcardMapping;
|
|
DWORD m_dwNotifyExAuth;
|
|
LPSTR m_pszCCPointer;
|
|
STR m_strRedirectHeaders;
|
|
DWORD m_dwUploadReadAhead;
|
|
DWORD m_dwPutReadSize;
|
|
BOOL m_fJobCGIEnabled;
|
|
#if defined(CAL_ENABLED)
|
|
DWORD m_dwCalHnd;
|
|
#endif
|
|
|
|
DWORD m_dwMaxExtLen;
|
|
BOOL m_fIgnoreTranslate;
|
|
BOOL m_fUseDigestSSP;
|
|
};
|
|
|
|
typedef W3_METADATA *PW3_METADATA;
|
|
|
|
typedef struct _W3_METADATA_INFO
|
|
{
|
|
|
|
DWORD dwMaxAge;
|
|
|
|
} W3_METADATA_INFO, *PW3_METADATA_INFO;
|
|
|
|
|
|
//
|
|
// Various states the HTTP Request goes through
|
|
//
|
|
|
|
enum HTR_STATE
|
|
{
|
|
//
|
|
// We're still gathering the client request header
|
|
//
|
|
|
|
HTR_READING_CLIENT_REQUEST = 0,
|
|
|
|
//
|
|
// The client is supplying some gateway data, deal with it
|
|
//
|
|
|
|
HTR_READING_GATEWAY_DATA,
|
|
|
|
//
|
|
// We need to take apart the client request and figure out what they
|
|
// want
|
|
//
|
|
|
|
HTR_PARSE,
|
|
|
|
//
|
|
// We're executing the verb or handing the request off to a gateway
|
|
//
|
|
|
|
HTR_DOVERB,
|
|
|
|
//
|
|
// The ISAPI application has submitted async IO operation
|
|
//
|
|
|
|
HTR_GATEWAY_ASYNC_IO,
|
|
|
|
//
|
|
// The client requested a file so send them the file
|
|
//
|
|
|
|
HTR_SEND_FILE,
|
|
|
|
//
|
|
// The proxy server is forwarding the request on to the remote server
|
|
//
|
|
|
|
HTR_PROXY_SENDING_REQUEST,
|
|
|
|
//
|
|
// The proxy server is waiting for a response from the remote server
|
|
//
|
|
|
|
HTR_PROXY_READING_RESPONSE,
|
|
|
|
//
|
|
// We're processing a CGI request so we need to ignore any IO
|
|
// completions that may occur as the CGIThread forwards the
|
|
// program's output
|
|
//
|
|
|
|
HTR_CGI,
|
|
|
|
//
|
|
// Processing a range request
|
|
//
|
|
|
|
HTR_RANGE,
|
|
|
|
//
|
|
// resume processing with clear text logon
|
|
//
|
|
|
|
HTR_RESTART_REQUEST,
|
|
|
|
|
|
//
|
|
// We're in the process of writing data from a client PUT request to
|
|
// disk
|
|
//
|
|
|
|
HTR_WRITING_FILE,
|
|
|
|
//
|
|
// We're renegotiating a certificate with the client
|
|
//
|
|
|
|
HTR_CERT_RENEGOTIATE,
|
|
|
|
//
|
|
// We're reading the entity body before doing redirect
|
|
//
|
|
|
|
HTR_REDIRECT,
|
|
|
|
//
|
|
// We're reading the entity body before sending access denial
|
|
//
|
|
|
|
HTR_ACCESS_DENIED,
|
|
|
|
//
|
|
// We've completely handled the client's request
|
|
//
|
|
|
|
HTR_DONE
|
|
};
|
|
|
|
|
|
enum CHUNK_STATE
|
|
{
|
|
READ_CHUNK_SIZE = 0,
|
|
READ_CHUNK_PARAMS,
|
|
READ_CHUNK,
|
|
READ_CHUNK_FOOTER,
|
|
READ_CHUNK_CRLF,
|
|
READ_CHUNK_DONE
|
|
};
|
|
|
|
#if 0 // This routine is no longer used /SAB
|
|
#define IS_WRITE_VERB(__verb__) ( (__verb__) == HTV_PUT || \
|
|
(__verb__) == HTV_DELETE)
|
|
#endif 0
|
|
|
|
#define CHUNK_READ_SIZE 80 // Important to keep this small, to
|
|
// avoid getting two chunks into the
|
|
// same buffer in one read.
|
|
|
|
#define CRLF_SIZE 2
|
|
|
|
#define SSLNEGO_MAP 0x00000001
|
|
|
|
/*******************************************************************
|
|
|
|
CLASS: HTTP_REQ_BASE
|
|
|
|
SYNOPSIS: Basic HTTP request object
|
|
|
|
|
|
HISTORY:
|
|
Johnl 24-Aug-1994 Created
|
|
|
|
********************************************************************/
|
|
|
|
class HTTP_REQ_BASE
|
|
{
|
|
public:
|
|
|
|
//
|
|
// Constructor/Destructor
|
|
//
|
|
|
|
HTTP_REQ_BASE( CLIENT_CONN * pClientConn,
|
|
PVOID pvInitialBuff,
|
|
DWORD cbInitialBuff );
|
|
|
|
virtual ~HTTP_REQ_BASE( VOID );
|
|
|
|
//
|
|
// This is the work entry point that is driven by the completion of the
|
|
// async IO.
|
|
//
|
|
|
|
virtual BOOL DoWork( BOOL * pfFinished ) = 0;
|
|
|
|
//
|
|
// Parses the client's HTTP request
|
|
//
|
|
|
|
virtual BOOL Parse( const CHAR* pchRequest,
|
|
DWORD cbData,
|
|
DWORD * pcbExtraData,
|
|
BOOL * pfHandled,
|
|
BOOL * pfFinished ) = 0;
|
|
|
|
|
|
// Following function can be overridden by individual derived object.
|
|
virtual dllexp BOOL GetInfo( const TCHAR * pszValName,
|
|
STR * pstr,
|
|
BOOL * pfFound = NULL )
|
|
{ if ( pfFound )
|
|
{
|
|
*pfFound = FALSE;
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
//
|
|
// Kicks off the read for a client request header
|
|
//
|
|
|
|
BOOL StartNewRequest( PVOID pvInitialBuff,
|
|
DWORD cbInitialBuff,
|
|
BOOL fFirst,
|
|
BOOL *pfDoAgain);
|
|
|
|
|
|
BOOL OnFillClientReq( BOOL * pfCompleteRequest,
|
|
BOOL * pfFinished,
|
|
BOOL * pfHandled );
|
|
|
|
BOOL OnCompleteRequest( TCHAR * pchRequest,
|
|
DWORD cbData,
|
|
BOOL * pfFinished,
|
|
BOOL * pfHandled );
|
|
|
|
BOOL OnRestartRequest( TCHAR * pchRequest,
|
|
DWORD cbData,
|
|
BOOL * pfFinished,
|
|
BOOL * pfHandled);
|
|
|
|
BOOL HandleCertRenegotiation( BOOL * pfFinished,
|
|
BOOL * pfHandled,
|
|
DWORD cbData );
|
|
|
|
BOOL DenyAccess( BOOL * pfFinished,
|
|
BOOL * pfDisconnected );
|
|
|
|
BOOL VrootAccessCheck( PW3_METADATA pMetaData,
|
|
DWORD dwDesiredAccess );
|
|
|
|
BOOL DoChange( LPBOOL );
|
|
|
|
BOOL UnWrapRequest( BOOL * pfCompleteRequest,
|
|
BOOL * pfFinished,
|
|
BOOL * pfHandled );
|
|
|
|
//
|
|
// Attempts to logon with the user information gleaned from the Parse
|
|
// we just did
|
|
//
|
|
|
|
BOOL LogonUser( BOOL * pfFinished );
|
|
|
|
BOOL LogonAsSystem( VOID );
|
|
//
|
|
// Common header parsing functions.
|
|
//
|
|
|
|
BOOL OnContentLength ( CHAR * pszValue );
|
|
BOOL OnIfModifiedSince( CHAR * pszValue );
|
|
BOOL OnIfUnmodifiedSince( CHAR * pszValue );
|
|
BOOL OnIfMatch( CHAR * pszValue );
|
|
BOOL OnIfNoneMatch( CHAR * pszValue );
|
|
BOOL OnIfRange( CHAR * pszValue );
|
|
BOOL OnUnlessModifiedSince( CHAR * pszValue );
|
|
BOOL ProcessAuthorization ( CHAR * pszValue );
|
|
BOOL OnProxyAuthorization ( CHAR * pszValue );
|
|
BOOL OnHost ( CHAR * pszValue );
|
|
BOOL OnRange ( CHAR * pszValue );
|
|
|
|
//BOOL OnAuthorization ( CHAR * pszValue );
|
|
|
|
BOOL ParseAuthorization( CHAR * pszValue );
|
|
|
|
//
|
|
// Builds and optionally sends an HTTP server response back to the client
|
|
//
|
|
|
|
static BOOL BuildStatusLine( BUFFER * pstrResp,
|
|
DWORD dwHTTPError,
|
|
DWORD dwError2,
|
|
LPSTR pszError2 = NULL,
|
|
STR *pstrErrorStr = NULL
|
|
);
|
|
|
|
//
|
|
// Builds a complete HTTP reply with extended explanation text
|
|
//
|
|
|
|
static BOOL BuildExtendedStatus(
|
|
STR * pstrResp,
|
|
DWORD dwHTTPError,
|
|
DWORD dwError2 = NO_ERROR,
|
|
DWORD dwExplanation = 0,
|
|
LPSTR pszError2 = NULL
|
|
);
|
|
|
|
//
|
|
// Sets the http status code and win32 error that should be used for
|
|
// this request when it gets written to the logfile
|
|
//
|
|
|
|
VOID SetLogStatus( DWORD LogHttpResponse, DWORD LogWinError )
|
|
{
|
|
_dwLogHttpResponse = LogHttpResponse;
|
|
_dwLogWinError = LogWinError;
|
|
}
|
|
|
|
DWORD QueryLogHttpResponse( VOID ) const
|
|
{ return _dwLogHttpResponse; }
|
|
|
|
DWORD QueryLogWinError( VOID ) const
|
|
{ return _dwLogWinError; }
|
|
|
|
//
|
|
// Builds a server header for responding back to the client
|
|
//
|
|
|
|
BOOL BuildBaseResponseHeader(
|
|
BUFFER * pbufResponse,
|
|
BOOL * pfFinished,
|
|
STR * pstrStatus = NULL, // Full status string
|
|
DWORD dwOptions = 0 );
|
|
|
|
BOOL BuildHttpHeader( OUT BOOL * pfFinished,
|
|
IN CHAR * pchStatus = NULL,
|
|
IN CHAR * pchAdditionalHeaders = NULL,
|
|
IN DWORD dwOptions = 0);
|
|
|
|
dllexp
|
|
BOOL SendHeader( IN CHAR * pchStatus OPTIONAL,
|
|
IN CHAR * pchAdditionalHeaders OPTIONAL,
|
|
IN DWORD IOFlags,
|
|
OUT BOOL * pfFinished,
|
|
IN DWORD dwOptions = 0,
|
|
IN BOOL fWriteHeader = TRUE );
|
|
|
|
BOOL SendHeader( IN CHAR * pchHeaders,
|
|
IN DWORD cbHeaders,
|
|
IN DWORD IOFlags,
|
|
OUT BOOL * pfFinished );
|
|
|
|
//
|
|
// Builds a 301 or 302 URL Moved message
|
|
//
|
|
|
|
dllexp
|
|
BOOL BuildURLMovedResponse( BUFFER * pbufResp,
|
|
STR * pstrURL,
|
|
DWORD dwServerCode,
|
|
BOOL fIncludeParams = FALSE );
|
|
|
|
dllexp
|
|
BOOL WriteLogRecord( VOID );
|
|
|
|
BOOL AppendLogParameter( CHAR * pszParam );
|
|
|
|
//
|
|
// Sends an access denied message with the forms of authorization
|
|
// we support
|
|
//
|
|
|
|
BOOL SendAuthNeededResp( BOOL * pfFinished );
|
|
|
|
BOOL SetUserNameAndPassword( TCHAR * pszUserName, TCHAR * pszPassword )
|
|
{ return _strUserName.Copy( pszUserName ) && _strPassword.Copy( pszPassword ); }
|
|
|
|
STR * QueryDenialHeaders( VOID )
|
|
{ return &_strDenialHdrs; }
|
|
|
|
STR * QueryAdditionalRespHeaders( VOID )
|
|
{ return &_strRespHdrs; }
|
|
|
|
DWORD QueryAuthentication( VOID ) const
|
|
{ return _pMetaData->QueryAuthentication(); }
|
|
|
|
DWORD QueryNotifyExAuth( VOID ) const
|
|
{ return _pMetaData->QueryNotifyExAuth(); }
|
|
|
|
DWORD QueryDirBrowseFlags( VOID ) const
|
|
{ return _pMetaData->QueryDirBrowseFlags(); }
|
|
|
|
BOOL IsIpDnsAccessCheckPresent( VOID ) const
|
|
{ return _pMetaData->IsIpDnsAccessCheckPresent(); }
|
|
|
|
PW3_METADATA QueryMetaData( VOID ) const
|
|
{ return _pMetaData; }
|
|
//
|
|
// Retrieves various bits of request information
|
|
//
|
|
|
|
enum HTR_STATE QueryState( VOID ) const
|
|
{ return _htrState; }
|
|
|
|
BOOL IsKeepConnSet( VOID ) const
|
|
{ return _fKeepConn; }
|
|
|
|
BOOL IsProcessByteRange( VOID ) const
|
|
{ return _fProcessByteRange; }
|
|
|
|
BOOL IsAuthenticationRequested( VOID ) const
|
|
{ return _fAuthenticationRequested; }
|
|
|
|
BOOL IsAuthenticated( VOID ) const
|
|
{ return !_strUserName.IsEmpty(); }
|
|
|
|
DWORD IsChunked( VOID ) const
|
|
{ return _fChunked; }
|
|
|
|
VOID SetChunked( VOID )
|
|
{ _fChunked = TRUE; }
|
|
|
|
VOID ClearChunked( VOID )
|
|
{ _fChunked = FALSE; }
|
|
|
|
VOID SetKeepConn( BOOL fKeepConn )
|
|
{ _fKeepConn = fKeepConn; }
|
|
|
|
VOID SetAuthenticationRequested( BOOL fAuthenticationRequested )
|
|
{ _fAuthenticationRequested = fAuthenticationRequested; }
|
|
|
|
BOOL IsLoggedOn( VOID ) const
|
|
{ return _fLoggedOn; }
|
|
|
|
BOOL IsClearTextPassword( VOID ) const
|
|
{ return _fClearTextPass; };
|
|
|
|
BOOL IsNTLMImpersonation( VOID ) const
|
|
{ return !_fClearTextPass && !_fAnonymous && !UseVrAccessToken(); }
|
|
|
|
BOOL IsSecurePort( VOID ) const
|
|
{ return _fSecurePort; }
|
|
|
|
BOOL IsProxyRequest( VOID ) const
|
|
{ return _fProxyRequest; }
|
|
|
|
VOID SetProxyRequest( BOOL fIsProxyRequest )
|
|
{ _fProxyRequest = fIsProxyRequest; }
|
|
|
|
BOOL IsClientProxy( VOID );
|
|
|
|
CLIENT_CONN * QueryClientConn( VOID ) const
|
|
{ return _pClientConn; }
|
|
|
|
W3_SERVER_INSTANCE * QueryW3Instance( VOID ) const
|
|
{ return _pW3Instance; }
|
|
|
|
W3_SERVER_INSTANCE * QueryW3InstanceAggressively( VOID ) const;
|
|
|
|
VOID SetW3Instance( IN W3_SERVER_INSTANCE* pInstance )
|
|
{ DBG_ASSERT(_pW3Instance == NULL); _pW3Instance = pInstance; }
|
|
|
|
W3_SERVER_STATISTICS * QueryW3StatsObj( VOID ) const
|
|
{ return _pW3Stats; }
|
|
|
|
VOID SetW3StatsObj( IN LPW3_SERVER_STATISTICS pW3Stats )
|
|
{ _pW3Stats = pW3Stats; }
|
|
|
|
BOOL IsPointNine( VOID ) const
|
|
{ return (_VersionMajor < 1); }
|
|
|
|
BOOL IsAtLeastOneOne( VOID ) const
|
|
{ return ((_VersionMajor == 1 && _VersionMinor >= 1) ||
|
|
(_VersionMajor >= 2)); }
|
|
|
|
BOOL IsOneOne( VOID ) const
|
|
{ return ((_VersionMajor == 1) && (_VersionMinor == 1)); }
|
|
|
|
BOOL IsAuthenticating( VOID ) const
|
|
{ return _fAuthenticating; }
|
|
|
|
DWORD QueryClientContentLength( VOID ) const
|
|
{ return _cbContentLength; }
|
|
|
|
DWORD QueryTotalRequestLength( VOID ) const
|
|
{ return _cbContentLength + _cbClientRequest; }
|
|
|
|
BYTE * QueryClientRequest( VOID ) const
|
|
{ return (BYTE *) _bufClientRequest.QueryPtr(); }
|
|
|
|
BUFFER * QueryClientReqBuff( VOID )
|
|
{ return &_bufClientRequest; }
|
|
|
|
CHAR * QueryURL( VOID ) const
|
|
{ return _strURL.QueryStr(); }
|
|
|
|
CHAR * QueryURLParams( VOID ) const
|
|
{ return _strURLParams.QueryStr(); }
|
|
|
|
HTTP_HEADERS * QueryHeaderList( VOID )
|
|
{ return &_HeaderList; }
|
|
|
|
BUFFER * QueryRespBuf( VOID )
|
|
{ return &_bufServerResp; }
|
|
|
|
CHAR * QueryRespBufPtr( VOID )
|
|
{ return (CHAR *) _bufServerResp.QueryPtr(); }
|
|
|
|
DWORD QueryRespBufCB( VOID )
|
|
{ return strlen( (CHAR *)_bufServerResp.QueryPtr()); }
|
|
|
|
VOID SetDeniedFlags( DWORD dwDeniedFlags )
|
|
{ _Filter.SetDeniedFlags( dwDeniedFlags ); }
|
|
|
|
CHAR * QueryHostAddr( VOID );
|
|
|
|
//
|
|
// If the client supplied additional data in their request, we store
|
|
// the byte count and data here.
|
|
//
|
|
|
|
DWORD QueryEntityBodyCB( VOID ) const
|
|
{ return _cbEntityBody; }
|
|
|
|
DWORD QueryTotalEntityBodyCB( VOID ) const
|
|
{ return _cbTotalEntityBody; }
|
|
|
|
VOID AddTotalEntityBodyCB( DWORD cbAdditionalEntityBody )
|
|
{ _cbTotalEntityBody += cbAdditionalEntityBody; }
|
|
|
|
BYTE * QueryEntityBody( VOID ) const
|
|
{ return (BYTE *) _bufClientRequest.QueryPtr() + _cbClientRequest; }
|
|
|
|
BOOL ReadMoreEntityBody(DWORD cbOffset,
|
|
DWORD cbSize);
|
|
|
|
BOOL ReadEntityBody( BOOL *pfDone,
|
|
BOOL fFirstRead = FALSE,
|
|
DWORD dwMaxAmountToRead = 0,
|
|
BOOL *pfDisconnected = NULL );
|
|
|
|
BOOL DecodeChunkedBytes( LPBYTE lpBuffer,
|
|
LPDWORD pnBytes );
|
|
|
|
BOOL IsChunkedReadComplete( ) {
|
|
return ( _ChunkState == READ_CHUNK_DONE );
|
|
}
|
|
|
|
//
|
|
// IO Status stuff
|
|
//
|
|
|
|
VOID SetLastCompletionStatus( DWORD BytesWritten,
|
|
DWORD CompletionStatus )
|
|
{
|
|
_cbBytesWritten = BytesWritten;
|
|
_status = CompletionStatus;
|
|
|
|
//
|
|
// Do accounting for async sends so that the total bytes matches
|
|
// the number actually sent to they client.
|
|
//
|
|
// TODO: If the client disconnects then the io completion may
|
|
// complete with an error even the data was successfully sent.
|
|
// This appears to be an issue with TCP, but requires further
|
|
// investigation. (taylorw)
|
|
//
|
|
|
|
if ( _fAsyncSendPosted )
|
|
{
|
|
_cbBytesSent += BytesWritten;
|
|
_fAsyncSendPosted = FALSE;
|
|
}
|
|
}
|
|
|
|
DWORD QueryIOStatus( VOID ) const
|
|
{ return _status; }
|
|
|
|
DWORD QueryBytesWritten( VOID ) const
|
|
{ return _cbBytesWritten; }
|
|
|
|
DWORD QueryBytesReceived( VOID ) const
|
|
{ return _cbBytesReceived; }
|
|
|
|
//
|
|
// Impersonation related stuff
|
|
//
|
|
|
|
BOOL UseVrAccessToken() const
|
|
{ return _pMetaData->QueryVrAccessToken() &&
|
|
(!_pMetaData->QueryVrPassThrough() || !_tcpauth.IsForwardable()); }
|
|
|
|
|
|
BOOL ImpersonateUser( VOID )
|
|
{ return (!UseVrAccessToken() ?
|
|
_tcpauth.Impersonate() :
|
|
_pMetaData->ImpersonateVrAccessToken()
|
|
); }
|
|
|
|
VOID RevertUser( VOID )
|
|
{ (!UseVrAccessToken() ?
|
|
_tcpauth.RevertToSelf():
|
|
::RevertToSelf()
|
|
); }
|
|
|
|
HANDLE QueryPrimaryToken( HANDLE * phDelete );
|
|
|
|
HANDLE QueryImpersonationHandle( BOOL fUnused = FALSE )
|
|
{ return (UseVrAccessToken() ?
|
|
_pMetaData->QueryVrAccessToken() :
|
|
_tcpauth.QueryImpersonationToken() ); }
|
|
|
|
HANDLE QueryUserImpersonationHandle( VOID )
|
|
{ return _tcpauth.QueryImpersonationToken(); }
|
|
|
|
HANDLE QueryVrootImpersonateHandle(VOID) const
|
|
{ return UseVrAccessToken() ? _pMetaData->QueryVrAccessToken() : NULL; }
|
|
|
|
TCP_AUTHENT * QueryAuthenticationObj( VOID )
|
|
{ return &_tcpauth; }
|
|
|
|
BOOL IsValid( VOID ) const
|
|
{ return _fValid; }
|
|
|
|
//
|
|
// Forwards request to the client connection object
|
|
//
|
|
|
|
VOID Disconnect( DWORD htResp = 0,
|
|
DWORD dwError2 = NO_ERROR,
|
|
BOOL fShutdown= FALSE,
|
|
LPBOOL pfFinished = NULL );
|
|
|
|
dllexp
|
|
BOOL ReadFile( LPVOID lpBuffer,
|
|
DWORD nBytesToRead,
|
|
DWORD * pcbBytesRead, // Only for sync reads
|
|
DWORD dwFlags = IO_FLAG_ASYNC );
|
|
|
|
dllexp
|
|
BOOL WriteFile( LPVOID lpBuffer,
|
|
DWORD nBytesToRead,
|
|
DWORD * pcbBytesWritten, // Only for sync writes
|
|
DWORD dwFlags = IO_FLAG_ASYNC );
|
|
|
|
dllexp
|
|
BOOL TestConnection( VOID );
|
|
|
|
BOOL TransmitFile( TS_OPEN_FILE_INFO * pOpenFile,
|
|
HANDLE hFile,
|
|
DWORD Offset,
|
|
DWORD BytesToWrite,
|
|
DWORD dwFlags = IO_FLAG_ASYNC,
|
|
PVOID pHead = NULL,
|
|
DWORD HeadLength = 0,
|
|
PVOID pTail = NULL,
|
|
DWORD TailLength = 0);
|
|
|
|
BOOL TransmitFileTs( TS_OPEN_FILE_INFO * pOpenFile,
|
|
DWORD Offset,
|
|
DWORD BytesToWrite,
|
|
DWORD dwFlags = IO_FLAG_ASYNC,
|
|
PVOID pHead = NULL,
|
|
DWORD HeadLength = 0,
|
|
PVOID pTail = NULL,
|
|
DWORD TailLength = 0);
|
|
|
|
BOOL SyncWsaSend( WSABUF * rgWsaBuffers,
|
|
DWORD cWsaBuffers,
|
|
LPDWORD pcbWritten );
|
|
|
|
|
|
BOOL PostCompletionStatus( DWORD cbBytesTransferred );
|
|
|
|
DWORD Reference( VOID );
|
|
DWORD Dereference( VOID );
|
|
DWORD QueryRefCount( VOID );
|
|
|
|
//
|
|
// Reset is called at the beginning of every request
|
|
//
|
|
|
|
virtual BOOL Reset( BOOL fResetPipelineInfo );
|
|
virtual VOID ReleaseCacheInfo( VOID );
|
|
|
|
|
|
//
|
|
// Called to reset Authentication status
|
|
//
|
|
|
|
BOOL ResetAuth( BOOL fSessionTerminated = TRUE );
|
|
|
|
// added these methods for exposing them to the Server extension processor
|
|
dllexp
|
|
const STR & QueryContentTypeStr( void) const { return ( _strContentType); }
|
|
dllexp
|
|
const STR & QueryMethodStr( void) const { return ( _strMethod); }
|
|
|
|
dllexp
|
|
const STR & QueryURLStr(void) const { return ( _strURL); }
|
|
|
|
dllexp
|
|
const STR & QueryPhysicalPathStr( void) const { return ( _strPhysicalPath); }
|
|
|
|
dllexp
|
|
const LPSTR QueryExpireHeader( void ) const
|
|
{ return ( _pMetaData->QueryExpireHeader() ); }
|
|
|
|
|
|
//
|
|
// Called at the beginning and end of a TCP session
|
|
//
|
|
|
|
VOID InitializeSession( CLIENT_CONN * pConn,
|
|
PVOID pvInitialBuff,
|
|
DWORD cbInitialBuff );
|
|
|
|
virtual VOID EndOfRequest( VOID ) = 0;
|
|
virtual VOID SessionTerminated( VOID );
|
|
|
|
//
|
|
// Generally when the state is set to HTR_DONE
|
|
//
|
|
|
|
VOID SetState( enum HTR_STATE htrstate,
|
|
DWORD dwLogHttpResponse = HT_DONT_LOG,
|
|
DWORD dwLogWinError = NO_ERROR )
|
|
{ _htrState = htrstate;
|
|
_dwLogHttpResponse = dwLogHttpResponse;
|
|
_dwLogWinError = dwLogWinError;
|
|
}
|
|
|
|
BOOL SetCertificateInfo( PHTTP_FILTER_CERTIFICATE_INFO pData,
|
|
CtxtHandle* pCtxt,
|
|
HANDLE hImpersonationToken,
|
|
HTTP_FILTER_DLL* pFilter );
|
|
|
|
BOOL CheckValidSSPILogin( VOID );
|
|
|
|
BOOL NotifyRequestSecurityContextClose( CtxtHandle *pH )
|
|
{ return _pAuthFilter ? _Filter.NotifyRequestSecurityContextClose( _pAuthFilter,
|
|
pH ) : TRUE; }
|
|
|
|
dllexp
|
|
BOOL CheckForBasicAuthenticationHeader( LPSTR pszHeaders );
|
|
|
|
BOOL IsAnonymous( VOID ) const
|
|
{ return _fAnonymous; }
|
|
|
|
HTTP_FILTER * QueryFilter( VOID )
|
|
{ return &_Filter; }
|
|
|
|
BOOL CheckCustomError(BUFFER *pBuf, DWORD dwErr, DWORD dwSubError,
|
|
BOOL *pfFinished, DWORD *pdwMsgSize, BOOL bCheckURL = TRUE);
|
|
|
|
VOID SetNoCache( VOID )
|
|
{ _bForceNoCache = 1; }
|
|
|
|
VOID ClearNoCache( VOID )
|
|
{ _bForceNoCache = 0; }
|
|
|
|
DWORD QueryNoCache( VOID)
|
|
{ return _bForceNoCache; }
|
|
|
|
VOID SetSendVary( VOID )
|
|
{ _bSendVary = 1; }
|
|
|
|
VOID ClearSendVary( VOID )
|
|
{ _bSendVary = 0; }
|
|
|
|
VOID ToggleSendCL( VOID )
|
|
{ _bSendContentLocation ^= 1; }
|
|
|
|
VOID SetSendCL( VOID )
|
|
{ _bSendContentLocation = 1; }
|
|
|
|
VOID ClearSendCL( VOID )
|
|
{ _bSendContentLocation = 0; }
|
|
|
|
BOOL IsCGIRequest( VOID ) const
|
|
{ return _GatewayType == GATEWAY_CGI; }
|
|
|
|
//
|
|
// The request looks like a gateway request (but may just be a poorly named
|
|
// directory)
|
|
//
|
|
|
|
BOOL IsProbablyGatewayRequest( VOID ) const
|
|
{ return (_GatewayType & GT_GATEWAY_REQUEST); }
|
|
|
|
enum HTTP_VERB QueryVerb( VOID ) const
|
|
{ return _verb; }
|
|
|
|
|
|
virtual DWORD BuildAllowHeader(CHAR *pszURL, CHAR *pszTail) = 0;
|
|
|
|
//
|
|
// Set the time for start of processing
|
|
//
|
|
|
|
VOID SetRequestStartTime( VOID )
|
|
{ if (!_fStartTimeValid) { _msStartRequest= GetCurrentTime(); _fStartTimeValid= TRUE;}}
|
|
|
|
|
|
HANDLE GetFileHandle( TS_OPEN_FILE_INFO * pOpenFile )
|
|
{
|
|
HANDLE hHandle = INVALID_HANDLE_VALUE;
|
|
|
|
if ( pOpenFile )
|
|
{
|
|
if ( ImpersonateUser() )
|
|
{
|
|
hHandle = pOpenFile->QueryFileHandle();
|
|
RevertUser();
|
|
}
|
|
}
|
|
return hHandle;
|
|
}
|
|
|
|
VOID IncrementBytesSeenByRawReadFilter( DWORD cbBytesSeen )
|
|
{
|
|
_cbOldData += cbBytesSeen;
|
|
}
|
|
|
|
protected:
|
|
|
|
//
|
|
// Breaks out the simple authorization info
|
|
//
|
|
|
|
BOOL ExtractClearNameAndPswd( CHAR * pch,
|
|
STR * pstrUserName,
|
|
STR * pstrPassword,
|
|
BOOL fUUEncoded );
|
|
|
|
//
|
|
// Appends the forms of authentication the server supports to the
|
|
// server response string
|
|
//
|
|
|
|
BOOL AppendAuthenticationHdrs( STR * pstrAuthHdrs,
|
|
BOOL * pfFinished );
|
|
|
|
|
|
//
|
|
// Data members
|
|
//
|
|
|
|
//
|
|
// Points to connection object we are communicating on
|
|
//
|
|
|
|
CLIENT_CONN * _pClientConn;
|
|
|
|
// Meta data info for this request.
|
|
|
|
PW3_METADATA _pMetaData;
|
|
|
|
// URI related info (file and metadata) for this request.
|
|
|
|
PW3_URI_INFO _pURIInfo;
|
|
|
|
//
|
|
// Points to the w3 instance
|
|
//
|
|
|
|
W3_SERVER_INSTANCE * _pW3Instance;
|
|
|
|
//
|
|
// Points to server instance's statistics object.
|
|
//
|
|
|
|
W3_SERVER_STATISTICS * _pW3Stats;
|
|
|
|
//
|
|
// Action the client is requesting
|
|
//
|
|
|
|
enum HTTP_VERB _verb;
|
|
|
|
//
|
|
// Statistics trackers
|
|
//
|
|
|
|
DWORD _cFilesSent;
|
|
DWORD _cFilesReceived;
|
|
DWORD _cbBytesSent; // Total for this request
|
|
DWORD _cbBytesReceived;
|
|
|
|
DWORD _cbTotalBytesSent; // Total for all requests using this
|
|
DWORD _cbTotalBytesReceived; // object
|
|
|
|
|
|
//
|
|
// Flags
|
|
//
|
|
|
|
BOOL _fValid:1; // TRUE if this object constructed successfully
|
|
BOOL _fKeepConn:1; // Pragma: Keep-connection was specified
|
|
BOOL _fAuthenticationRequested:1; // request client authentication
|
|
BOOL _fLoggedOn:1; // A user was successfully logged on
|
|
BOOL _fAnonymous:1; // The user is using the Anonymous user token
|
|
BOOL _fSecurePort; // This request is coming over an encrypted port
|
|
BOOL _fMappedAcct:1; // The user is using a mapped account
|
|
BOOL _fClearTextPass:1; // The user supplied a clear text password
|
|
BOOL _fAuthenticating:1; // We're in an NT authentication conversation
|
|
BOOL _fBasicRealm:1; // TRUE if realm specified
|
|
BOOL _fAuthSystem:1;
|
|
BOOL _fAuthCert:1;
|
|
BOOL _fInvalidAccessToken:1;
|
|
|
|
BOOL _fAsyncSendPosted:1; // TRUE when we send data to the client asychronously
|
|
|
|
BOOL _fChunked:1; // TRUE iff the entity body is in the chunked
|
|
// transfer-encoding
|
|
BOOL _fDiscNoError:1; // TRUE if we're to disconnect w/o an error.
|
|
BOOL _fNoDisconnectOnError:1; // TRUE if we're not to disconnect on an early error.
|
|
|
|
BOOL _fProxyRequest:1; // This is request is a proxy request
|
|
|
|
// Accept range variables
|
|
|
|
BOOL _fAcceptRange:1; // TRUE if the referenced file accept byte ranges
|
|
BOOL _fProcessByteRange:1; // TRUE while processing a byte range request
|
|
BOOL _fUnsatisfiableByteRange:1; // TRUE if an unsatisfiable byte range was encountered
|
|
BOOL _fMimeMultipart:1; // TRUE if generating a MIME multipart message
|
|
BOOL _fIfModifier:1; // TRUE if we've seen an If-Match, etc.
|
|
BOOL _fHaveContentLength:1;// Set to TRUE if we've seen a content length
|
|
// on this requests.
|
|
BOOL _fLogRecordWritten:1; // TRUE if we've written a log record
|
|
DWORD _iRangeIdx; // index in strRange string
|
|
DWORD _dwRgNxOffset; // next range offset
|
|
DWORD _dwRgNxSizeToSend; // next range size
|
|
DWORD _cbMimeMultipart; // length of a MIME multipart message body
|
|
|
|
//
|
|
// The state of the HTTP request
|
|
//
|
|
|
|
enum HTR_STATE _htrState;
|
|
|
|
enum GATEWAY_TYPE _GatewayType; // BGI vs CGI vs BAT
|
|
|
|
//
|
|
// List of raw headers passed by client
|
|
//
|
|
|
|
HTTP_HEADERS _HeaderList;
|
|
|
|
//
|
|
// Client protocol version information
|
|
//
|
|
|
|
BYTE _VersionMajor;
|
|
BYTE _VersionMinor;
|
|
|
|
//
|
|
// If the client is passing data to a gateway, they will specify
|
|
// the length and type in a Content-length/type header that is stored
|
|
// here
|
|
//
|
|
|
|
STR _strContentType;
|
|
UINT _cbContentLength;
|
|
|
|
//
|
|
// The URL the client is requesting
|
|
//
|
|
|
|
STR _strURL; // Just the URL
|
|
STR _strURLPathInfo; // Combined URL and script path info
|
|
STR _strURLParams; // Just the params (w/o '?')
|
|
STR _strLogParams; // Copy of _strURLParams for logging
|
|
STR _strPathInfo; // Additional script path info
|
|
STR _strRawURL; // Combined URL and params
|
|
STR _strOriginalURL; // URL before being passed to filters
|
|
|
|
//
|
|
// Various other pieces of data in the HTTP request we care about
|
|
//
|
|
|
|
STR _strMethod; // GET, HEAD, POST etc.
|
|
STR _strAuthType; // "user", "kerberos", "nt" etc.
|
|
STR _strAuthInfo; // Current SSP authorization blob
|
|
STR _strUserName; // The user name (empty if Guest)
|
|
STR _strPassword; // Temporarily holds the password
|
|
STR _strUnmappedUserName; // User before filter mappings
|
|
STR _strUnmappedPassword; // Password before filter mappings
|
|
|
|
STR _strPhysicalPath; // Physical path of URL (maybe empty)
|
|
STR _strUnmappedPhysicalPath; // unmapped Physical path of URL (maybe empty)
|
|
|
|
STR _strRespHdrs; // Optional headers from filters
|
|
STR _strDenialHdrs; // Optional headers from filters
|
|
// to add if request is denied
|
|
STR _strHostAddr; // Host address as a domain name
|
|
STR _strRange;
|
|
|
|
BOOL _fAuthTypeDigest; // is auth type Digest/NT-Digest
|
|
LARGE_INTEGER _liModifiedSince; // Contains If-Modified-Since time
|
|
LARGE_INTEGER _liUnlessModifiedSince; // Contains Unless-Modified-Since time
|
|
LARGE_INTEGER _liUnmodifiedSince; // Contains If-Unmodified-Since time
|
|
DWORD _dwExpireInDay; // # of days before pwd expiration
|
|
// or 0x7fffffff if n/a
|
|
DWORD _dwModifiedSinceLength; // Length parameter passed in with IMS.
|
|
|
|
BOOL _bProcessingCustomError:1; // TRUE if we're processing a custom error.
|
|
BOOL _bForceNoCache:1; // Set to TRUE if must force no-cache.
|
|
BOOL _bSendContentLocation:1; // Set to TRUE if we need to send C-L:
|
|
BOOL _bSendVary:1; // Set to TRUE if we need to send Vary: *.
|
|
|
|
//
|
|
// Encapsulates authentication and impersonation code
|
|
//
|
|
|
|
BOOL _fSingleRequestAuth:1;
|
|
TCP_AUTHENT _tcpauth;
|
|
|
|
//
|
|
// Used to calculate the time of this request
|
|
//
|
|
|
|
BOOL _fStartTimeValid:1;
|
|
DWORD _msStartRequest;
|
|
|
|
//
|
|
// Filter context information
|
|
//
|
|
|
|
HTTP_FILTER _Filter;
|
|
HTTP_FILTER_DLL * _pAuthFilter;
|
|
|
|
//
|
|
// Contains the HTTP client request buffer
|
|
// _cbClientRequest indicates the number of bytes in the HTTP request
|
|
// (excluding gateway data)
|
|
// _cbOldData - Number of bytes in buffer raw read filters have already
|
|
// seen
|
|
// _cbEntityBody - Number of bytes of entity body currently in buffer
|
|
// _cbTotalEntityBody - Number of bytes expected in entity body.
|
|
// _cbChunkHeader - Number of bytes in chunk header processed.
|
|
// _cbChunkBytesRead - Number of bytes in the current transfer-encoded
|
|
// chunk we've read.
|
|
// _cbExtraData - Number of 'extra' bytes in buffer.
|
|
// _pchExtraData - Pointer to start of 'extra' bytes.
|
|
//
|
|
|
|
BUFFER _bufClientRequest;
|
|
DWORD _cbClientRequest;
|
|
DWORD _cbOldData;
|
|
DWORD _cbEntityBody;
|
|
DWORD _cbTotalEntityBody;
|
|
DWORD _cbChunkHeader;
|
|
DWORD _cbChunkBytesRead;
|
|
DWORD _cbExtraData;
|
|
CHAR *_pchExtraData;
|
|
|
|
//
|
|
// Contains the server response buffer, generally only used for response
|
|
// headers
|
|
//
|
|
|
|
BUFFER _bufServerResp;
|
|
|
|
//
|
|
// Stores the results of the last IO request
|
|
//
|
|
|
|
APIERR _status;
|
|
DWORD _cbBytesWritten;
|
|
DWORD _cbRestartBytesWritten;
|
|
DWORD _dwRenegotiated;
|
|
DWORD _dwSslNegoFlags;
|
|
AC_RESULT _acIpAccess;
|
|
BOOL _fNeedDnsCheck;
|
|
|
|
//
|
|
// Stores the request codes to write to the request log
|
|
//
|
|
|
|
DWORD _dwLogHttpResponse;
|
|
DWORD _dwLogWinError;
|
|
|
|
// Information used for decoding chunked requests.
|
|
|
|
enum CHUNK_STATE _ChunkState;
|
|
DWORD _dwChunkSize; // reset value is -1 => chunk size not sent.
|
|
BYTE _CRCount;
|
|
BYTE _LFCount;
|
|
|
|
BUFFER _bufLastAnonAcctDesc;
|
|
DWORD _cbLastAnonAcctDesc;
|
|
|
|
#if defined(CAL_ENABLED)
|
|
LPVOID m_pCalAuthCtxt;
|
|
LPVOID m_pCalSslCtxt;
|
|
#endif
|
|
|
|
VOID * m_ppvFrames[ MAX_BACKTRACE_FRAMES ];
|
|
};
|
|
|
|
#define CERT_NEGO_SUCCESS 1
|
|
#define CERT_NEGO_FAILURE 2
|
|
|
|
//
|
|
// Macro to check for both normal and localhost access
|
|
//
|
|
|
|
#define IS_ACCESS_ALLOWED(op) ( \
|
|
((GetFilePerms() & VROOT_MASK_## op) != 0) && \
|
|
(((GetFilePerms() & VROOT_MASK_NO_REMOTE_## op) == 0) || \
|
|
IsIPAddressLocal( \
|
|
QueryClientConn()->QueryLocalIPAddress(), \
|
|
QueryClientConn()->QueryRemoteIPAddress()) ) )
|
|
|
|
#define IS_ACCESS_ALLOWED2(_pExec, op) ( \
|
|
((_pExec->_pMetaData->QueryAccessPerms() & VROOT_MASK_## op) != 0) && \
|
|
(((_pExec->_pMetaData->QueryAccessPerms() & VROOT_MASK_NO_REMOTE_## op) == 0) || \
|
|
IsIPAddressLocal( \
|
|
QueryClientConn()->QueryLocalIPAddress(), \
|
|
QueryClientConn()->QueryRemoteIPAddress()) ) )
|
|
|
|
# endif // _BASEREQ_HXX_
|
|
|
|
|