Source code of Windows XP (NT5)
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.

614 lines
16 KiB

  1. //---------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 1997 - 1999
  3. //
  4. // httpreg.c
  5. //
  6. // HTTP/RPC protocol specific functions.
  7. //
  8. // Author:
  9. // 06-02-97 Edward Reus Initial version.
  10. //
  11. //---------------------------------------------------------------------------
  12. #define FD_SETSIZE 1
  13. #include <precomp.hxx>
  14. //-------------------------------------------------------------------------
  15. // HttpParseServerPort()
  16. //
  17. // Parse strings of the form: <svr>[:<port>]
  18. //-------------------------------------------------------------------------
  19. static BOOL HttpParseServerPort( IN char *pszServerPort,
  20. IN char *pszDefaultPort,
  21. OUT char *pszServer,
  22. OUT char *pszPort )
  23. {
  24. char ch;
  25. char *psz;
  26. char *pszColon;
  27. if (pszColon=strchr(pszServerPort,':'))
  28. {
  29. *pszColon = 0;
  30. psz = pszColon;
  31. psz++;
  32. strcpy(pszServer,pszServerPort);
  33. *pszColon = ':';
  34. if (*psz)
  35. {
  36. strcpy(pszPort,psz);
  37. }
  38. else
  39. {
  40. strcpy(pszPort,pszDefaultPort);
  41. }
  42. }
  43. else
  44. {
  45. strcpy(pszServer,pszServerPort);
  46. strcpy(pszPort,pszDefaultPort);
  47. }
  48. return TRUE;
  49. }
  50. //-------------------------------------------------------------------------
  51. // HttpParseProxyName()
  52. //
  53. //-------------------------------------------------------------------------
  54. const char *HttpProxyPrefix = "http://";
  55. const int HttpProxyPrefixSize = sizeof("http://") - 1;
  56. BOOL HttpParseProxyName( IN char *pszProxyList,
  57. OUT char *pszHttpProxy,
  58. OUT char *pszHttpProxyPort )
  59. {
  60. BOOL fStatus;
  61. char *psz;
  62. char *pszSemiColon;
  63. int StringLength;
  64. strcpy(pszHttpProxy,"");
  65. strcpy(pszHttpProxyPort,"");
  66. // Check for no configured proxy:
  67. if ((!pszProxyList)||(!*pszProxyList))
  68. {
  69. return TRUE;
  70. }
  71. // if the string is large enough to contain the prefix, check
  72. // whether it has a prefix
  73. StringLength = strlen(pszProxyList);
  74. if (StringLength >= HttpProxyPrefixSize)
  75. {
  76. if (RpcpStringNCompareA(pszProxyList, HttpProxyPrefix, HttpProxyPrefixSize) == 0)
  77. pszProxyList += HttpProxyPrefixSize;
  78. }
  79. if (!strstr(pszProxyList,EQUALS_STR))
  80. {
  81. return HttpParseServerPort(pszProxyList,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
  82. }
  83. if (psz=strstr(pszProxyList,HTTP_EQUALS_STR))
  84. {
  85. psz += strlen(HTTP_EQUALS_STR);
  86. if (pszSemiColon=strstr(psz,SEMICOLON_STR))
  87. {
  88. *pszSemiColon = 0;
  89. fStatus = HttpParseServerPort(psz,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
  90. *pszSemiColon = CHAR_SEMICOLON;
  91. return fStatus;
  92. }
  93. else
  94. {
  95. return HttpParseServerPort(psz,DEF_HTTP_PORT,pszHttpProxy,pszHttpProxyPort);
  96. }
  97. }
  98. else
  99. {
  100. return TRUE;
  101. }
  102. }
  103. //-------------------------------------------------------------------------
  104. // HttpFreeProxyOverrideList()
  105. //
  106. //-------------------------------------------------------------------------
  107. static void HttpFreeProxyOverrideList( IN char **ppszOverrideList )
  108. {
  109. char **ppszTmp = ppszOverrideList;
  110. if (ppszOverrideList)
  111. {
  112. while (*ppszTmp)
  113. {
  114. I_RpcFree(*ppszTmp);
  115. ppszTmp++;
  116. }
  117. I_RpcFree(ppszOverrideList);
  118. }
  119. }
  120. //-------------------------------------------------------------------------
  121. // HttpParseProxyOverrideList()
  122. //
  123. //-------------------------------------------------------------------------
  124. static char **HttpParseProxyOverrideList( IN char *pszProxyOverrideList )
  125. {
  126. int i;
  127. int iLen;
  128. int count = 1;
  129. DWORD dwSize = 1+strlen(pszProxyOverrideList);
  130. char *pszList;
  131. char *psz;
  132. char **ppszPatternList;
  133. if (!dwSize)
  134. {
  135. return NULL;
  136. }
  137. // Make a local copy of the pattern list, to work with:
  138. pszList = (char *) alloca(dwSize);
  139. strcpy(pszList,pszProxyOverrideList);
  140. // See how many separate patterns ther are in the override list:
  141. //
  142. // NOTE: That count may be too high, if either the list contains
  143. // double semicolons or the list ends with a semicolon. If
  144. // either/both of these happen that's Ok.
  145. psz = pszList;
  146. while (psz=strstr(psz,";"))
  147. {
  148. count++;
  149. psz++;
  150. }
  151. ppszPatternList = (char**)RpcpFarAllocate( (1+count)*sizeof(char*) );
  152. if (!ppszPatternList)
  153. {
  154. // Out of memory.
  155. return NULL;
  156. }
  157. memset(ppszPatternList,0,(1+count)*sizeof(char*));
  158. i = 0;
  159. while (i<count)
  160. {
  161. if (!*pszList)
  162. {
  163. // End of list. This happens when the list contained empty
  164. // patterns.
  165. break;
  166. }
  167. psz = strstr(pszList,";");
  168. if (psz)
  169. {
  170. *psz = 0;
  171. if ( (iLen=strlen(pszList)) == 0)
  172. {
  173. // Zero length pattern.
  174. pszList = ++psz;
  175. continue;
  176. }
  177. ppszPatternList[i] = (char*)RpcpFarAllocate(1+iLen);
  178. if (!ppszPatternList[i])
  179. {
  180. HttpFreeProxyOverrideList(ppszPatternList);
  181. return NULL;
  182. }
  183. strcpy(ppszPatternList[i++],pszList);
  184. pszList = ++psz;
  185. }
  186. else
  187. {
  188. ppszPatternList[i] = (char*)RpcpFarAllocate(1+strlen(pszList));
  189. if (!ppszPatternList[i])
  190. {
  191. HttpFreeProxyOverrideList(ppszPatternList);
  192. return NULL;
  193. }
  194. strcpy(ppszPatternList[i++],pszList);
  195. }
  196. }
  197. return ppszPatternList;
  198. }
  199. //-------------------------------------------------------------------------
  200. // HttpCheckRegistry()
  201. //
  202. // With IE and WinInet you can setup a list of proxies to use to go through
  203. // with an HTTP (or other) internet request. We need to support this as
  204. // well. There are three registry entries of interest, which are located
  205. // at:
  206. //
  207. // \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
  208. //
  209. // They are:
  210. //
  211. // ProxyEnable: REG_BINARY
  212. // A flag (TRUE/FALSE) to enable/disable proxies.
  213. //
  214. // ProxyServer: REG_SZ
  215. // On of: an empty string (no proxy specified), a single proxy server
  216. // name (for any format), or a list of proxy servers to use by format.
  217. // The list is of the form:
  218. //
  219. // ftp=<svr:port>,gopher=<svr:port>,http=<svr:port>,...
  220. //
  221. // Note that not all protocols need to be in the list. And the port#
  222. // does not need to be specifed. If not present then default the port#
  223. // to the default for that internet protocol (scheme).
  224. //
  225. // ProxyOverride: REG_SZ
  226. // A semicolon separated list of server names, internet addresses or
  227. // patterns which, if specified are used to denote machines that you
  228. // want to directly access, without using the proxy server. Examples
  229. // would be:
  230. //
  231. // 12.34.56.78;MySvr*;111.222.*;*green*
  232. //
  233. //-------------------------------------------------------------------------
  234. BOOL HttpCheckRegistry( IN char *pszServer,
  235. OUT char **ppszHttpProxy,
  236. OUT char **ppszHttpProxyPort,
  237. OUT RPCProxyAccessType *AccessType
  238. )
  239. {
  240. int i;
  241. long lStatus;
  242. DWORD dwType;
  243. DWORD dwEnabled;
  244. DWORD dwSize;
  245. HKEY hKey;
  246. HKEY hUserKey;
  247. char szProxyList[256];
  248. char szProxyOverrideList[256];
  249. char szHttpProxy[MAX_HTTP_COMPUTERNAME_SIZE];
  250. char szHttpProxyPort[MAX_HTTP_PORTSTRING_SIZE];
  251. char *pszDotServer;
  252. char **ppszOverrideList;
  253. struct hostent UNALIGNED *pHostEnt;
  254. struct in_addr ServerInAddr;
  255. BOOL LocalDirect;
  256. *ppszHttpProxy = NULL;
  257. *ppszHttpProxyPort = NULL;
  258. *AccessType = rpcpatDirect;
  259. #if TRUE
  260. lStatus = RegOpenCurrentUser( KEY_READ, &hUserKey );
  261. if (lStatus != ERROR_SUCCESS)
  262. {
  263. return TRUE;
  264. }
  265. lStatus = RegOpenKeyEx( hUserKey,
  266. REG_PROXY_PATH_STR,
  267. 0,
  268. KEY_READ,
  269. &hKey );
  270. RegCloseKey(hUserKey);
  271. if (lStatus != ERROR_SUCCESS)
  272. {
  273. return TRUE;
  274. }
  275. #else
  276. HANDLE hUserToken;
  277. HANDLE hThread = GetCurrentThread(); // Note: don't need to CloseHandle().
  278. DWORD dwStatus = 0;
  279. DWORD dwSizeNeeded = 0;
  280. TOKEN_USER *pTokenData;
  281. //
  282. // First, try to get the access token from the thread, in case
  283. // we are impersonating.
  284. //
  285. if (!hThread)
  286. {
  287. dwStatus = GetLastError();
  288. return TRUE;
  289. }
  290. BOOL b = OpenThreadToken( hThread,
  291. TOKEN_READ,
  292. FALSE, // Use context of the thread...
  293. &hUserToken );
  294. if (!b)
  295. {
  296. dwStatus = GetLastError();
  297. if (dwStatus == ERROR_NO_TOKEN)
  298. {
  299. // If we get here, then the thread has no access token, so
  300. // try to get the process's access token.
  301. //
  302. HANDLE hProcess = GetCurrentProcess(); // Never fails.
  303. dwStatus = NO_ERROR;
  304. b = OpenProcessToken(hProcess,
  305. TOKEN_READ,
  306. &hUserToken);
  307. if (!b)
  308. {
  309. dwStatus = GetLastError();
  310. }
  311. }
  312. }
  313. if (dwStatus)
  314. {
  315. #ifdef DBG_REGISTRY
  316. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  317. DPFLTR_WARNING_LEVEL,
  318. "HttpCheckRegistry(): OpenThreadToken() Failed: %d\n",
  319. dwStatus));
  320. #endif
  321. return TRUE;
  322. }
  323. GetTokenInformation( hUserToken,
  324. TokenUser,
  325. 0,
  326. 0,
  327. &dwSizeNeeded
  328. );
  329. pTokenData = (TOKEN_USER*)_alloca(dwSizeNeeded);
  330. if (!GetTokenInformation( hUserToken,
  331. TokenUser,
  332. pTokenData,
  333. dwSizeNeeded,
  334. &dwSizeNeeded ))
  335. {
  336. CloseHandle(hUserToken);
  337. return TRUE;
  338. }
  339. CloseHandle(hUserToken);
  340. wchar_t UnicodeBuffer[256]; // Large enough....
  341. UNICODE_STRING UnicodeString;
  342. UnicodeString.Buffer = UnicodeBuffer;
  343. UnicodeString.Length = 0;
  344. UnicodeString.MaximumLength = sizeof(UnicodeBuffer);
  345. NTSTATUS NtStatus;
  346. NtStatus = RtlConvertSidToUnicodeString( &UnicodeString,
  347. pTokenData->User.Sid,
  348. FALSE );
  349. if (!NT_SUCCESS(NtStatus))
  350. {
  351. return TRUE;
  352. }
  353. UnicodeString.Buffer[UnicodeString.Length] = 0;
  354. //
  355. // Open the user key (equivalent to HKCU).
  356. //
  357. lStatus = RegOpenKeyEx( HKEY_USERS,
  358. UnicodeString.Buffer,
  359. 0,
  360. KEY_READ,
  361. &hUserKey );
  362. if (lStatus != ERROR_SUCCESS)
  363. {
  364. return TRUE;
  365. }
  366. lStatus = RegOpenKeyEx( hUserKey,
  367. REG_PROXY_PATH_STR,
  368. 0,
  369. KEY_READ,
  370. &hKey );
  371. if (lStatus != ERROR_SUCCESS)
  372. {
  373. RegCloseKey(hUserKey);
  374. return TRUE;
  375. }
  376. RegCloseKey(hUserKey);
  377. #endif
  378. dwSize = sizeof(dwEnabled);
  379. lStatus = RegQueryValueEx(
  380. hKey,
  381. REG_PROXY_ENABLE_STR,
  382. 0,
  383. &dwType,
  384. (LPBYTE)&dwEnabled,
  385. &dwSize
  386. );
  387. if (lStatus != ERROR_SUCCESS)
  388. {
  389. RegCloseKey(hKey);
  390. return TRUE;
  391. }
  392. #ifdef DBG_REGISTRY
  393. if (dwType == REG_BINARY)
  394. {
  395. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  396. DPFLTR_WARNING_LEVEL,
  397. "HttpCheckRegistry(): Proxy Enabled: %s\n",
  398. (dwEnabled)? "TRUE" : "FALSE"));
  399. }
  400. #endif // DBG_REGISTRY
  401. if (!dwEnabled)
  402. {
  403. // IE proxies are disabled, no need to go on.
  404. RegCloseKey(hKey);
  405. return TRUE;
  406. }
  407. dwSize = sizeof(szProxyList);
  408. lStatus = RegQueryValueExA( // Needs to be ANSI
  409. hKey,
  410. REG_PROXY_SERVER_STR,
  411. 0,
  412. &dwType,
  413. (LPBYTE)szProxyList,
  414. &dwSize
  415. );
  416. if (lStatus != ERROR_SUCCESS)
  417. {
  418. RegCloseKey(hKey);
  419. return TRUE;
  420. }
  421. #ifdef DBG_REGISTRY
  422. if (dwType == REG_SZ)
  423. {
  424. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  425. DPFLTR_WARNING_LEVEL,
  426. "HttpCheckRegistry(): Proxy List: %s\n",
  427. szProxyList));
  428. }
  429. #endif // DBG_REGISTRY
  430. if (!HttpParseProxyName(szProxyList,szHttpProxy,szHttpProxyPort))
  431. {
  432. RegCloseKey(hKey);
  433. return TRUE;
  434. }
  435. dwSize = sizeof(szProxyOverrideList);
  436. lStatus = RegQueryValueExA( // Needs to be ANSI
  437. hKey,
  438. REG_PROXY_OVERRIDE_STR,
  439. 0,
  440. &dwType,
  441. (LPBYTE)szProxyOverrideList,
  442. &dwSize
  443. );
  444. if (lStatus != ERROR_SUCCESS)
  445. {
  446. // Don't quit if the ProxyOverride entry is missing, that's Ok...
  447. szProxyOverrideList[0] = 0;
  448. }
  449. #ifdef DBG_REGISTRY
  450. if (dwType == REG_SZ)
  451. {
  452. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  453. DPFLTR_WARNING_LEVEL,
  454. "HttpCheckRegistry(): Proxy Override List: %s\n",
  455. szProxyOverrideList));
  456. }
  457. #endif // DBG_REGISTRY
  458. RegCloseKey(hKey);
  459. ppszOverrideList = HttpParseProxyOverrideList(szProxyOverrideList);
  460. if (ppszOverrideList)
  461. {
  462. LocalDirect = MatchExactList(
  463. (unsigned char *) LOCAL_ADDRESSES_STR,
  464. (unsigned char **) ppszOverrideList
  465. );
  466. if (!LocalDirect)
  467. *AccessType = rpcpatHTTPProxy;
  468. else
  469. {
  470. // we don't know. <local> is in the list of overrides,
  471. // but we don't know whether the server is local
  472. *AccessType = rpcpatUnknown;
  473. }
  474. // Check the server name to see if it's in the override list:
  475. if (MatchREList(
  476. (unsigned char *) pszServer,
  477. (unsigned char **) ppszOverrideList
  478. ))
  479. {
  480. // The server name is in the override list.
  481. HttpFreeProxyOverrideList(ppszOverrideList);
  482. *AccessType = rpcpatDirect;
  483. return TRUE;
  484. }
  485. // Convert the server name to dot notation and see if its in
  486. // the override list:
  487. pHostEnt = gethostbyname(pszServer);
  488. if (pHostEnt)
  489. {
  490. // Note that the server may actually have several addresses in
  491. // a (NULL terminated) array. Need to check each one...
  492. i = 0;
  493. while (pHostEnt->h_addr_list[i])
  494. {
  495. memcpy(&ServerInAddr,pHostEnt->h_addr_list[i++],pHostEnt->h_length);
  496. pszDotServer = inet_ntoa(ServerInAddr);
  497. #ifdef DBG_REGISTRY
  498. TransDbgPrint((DPFLTR_RPCPROXY_ID,
  499. DPFLTR_WARNING_LEVEL,
  500. "HttpCheckRegistry(): Server: %s Address: %s\n",
  501. pszServer,
  502. pszDotServer));
  503. #endif // DBG_REGISTRY
  504. if ( (pszDotServer)
  505. && MatchREList(
  506. (unsigned char *) pszDotServer,
  507. (unsigned char **) ppszOverrideList
  508. ) )
  509. {
  510. // The server name (in dot notation) is in the override list.
  511. HttpFreeProxyOverrideList(ppszOverrideList);
  512. *AccessType = rpcpatDirect;
  513. return TRUE;
  514. }
  515. }
  516. }
  517. HttpFreeProxyOverrideList(ppszOverrideList);
  518. }
  519. *ppszHttpProxy = (char *)RpcpFarAllocate(1+strlen(szHttpProxy));
  520. if (!*ppszHttpProxy)
  521. {
  522. return FALSE;
  523. }
  524. strcpy(*ppszHttpProxy,szHttpProxy);
  525. *ppszHttpProxyPort = (char*)RpcpFarAllocate(1+strlen(szHttpProxyPort));
  526. if (!*ppszHttpProxyPort)
  527. {
  528. I_RpcFree(*ppszHttpProxy);
  529. *ppszHttpProxy = NULL;
  530. return FALSE;
  531. }
  532. strcpy(*ppszHttpProxyPort,szHttpProxyPort);
  533. return TRUE;
  534. }