Process Hacker
whois.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Network Tools -
3  * Whois dialog
4  *
5  * Copyright (C) 2013 dmex
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #pragma comment(lib, "Winhttp.lib")
24 
25 #include "nettools.h"
26 #include <mxml.h>
27 #include <winhttp.h>
28 
29 static BOOLEAN ReadRequestString(
30  _In_ HINTERNET Handle,
31  _Out_ _Deref_post_z_cap_(*DataLength) PSTR *Data,
32  _Out_ ULONG *DataLength
33  )
34 {
35  PSTR data;
36  ULONG allocatedLength;
37  ULONG dataLength;
38  ULONG returnLength;
39  BYTE buffer[PAGE_SIZE];
40 
41  allocatedLength = sizeof(buffer);
42  data = (PSTR)PhAllocate(allocatedLength);
43  dataLength = 0;
44 
45  // Zero the buffer
46  memset(buffer, 0, PAGE_SIZE);
47 
48  while (WinHttpReadData(Handle, buffer, PAGE_SIZE, &returnLength))
49  {
50  if (returnLength == 0)
51  break;
52 
53  if (allocatedLength < dataLength + returnLength)
54  {
55  allocatedLength *= 2;
56  data = (PSTR)PhReAllocate(data, allocatedLength);
57  }
58 
59  // Copy the returned buffer into our pointer
60  memcpy(data + dataLength, buffer, returnLength);
61  // Zero the returned buffer for the next loop
62  //memset(buffer, 0, returnLength);
63 
64  dataLength += returnLength;
65  }
66 
67  if (allocatedLength < dataLength + 1)
68  {
69  allocatedLength++;
70  data = (PSTR)PhReAllocate(data, allocatedLength);
71  }
72 
73  // Ensure that the buffer is null-terminated.
74  data[dataLength] = 0;
75 
76  *DataLength = dataLength;
77  *Data = data;
78 
79  return TRUE;
80 }
81 
83  _In_ PVOID Parameter
84  )
85 {
86  BOOLEAN isSuccess = FALSE;
87  ULONG xmlLength = 0;
88  PSTR xmlBuffer = NULL;
89  PPH_STRING phVersion = NULL;
90  PPH_STRING userAgent = NULL;
91  PPH_STRING whoisHttpGetString = NULL;
92  HINTERNET connectionHandle = NULL;
93  HINTERNET requestHandle = NULL;
94  HINTERNET sessionHandle = NULL;
95  PNETWORK_OUTPUT_CONTEXT context = NULL;
96  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig = { 0 };
97 
98  //4.4.3. IP Addresses and Networks
99  // https://www.arin.net/resources/whoisrws/whois_api.html
100  //TODO: use REF string from /rest/ip/ lookup for querying the IP network: "/rest/net/NET-74-125-0-0-1?showDetails=true"
101  // or use CIDR string from /rest/ip/ lookup for querying the IP network: "/rest/cidr/216.34.181.0/24?showDetails=true
102  //WinHttpAddRequestHeaders(requestHandle, L"application/arin.whoisrws-v1+xml", -1L, 0);
103 
104  __try
105  {
106  // Query thread context.
107  if ((context = (PNETWORK_OUTPUT_CONTEXT)Parameter) == NULL)
108  __leave;
109 
110  // Query PH version.
111  if ((phVersion = PhGetPhVersion()) == NULL)
112  __leave;
113 
114  // Create a user agent string.
115  if ((userAgent = PhConcatStrings2(L"Process Hacker ", phVersion->Buffer)) == NULL)
116  __leave;
117 
118  // Query the current system proxy
119  WinHttpGetIEProxyConfigForCurrentUser(&proxyConfig);
120 
121  // Open the HTTP session with the system proxy configuration if available
122  if (!(sessionHandle = WinHttpOpen(
123  userAgent->Buffer,
124  proxyConfig.lpszProxy != NULL ? WINHTTP_ACCESS_TYPE_NAMED_PROXY : WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
125  proxyConfig.lpszProxy,
126  proxyConfig.lpszProxyBypass,
127  0
128  )))
129  {
130  __leave;
131  }
132 
133  if (!(connectionHandle = WinHttpConnect(
134  sessionHandle,
135  L"whois.arin.net",
136  INTERNET_DEFAULT_HTTP_PORT,
137  0
138  )))
139  {
140  __leave;
141  }
142 
143  if (!(whoisHttpGetString = PhFormatString(L"/rest/ip/%s", context->IpAddressString)))
144  __leave;
145 
146  if (!(requestHandle = WinHttpOpenRequest(
147  connectionHandle,
148  NULL,
149  whoisHttpGetString->Buffer,
150  NULL,
151  WINHTTP_NO_REFERER,
152  WINHTTP_DEFAULT_ACCEPT_TYPES,
153  WINHTTP_FLAG_REFRESH
154  )))
155  {
156  __leave;
157  }
158 
159  if (!WinHttpAddRequestHeaders(requestHandle, L"Accept: text/plain", -1L, 0))
160  __leave;
161 
162  if (!WinHttpSendRequest(
163  requestHandle,
164  WINHTTP_NO_ADDITIONAL_HEADERS, 0,
165  WINHTTP_NO_REQUEST_DATA, 0,
166  WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH, 0
167  ))
168  {
169  __leave;
170  }
171 
172  if (!WinHttpReceiveResponse(requestHandle, NULL))
173  __leave;
174 
175  if (!ReadRequestString(requestHandle, &xmlBuffer, &xmlLength))
176  __leave;
177 
178  PostMessage(context->WindowHandle, NTM_RECEIVEDWHOIS, (WPARAM)xmlLength, (LPARAM)xmlBuffer);
179  PostMessage(context->WindowHandle, NTM_RECEIVEDFINISH, 0, 0);
180 
181  isSuccess = TRUE;
182  }
183  __finally
184  {
185  if (phVersion)
186  PhDereferenceObject(phVersion);
187 
188  if (userAgent)
189  PhDereferenceObject(userAgent);
190 
191  if (whoisHttpGetString)
192  PhDereferenceObject(whoisHttpGetString);
193 
194  if (requestHandle)
195  WinHttpCloseHandle(requestHandle);
196 
197  if (connectionHandle)
198  WinHttpCloseHandle(connectionHandle);
199 
200  if (sessionHandle)
201  WinHttpCloseHandle(sessionHandle);
202  }
203 
204  return STATUS_SUCCESS;
205 }