Leaked source code of windows server 2003
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.

442 lines
17 KiB

  1. /*-----------------------------------------------------------------------------
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name: cookies.cxx
  4. Abstract:
  5. Cookie upgrade object implementation
  6. Upgrades cookies to new format by parsing existing cookies
  7. files and adding them to the newly created cookie cache index.
  8. Currently upgrades v3.2 to v4.0.
  9. Author:
  10. Adriaan Canter (adriaanc) 01-Nov-1996.
  11. Modification history:
  12. Ahsan Kabir (akabir) 25-Sep-1997 made a few minor alterations.
  13. -------------------------------------------------------------------------------*/
  14. #include <wininetp.h>
  15. #include <cache.hxx>
  16. /*-----------------------------------------------------------------------------
  17. CCookieLoader::GetHKLMCookiesDirectory
  18. ----------------------------------------------------------------------------*/
  19. DWORD CCookieLoader::GetHKLMCookiesDirectory(CHAR *szCookiesDirectory)
  20. {
  21. DWORD dwError;
  22. REGISTRY_OBJ roCookiePath(HKEY_LOCAL_MACHINE, IE3_COOKIES_PATH_KEY);
  23. DWORD cbKeyLen = MAX_PATH;
  24. if ((dwError=roCookiePath.GetStatus())==ERROR_SUCCESS)
  25. {
  26. dwError = roCookiePath.GetValue(CACHE_DIRECTORY_VALUE, (LPBYTE)szCookiesDirectory, &cbKeyLen);
  27. }
  28. return dwError;
  29. }
  30. /*-----------------------------------------------------------------------------
  31. CCookieLoader::ParseNextCookie
  32. Upgrades cookies from Cache Version 3.2 to Cache Version 4.0
  33. ----------------------------------------------------------------------------*/
  34. CHAR* CCookieLoader::ParseNextCookie(CHAR* ptr, CHAR** ppszHash,
  35. FILETIME* pftExpire, FILETIME* pftLast)
  36. {
  37. CHAR *pszName, *pszValue, *pszFlags,
  38. *pszExpireTimeLow, *pszExpireTimeHigh,
  39. *pszLastTimeHigh, *pszLastTimeLow,
  40. *pszDelimiter, *pszNextCookie;
  41. __try
  42. {
  43. // Get the first token (cookie name).
  44. pszName = StrTokExA(&ptr, "\n");
  45. if (!pszName) // Cookie name.
  46. {
  47. // Normal termination of the parse.
  48. pszNextCookie = 0;
  49. goto exit;
  50. }
  51. // Parse the rest of the cookie
  52. pszValue = StrTokExA(&ptr, "\n"); // Cookie value.
  53. *ppszHash = StrTokExA(&ptr, "\n"); // Combo of domain and path.
  54. pszFlags = StrTokExA(&ptr, "\n"); // Cookie flags.
  55. pszExpireTimeLow = StrTokExA(&ptr, "\n"); // Expire time.
  56. pszExpireTimeHigh = StrTokExA(&ptr, "\n");
  57. pszLastTimeLow = StrTokExA(&ptr, "\n"); // Last Modified time.
  58. pszLastTimeHigh = StrTokExA(&ptr, "\n");
  59. pszDelimiter = StrTokExA(&ptr, "\n"); // Delimiter should be "*"
  60. // Abnormal termination of parse.
  61. if (!pszDelimiter || pszDelimiter[0] != '*')
  62. {
  63. TcpsvcsDbgAssert(FALSE);
  64. pszNextCookie = 0;
  65. goto exit;
  66. }
  67. // Set the times.
  68. pftExpire->dwLowDateTime = atoi(pszExpireTimeLow);
  69. pftExpire->dwHighDateTime = atoi(pszExpireTimeHigh);
  70. pftLast->dwLowDateTime = atoi(pszLastTimeLow);
  71. pftLast->dwHighDateTime = atoi(pszLastTimeHigh);
  72. pszNextCookie = pszDelimiter+2;
  73. }
  74. __except(EXCEPTION_EXECUTE_HANDLER)
  75. {
  76. TcpsvcsDbgAssert(FALSE);
  77. pszNextCookie = 0;
  78. goto exit;
  79. }
  80. ENDEXCEPT
  81. exit:
  82. return pszNextCookie;
  83. }
  84. /*-----------------------------------------------------------------------------
  85. CCookieLoader::LoadCookies
  86. ----------------------------------------------------------------------------*/
  87. DWORD CCookieLoader::LoadCookies(URL_CONTAINER *UrlContainer)
  88. {
  89. HANDLE hFind = INVALID_HANDLE_VALUE;
  90. HANDLE hFile = INVALID_HANDLE_VALUE;
  91. FILETIME ftExpire, ftLast;
  92. CHAR szCookieFileName [MAX_PATH],
  93. szCookieFileNamePattern [MAX_PATH],
  94. szOldMemMapFilePath [MAX_PATH],
  95. szHKLMCookiesPath [MAX_PATH],
  96. szCookieName [MAX_PATH],
  97. szHKLMCookieFileName [MAX_PATH],
  98. szHKCUCookieFileName [MAX_PATH];
  99. CHAR *pszHash, *ptr,
  100. *pszCurrentCookie, *szBuffer;
  101. WIN32_FIND_DATA FindData;
  102. BOOL bReturn;
  103. DWORD cbRead = 0, dwError = ERROR_SUCCESS;
  104. // Data for a single cookie should fit in 2 pages.
  105. BYTE bCacheEntryInfoBuffer[2 * PAGE_SIZE];
  106. LPCACHE_ENTRY_INFO pCacheEntryInfo;
  107. DWORD cbCacheEntryInfoBuffer;
  108. DWORD dwDIR_SEP_STRING = strlen(DIR_SEPARATOR_STRING);
  109. DWORD dwLen;
  110. REGISTRY_OBJ roCachePath(HKEY_CURRENT_USER, OLD_CACHE_KEY);
  111. DWORD cbKeyLen = MAX_PATH;
  112. szBuffer = 0;
  113. __try
  114. {
  115. if (!UrlContainer)
  116. {
  117. dwError = ERROR_INVALID_PARAMETER;
  118. goto exit;
  119. }
  120. TCHAR szSigKey[MAX_PATH];
  121. // Check to see if we are upgrading cookies
  122. // from local machine to per user.
  123. // If IE4's signature isn't present, then we'll guess that IE3 might have been.
  124. if (UrlContainer->IsPerUserItem()
  125. &&
  126. ((roCachePath.GetStatus()!=ERROR_SUCCESS)
  127. ||
  128. (roCachePath.GetValue(CACHE_SIGNATURE_VALUE, (LPBYTE) szSigKey, &cbKeyLen)!=ERROR_SUCCESS)))
  129. {
  130. DWORD cb = MAX_PATH;
  131. CHAR szUserName[MAX_PATH];
  132. // We are converting cookies from HKLM to HKCU.
  133. // This is done by enumerating the user's cookies
  134. // files and copying them to the per-user diretory.
  135. // Once this is accomplished, cookie converting will
  136. // proceed normally.
  137. // Get the cookies directory as specified by HKLM.
  138. GetHKLMCookiesDirectory(szHKLMCookiesPath);
  139. // Get the current user name.
  140. GetUserName(szUserName, &cb);
  141. // szCookieFileNamePattern will look like c:\winnt\cookies\joeuser@*.txt
  142. dwLen = strlen(szHKLMCookiesPath) +
  143. strlen(szUserName) +
  144. dwDIR_SEP_STRING +
  145. 7; // strlen("@*.txt" + '\0';
  146. if( dwLen > MAX_PATH )
  147. {
  148. dwError = ERROR_INSUFFICIENT_BUFFER;
  149. goto exit;
  150. }
  151. strcpy(szCookieFileNamePattern, szHKLMCookiesPath);
  152. strcat(szCookieFileNamePattern, DIR_SEPARATOR_STRING);
  153. strcat(szCookieFileNamePattern, szUserName);
  154. strcat(szCookieFileNamePattern, "@*.txt");
  155. // Enumerate the users cache files
  156. hFind = FindFirstFile(szCookieFileNamePattern, &FindData);
  157. if (hFind != INVALID_HANDLE_VALUE)
  158. {
  159. // One or more cookie files exist.
  160. do
  161. {
  162. // Construct absolute path from HKLM to cookies file.
  163. dwLen = strlen(szHKLMCookiesPath) +
  164. strlen(FindData.cFileName) +
  165. dwDIR_SEP_STRING +
  166. 1;
  167. if( dwLen > MAX_PATH )
  168. {
  169. dwError = ERROR_INSUFFICIENT_BUFFER;
  170. goto exit;
  171. }
  172. strcpy(szHKLMCookieFileName, szHKLMCookiesPath);
  173. strcat(szHKLMCookieFileName, DIR_SEPARATOR_STRING);
  174. strcat(szHKLMCookieFileName, FindData.cFileName);
  175. // Construct absolute path from HKCU to cookies file.
  176. dwLen = strlen(UrlContainer->GetCachePath()) +
  177. strlen(FindData.cFileName) +
  178. 1;
  179. // We should rescue as many cookies as we can.
  180. if( dwLen <= MAX_PATH )
  181. {
  182. strcpy(szHKCUCookieFileName, UrlContainer->GetCachePath());
  183. strcat(szHKCUCookieFileName, FindData.cFileName);
  184. // Move the file to the per-user directory.
  185. CopyFile(szHKLMCookieFileName, szHKCUCookieFileName, TRUE);
  186. }
  187. } while (FindNextFile(hFind, &FindData));
  188. // Close the Find handle.
  189. if (hFind != INVALID_HANDLE_VALUE)
  190. {
  191. FindClose(hFind);
  192. hFind = INVALID_HANDLE_VALUE;
  193. }
  194. } // Per-user upgrade.
  195. }
  196. // No per-user upgrade. szCookieFileNamePattern will look like
  197. // c:\winnt\cookies\*@*.txt or c:\winnt\profiles\joeuser\cookies\*@*.txt.
  198. dwLen = strlen(UrlContainer->GetCachePath()) + 8; // strlen("*@*.txt" + '\0';
  199. if( dwLen > MAX_PATH )
  200. {
  201. dwError = ERROR_INSUFFICIENT_BUFFER;
  202. goto exit;
  203. }
  204. strcpy(szCookieFileNamePattern, UrlContainer->GetCachePath());
  205. strcat(szCookieFileNamePattern, "*@*.txt");
  206. // Enumerate the cache files.
  207. hFind = FindFirstFile(szCookieFileNamePattern, &FindData);
  208. if (hFind == INVALID_HANDLE_VALUE)
  209. {
  210. // OK, No cookies files to upgrade.
  211. // BUGBUG - should we verify this?
  212. dwError = ERROR_SUCCESS;
  213. goto exit;
  214. }
  215. // One or more cookie files exist.
  216. do
  217. {
  218. // Construct absolute path to cookie file.
  219. dwLen = strlen(UrlContainer->GetCachePath()) +
  220. strlen(FindData.cFileName) +
  221. 1;
  222. if( dwLen > MAX_PATH )
  223. {
  224. continue;
  225. }
  226. strcpy(szCookieFileName, UrlContainer->GetCachePath());
  227. strcat(szCookieFileName, FindData.cFileName);
  228. // Get the WIN32_FILE_ATTRIBUTE for the call to AddUrl
  229. // This wrapper works for Win95 and WinNT.
  230. // Open the cookie file.
  231. hFile = CreateFile(
  232. szCookieFileName, // Absolute path to cookies file.
  233. GENERIC_READ, // Read only.
  234. FILE_SHARE_READ, // Share.
  235. 0, // Security Attribute (ignored in W95).
  236. OPEN_EXISTING, // Fail if doesn't exist.
  237. FILE_ATTRIBUTE_NORMAL, // No special attributes.
  238. 0 // Attribute template.
  239. );
  240. // File handle must be valid.
  241. TcpsvcsDbgAssert(hFile != INVALID_HANDLE_VALUE);
  242. if (hFile != INVALID_HANDLE_VALUE)
  243. {
  244. // Allocate memory for cookie file contents.
  245. // BUGBUG - put an upper limit on this? ->
  246. // 300 cookies * 4k/cookie = 1200k plus sundry.
  247. szBuffer = new CHAR[FindData.nFileSizeLow + 1];
  248. if (!szBuffer)
  249. {
  250. dwError = ERROR_NOT_ENOUGH_MEMORY;
  251. goto exit;
  252. }
  253. // Read the file into memory.
  254. bReturn = ReadFile(hFile, szBuffer, FindData.nFileSizeLow, &cbRead, NULL);
  255. // ReadFile must be successful.
  256. TcpsvcsDbgAssert(bReturn);
  257. if (bReturn)
  258. {
  259. // Null terminate buffer.
  260. szBuffer[cbRead] = '\0';
  261. // Parse each cookie out of the buffer.
  262. pszCurrentCookie = szBuffer;
  263. while (pszCurrentCookie = ParseNextCookie(pszCurrentCookie,
  264. &pszHash, &ftExpire, &ftLast))
  265. {
  266. // Construct the cookie name from the following strings:
  267. // FindData.cFileName is like "[email protected]"
  268. // pszHash is like "foobar.com/"
  269. // szCookieName should then be "Cookie:[email protected]/"
  270. strcpy(szCookieName, COOKIE_PREFIX);
  271. strcat(szCookieName, FindData.cFileName);
  272. ptr = strstr(szCookieName, "@");
  273. // Downcase the username portion of the file.
  274. CHAR* tptr = ptr;
  275. while (*--tptr != ':')
  276. *tptr = tolower(*tptr);
  277. strcpy(ptr+1, pszHash);
  278. // Check to see if an earlier version of this cookie
  279. // has already been added to the cache index file.
  280. BOOL fAddToCache = TRUE;
  281. pCacheEntryInfo = (LPCACHE_ENTRY_INFO) bCacheEntryInfoBuffer;
  282. cbCacheEntryInfoBuffer = sizeof(bCacheEntryInfoBuffer);
  283. dwError = UrlContainer->GetUrlInfo(szCookieName, &pCacheEntryInfo,
  284. &cbCacheEntryInfoBuffer, 0, 0, 0);
  285. #ifndef UNIX
  286. if (dwError == ERROR_SUCCESS
  287. && CompareFileTime(pCacheEntryInfo->LastModifiedTime, ftLast) > 0)
  288. #else
  289. /* There is a problem with multiple cookies in a single
  290. * cookie file. When adding the second cookie, we will
  291. * try to delete the existing cookie (the first one that
  292. * was added), and thus try to delete the cookie file
  293. * itself. But, deletion of the cookie file will fail on
  294. * Win32 because the file is already open above for
  295. * parsing. On Unix, the deletion will succeed.
  296. * So, the work-around is to not add the second cookie
  297. * which is from the same site. The entry will remain
  298. * in the cookie file anyway.
  299. */
  300. if (dwError == ERROR_SUCCESS)
  301. #endif /* UNIX */
  302. fAddToCache = FALSE;
  303. if (fAddToCache)
  304. {
  305. // Either this cookie was not found in the index file or
  306. // it was found and the last modified time on it is
  307. // less than the currently parsed cookie. Proceed
  308. // to add this cookie to the index file.
  309. // Add it to the cookie container.
  310. // BUGBUG - besides assert, what to do if this fails?
  311. AddUrlArg Args;
  312. memset(&Args, 0, sizeof(Args));
  313. Args.pszUrl = szCookieName; // [email protected]
  314. Args.pszFilePath = szCookieFileName; // c:\winnt\cookies\[email protected]
  315. Args.qwExpires = FT2LL(ftExpire); // Expire time.
  316. Args.qwLastMod = FT2LL(ftLast); // Last modified time.
  317. Args.dwEntryType |= COOKIE_CACHE_ENTRY;
  318. dwError = UrlContainer->AddUrl(&Args);
  319. TcpsvcsDbgAssert(dwError == ERROR_SUCCESS);
  320. }
  321. } // Successful next cookie field.
  322. } // Successful read.
  323. // Done with this cookie file. Delete the buffer.
  324. delete [] szBuffer;
  325. // And close the file
  326. CloseHandle(hFile);
  327. hFile = INVALID_HANDLE_VALUE;
  328. } // File handle is valid.
  329. } while (FindNextFile(hFind, &FindData));
  330. // No more cookie files or an error occured.
  331. if ((dwError = GetLastError()) != ERROR_NO_MORE_FILES)
  332. goto exit;
  333. // Normal termination.
  334. dwError = ERROR_SUCCESS;
  335. exit:
  336. // Close the file handle.
  337. if (hFile != INVALID_HANDLE_VALUE)
  338. CloseHandle(hFile);
  339. // Close the Find handle.
  340. if (hFind != INVALID_HANDLE_VALUE)
  341. FindClose(hFind);
  342. } // try
  343. __except(EXCEPTION_EXECUTE_HANDLER)
  344. {
  345. // Cleanup.
  346. delete [] szBuffer;
  347. if (hFind != INVALID_HANDLE_VALUE)
  348. FindClose(hFind);
  349. if (hFile != INVALID_HANDLE_VALUE)
  350. CloseHandle(hFile);
  351. TcpsvcsDbgAssert(FALSE);
  352. dwError = ERROR_EXCEPTION_IN_SERVICE;
  353. return dwError;
  354. }
  355. ENDEXCEPT
  356. return dwError;
  357. }