/*++ Copyright (c) 2001 Microsoft Corporation Module Name: w3wplisthttpreq.cxx Abstract: implementation of class W3wpListHttpReq. This class reads in all the relevant info from the http_request. Author: Hamid Mahmood (t-hamidm) 08-13-2001 Revision History: --*/ #include "precomp.hxx" CHAR W3wpListHttpReq::sm_chHttpHeaderVerbosityLevel[HttpHeaderMaximum] = { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 4,4,4,3,4,4,4,4,4,4,4,4,4,4,3,4,4,4,3 }; W3wpListHttpReq::W3wpListHttpReq() /*++ Routine Description: Constructor Arguments: None Return Value: none --*/ { m_httpRequestId = 0; m_dwNumUnknownHeaders = 0; m_httpVerb = HttpVerbMaximum; m_majorVersion = 0; m_minorVersion = 0; m_fIsHeaderPresent = FALSE; m_pszURI = NULL; m_pszHostName = NULL; m_pszUnknownVerb = NULL; m_pszQueryString = NULL; m_pszDateTime = NULL; m_pszClientIP = NULL; for (DWORD i = 0; i < HttpHeaderMaximum; i++) { m_ppszKnownHeaders[i] = NULL; } m_ppszUnknownHeaderNames = NULL; m_ppszUnknownHeaderValues = NULL; m_dwSignature = W3WPLIST_HTTP_REQ_SIGNATURE; } W3wpListHttpReq::~W3wpListHttpReq() /*++ Routine Description: Destructor Arguments: None Return Value: none --*/ { DBG_ASSERT (m_dwSignature == W3WPLIST_HTTP_REQ_SIGNATURE); m_dwSignature = W3WPLIST_HTTP_REQ_SIGNATURE_FREE; DBG_ASSERT(m_httpRequestId == 0); DBG_ASSERT(m_dwNumUnknownHeaders == 0); DBG_ASSERT(m_httpVerb == HttpVerbMaximum); DBG_ASSERT(m_majorVersion == 0); DBG_ASSERT(m_minorVersion == 0); DBG_ASSERT(m_fIsHeaderPresent == FALSE); DBG_ASSERT(m_pszURI == NULL); DBG_ASSERT(m_pszHostName == NULL); DBG_ASSERT(m_pszUnknownVerb == NULL); DBG_ASSERT(m_pszQueryString == NULL); DBG_ASSERT(m_pszDateTime == NULL); DBG_ASSERT(m_pszClientIP == NULL); for (DWORD i = 0; i < HttpHeaderMaximum; i++) { DBG_ASSERT(m_ppszKnownHeaders[i] == NULL); } DBG_ASSERT(m_ppszUnknownHeaderNames == NULL); DBG_ASSERT(m_ppszUnknownHeaderValues == NULL); }; VOID W3wpListHttpReq::Terminate() /*++ Routine Description: Deallocates memory Arguments: None Return Value: none --*/ { m_httpRequestId = 0; m_httpVerb = HttpVerbMaximum; m_fIsHeaderPresent = FALSE; m_minorVersion = 0; m_majorVersion = 0; delete[] m_pszURI; m_pszURI = NULL; delete[] m_pszHostName; m_pszHostName = NULL; delete[] m_pszUnknownVerb; m_pszUnknownVerb = NULL; delete[] m_pszQueryString; m_pszQueryString = NULL; delete[] m_pszDateTime; m_pszDateTime = NULL; delete[] m_pszClientIP; m_pszClientIP = NULL; for (DWORD i = 0; i < HttpHeaderMaximum; i++) { delete[] m_ppszKnownHeaders[i]; m_ppszKnownHeaders[i] = NULL; } for (DWORD i = 0; i < m_dwNumUnknownHeaders; i++) { delete[] m_ppszUnknownHeaderNames[i]; m_ppszUnknownHeaderNames[i] = NULL; delete[] m_ppszUnknownHeaderValues[i]; m_ppszUnknownHeaderValues[i] = NULL; } m_ppszUnknownHeaderNames = NULL; m_ppszUnknownHeaderValues = NULL; m_dwNumUnknownHeaders = 0; } HRESULT W3wpListHttpReq::ReadFromWorkerProcess( HANDLE hProcess, HTTP_REQUEST* pHttpRequest, CHAR chVerbosity ) /*++ Routine Description: Reads in the relevant info from the input http_request *. Arguments: hProcess -- input PID pHttpRequest -- * to HTTP_REQEUST obj in worker process chVerbosity -- verbosity level Return Value: HRESULT -- S_OK if success, otherwise E_FAIL --*/ { BOOL fReadMemStatus = FALSE; SIZE_T stNumBytesRead; DWORD dwStrSize = 0; PHTTP_UNKNOWN_HEADER pUnknownHeadersInRemoteProcess = NULL; HTTP_UNKNOWN_HEADER unknownHeader; HRESULT hr = S_OK; // // check for Ctrl+C, Ctrl+Break, etc // if ( CONSOLE_HANDLER_VAR::g_HAS_CONSOLE_EVENT_OCCURED == TRUE ) { hr = E_FAIL; goto end; } m_httpRequestId = pHttpRequest->RequestId; m_httpVerb = pHttpRequest->Verb; // // read in the unknown verb // dwStrSize = pHttpRequest->UnknownVerbLength; if ( dwStrSize != 0 ) { m_pszUnknownVerb = new CHAR[dwStrSize + 1]; if ( m_pszUnknownVerb == NULL ) // new failed { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->pUnknownVerb, m_pszUnknownVerb, pHttpRequest->UnknownVerbLength, &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } m_pszUnknownVerb[dwStrSize] = '\0'; } // // read in the Hostname // dwStrSize = pHttpRequest->CookedUrl.HostLength / sizeof(WCHAR); if ( dwStrSize != 0 ) { m_pszHostName = new WCHAR[dwStrSize + 1]; if ( m_pszHostName == NULL ) // new failed { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->CookedUrl.pHost, m_pszHostName, pHttpRequest->CookedUrl.HostLength, &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } m_pszHostName[dwStrSize] = L'\0'; } // // read in the AbsPath // dwStrSize = pHttpRequest->CookedUrl.AbsPathLength / sizeof(WCHAR); if ( dwStrSize != 0 ) { m_pszURI = new WCHAR[dwStrSize + 1]; if ( m_pszURI == NULL ) // new failed { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->CookedUrl.pAbsPath, m_pszURI, pHttpRequest->CookedUrl.AbsPathLength, &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } m_pszURI[dwStrSize] = L'\0'; } // // The rest is read in only if verbosity level is high enough // if ( chVerbosity < 2 ) { goto end; } // // save protocol info // m_majorVersion = pHttpRequest->Version.MajorVersion; m_minorVersion = pHttpRequest->Version.MinorVersion; // // read in the QueryString // dwStrSize = pHttpRequest->CookedUrl.QueryStringLength / sizeof(WCHAR); if ( dwStrSize != 0 ) { m_pszQueryString = new WCHAR[dwStrSize + 1]; if ( m_pszQueryString == NULL ) // new failed { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->CookedUrl.pQueryString, m_pszQueryString, pHttpRequest->CookedUrl.QueryStringLength, &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } m_pszQueryString[dwStrSize] = L'\0'; } // Read verbosity 3 stuff; if ( chVerbosity < 3 ) { goto end; } // // Client - IP // if ( pHttpRequest->Address.pRemoteAddress != NULL ) { SOCKADDR_STORAGE SockAddr; CHAR szNumericAddress[NI_MAXHOST]; if( pHttpRequest->Address.pLocalAddress->sa_family == AF_INET ) { SOCKADDR_IN * pSockaddr_In = ( SOCKADDR_IN * )&SockAddr; fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->Address.pRemoteAddress, pSockaddr_In, sizeof(SOCKADDR_IN), &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } if( getnameinfo( ( LPSOCKADDR )&SockAddr, sizeof( SOCKADDR_IN ), szNumericAddress, sizeof( szNumericAddress ), NULL, 0, NI_NUMERICHOST ) != 0 ) { hr = HRESULT_FROM_WIN32( WSAGetLastError() ); goto end; } } else if( pHttpRequest->Address.pLocalAddress->sa_family == AF_INET6 ) { SOCKADDR_IN6 * pSockaddr_In6 = ( SOCKADDR_IN6 * )&SockAddr; fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->Address.pRemoteAddress, pSockaddr_In6, sizeof(SOCKADDR_IN6), &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } if( getnameinfo( ( LPSOCKADDR )&SockAddr, sizeof( SOCKADDR_IN6 ), szNumericAddress, sizeof( szNumericAddress ), NULL, 0, NI_NUMERICHOST ) != 0 ) { hr = HRESULT_FROM_WIN32( WSAGetLastError() ); goto end; } } else { DBG_ASSERT( FALSE ); } m_pszClientIP = new CHAR[strlen( szNumericAddress ) + 1]; if ( m_pszClientIP == NULL ) { hr = E_FAIL; goto end; } strcpy( m_pszClientIP, szNumericAddress ); } // // read headers, verbosity level for each header is // defined in sm_chHttpHeaderVerbosityLevel array // for( DWORD i = 0; i < HttpHeaderMaximum; i++) { // // match verbosity level from the static array // if ( sm_chHttpHeaderVerbosityLevel[i] <= chVerbosity ) { dwStrSize = pHttpRequest->Headers.KnownHeaders[i].RawValueLength; if ( dwStrSize != 0 ) { m_fIsHeaderPresent = TRUE; m_ppszKnownHeaders[i] = new CHAR[dwStrSize + 1]; if (m_ppszKnownHeaders[i] == NULL) { hr = E_FAIL; goto end;; } fReadMemStatus = ReadProcessMemory( hProcess, pHttpRequest->Headers.KnownHeaders[i].pRawValue, m_ppszKnownHeaders[i], pHttpRequest->Headers.KnownHeaders[i].RawValueLength, &stNumBytesRead ); if ( fReadMemStatus == FALSE ) { hr = E_FAIL; goto end; } m_ppszKnownHeaders[i][dwStrSize] = '\0'; } } // verbosity level check } // end for loop if ( chVerbosity < 4 ) { goto end; } // // read in unknown headers // m_dwNumUnknownHeaders = pHttpRequest->Headers.UnknownHeaderCount; if ( m_dwNumUnknownHeaders > 0 ) // some unknown headers exist { m_fIsHeaderPresent = TRUE; pUnknownHeadersInRemoteProcess = pHttpRequest->Headers.pUnknownHeaders; // // allocate memory for unknown headers // m_ppszUnknownHeaderNames = new CHAR*[m_dwNumUnknownHeaders]; if ( m_ppszUnknownHeaderNames == NULL ) { hr = E_FAIL; goto end; } m_ppszUnknownHeaderValues = new CHAR*[m_dwNumUnknownHeaders]; if ( m_ppszUnknownHeaderValues == NULL ) { hr = E_FAIL; goto end; } // // read in all the unknown headers // for (DWORD i = 0 ; i < m_dwNumUnknownHeaders; i++ , pUnknownHeadersInRemoteProcess++) { // // read in the unknown header struct // fReadMemStatus = ReadProcessMemory( hProcess, pUnknownHeadersInRemoteProcess, &unknownHeader, sizeof(HTTP_UNKNOWN_HEADER), &stNumBytesRead ); if (fReadMemStatus == FALSE) { hr = E_FAIL; goto end; } // // read in the name of the header // dwStrSize = unknownHeader.NameLength; m_ppszUnknownHeaderNames[i] = new CHAR[dwStrSize + 1]; if ( m_ppszUnknownHeaderNames[i] == NULL) { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, unknownHeader.pName, m_ppszUnknownHeaderNames[i], unknownHeader.NameLength, &stNumBytesRead ); if (fReadMemStatus == FALSE) { hr = E_FAIL; goto end; } m_ppszUnknownHeaderNames[i][dwStrSize] = '\0'; // // read in the value of the header // dwStrSize = unknownHeader.RawValueLength; m_ppszUnknownHeaderValues[i] = new CHAR[dwStrSize + 1]; if ( m_ppszUnknownHeaderValues[i] == NULL) { hr = E_FAIL; goto end; } fReadMemStatus = ReadProcessMemory( hProcess, unknownHeader.pRawValue, m_ppszUnknownHeaderValues[i], unknownHeader.RawValueLength, &stNumBytesRead ); if (fReadMemStatus == FALSE) { hr = E_FAIL; goto end; } m_ppszUnknownHeaderValues[i][dwStrSize] = '\0'; } // for loop pUnknownHeadersInRemoteProcess = NULL; } // if unknown headers exists end: return hr; } VOID W3wpListHttpReq::Print(CHAR chVerbosity) /*++ Routine Description: Outputs request info dependent on the verbosity level. Arguments: chVerbosity -- verbosity level Return Value: None --*/ { #define MAX_TAG_WIDTH_1 12 #define MAX_TAG_WIDTH_2 20 enum{ URI = 0, HOSTNAME, PROTOCOL, METHOD, QUERY, CLIENT_IP, REQUEST_ID, DATE_TIME, HEADERS }; WCHAR* pOutputTags[] = { L"URI", L"Hostname", L"Protocol", L"Method", L"Query", L"Client-IP", L"Request Id", L"Date/Time", L"Headers" }; WCHAR * pVerbs[] = { L"Unparsed", L"Unknown", L"Invalid", L"OPTIONS", L"GET", L"HEAD", L"POST", L"PUT", L"DELETE", L"TRACE", L"CONNECT", L"TRACK", L"MOVE", L"COPY", L"PROPFIND", L"PROPPATCH", L"MKCOL", L"LOCK", L"UNLOCK", L"SEARCH", }; WCHAR* pOutputHeaderNames[] = { L"Cache-Control", L"Connection", L"Date", L"Keep-Alive", L"Pragma", L"Trailer", L"Transfer-Encoding", L"Upgrade", L"Via", L"Warning", L"Allow", L"Content-Length", L"Content-Type", L"Content-Encoding", L"Content-Language", L"Content-Location", L"Content-Md5", L"Content-Range", L"Expires", L"LastModified", L"Accept", L"Accept-Charset", L"Accept-Encoding", L"Accept-Language", L"Authorization", L"Cookie", L"Expect", L"From", L"Host", L"If-Match", L"If-Modified-Since", L"If-NoneMatch", L"If-Range", L"If-Unmodified-Since", L"Max-Forwards", L"Proxy-Authorization", L"Referer", L"Range", L"Te", L"Translate", L"UserAgent" }; DBG_ASSERT (chVerbosity > 0); wprintf ( L"%-*s: %u\n", MAX_TAG_WIDTH_1, pOutputTags[REQUEST_ID], m_httpRequestId ); wprintf ( L" %-*s: %s\n", MAX_TAG_WIDTH_1, pOutputTags[URI], m_pszURI ); wprintf ( L" %-*s: %s\n", MAX_TAG_WIDTH_1, pOutputTags[HOSTNAME], m_pszHostName ); if ( m_httpVerb != HttpVerbUnknown) { wprintf ( L" %-*s: %s\n", MAX_TAG_WIDTH_1, pOutputTags[METHOD], pVerbs[m_httpVerb] ); } else { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_1, pOutputTags[METHOD], m_pszUnknownVerb ); } if ( chVerbosity < 2 ) { goto end; } wprintf ( L" %-*s: HTTP/%d.%d\n", MAX_TAG_WIDTH_1, pOutputTags[PROTOCOL], m_majorVersion, m_minorVersion ); if ( m_pszQueryString != NULL ) { wprintf ( L" %-*s: %s\n", MAX_TAG_WIDTH_1, pOutputTags[QUERY], m_pszQueryString ); } if ( chVerbosity < 3 ) { goto end; } if ( m_pszClientIP != NULL ) { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_1, pOutputTags[CLIENT_IP], m_pszClientIP ); } if ( m_fIsHeaderPresent != TRUE ) { goto end; } wprintf ( L" %-*s:\n", MAX_TAG_WIDTH_1, pOutputTags[HEADERS] ); if ( m_ppszKnownHeaders[HttpHeaderReferer] != NULL ) { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_2, pOutputHeaderNames[HttpHeaderReferer], m_ppszKnownHeaders[HttpHeaderReferer] ); } if ( m_ppszKnownHeaders[HttpHeaderUserAgent] != NULL ) { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_2, pOutputHeaderNames[HttpHeaderUserAgent], m_ppszKnownHeaders[HttpHeaderUserAgent] ); } if ( m_ppszKnownHeaders[HttpHeaderCookie] != NULL ) { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_2, pOutputHeaderNames[HttpHeaderCookie], m_ppszKnownHeaders[HttpHeaderCookie] ); } if ( chVerbosity < 4 ) { goto end; } for( DWORD i = 0; i < HttpHeaderMaximum; i++) { if ( ( i != HttpHeaderCookie ) && ( i != HttpHeaderUserAgent ) && ( i != HttpHeaderReferer ) ) { if ( m_ppszKnownHeaders[i] != NULL ) { printf ( " %-*S: %s\n", MAX_TAG_WIDTH_2, pOutputHeaderNames[i], m_ppszKnownHeaders[i] ); } } } // end for loop // for loop for ( DWORD i = 0; i < m_dwNumUnknownHeaders; i++) { printf ( " %-*s: %s\n", MAX_TAG_WIDTH_2, m_ppszUnknownHeaderNames[i], m_ppszUnknownHeaderValues[i] ); } end: return; }