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.

134 lines
4.7 KiB

  1. //***********************************************************************************
  2. //
  3. // Copyright (c) 2002 Microsoft Corporation. All Rights Reserved.
  4. //
  5. // File: WUTESTKEYS.CPP
  6. // Module: WUTESTKEYS.LIB
  7. //
  8. //***********************************************************************************
  9. #include <iucommon.h>
  10. #include <fileutil.h>
  11. #include <trust.h>
  12. #include <shlobj.h>
  13. #include <memutil.h>
  14. #include <advpub.h>
  15. #include <WUTestKeys.h>
  16. #define HOUR (60 * 60)
  17. #define DAY (24 * HOUR)
  18. #define TWO_WEEKS (14 * DAY)
  19. const DWORD MAX_FILE_SIZE = 200; //Maximum expected file size in bytes
  20. const TCHAR WU_DIR[] = _T("\\WindowsUpdate\\");
  21. const CHAR WU_SENTINEL_STRING[] = "Windows Update Test Key Authorization File\r\n";
  22. //function to check if the specified file is a valid WU test file
  23. BOOL IsValidWUTestFile(LPCTSTR lpszFilePath);
  24. // This function returns true if the specified file is a valid WU Test Authorization file
  25. BOOL WUAllowTestKeys(LPCTSTR lpszFileName)
  26. {
  27. TCHAR szWUDirPath[MAX_PATH + 1];
  28. TCHAR szFilePath[MAX_PATH + 1];
  29. TCHAR szTxtFilePath[MAX_PATH+1];
  30. TCHAR szTextFile[MAX_PATH+1];
  31. if (S_OK != SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, 0, szWUDirPath) ||
  32. FAILED(StringCchCatEx(szWUDirPath, ARRAYSIZE(szWUDirPath), WU_DIR, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  33. {
  34. return FALSE;
  35. }
  36. if (NULL == lpszFileName ||
  37. FAILED(StringCchCopyEx(szFilePath, ARRAYSIZE(szFilePath), szWUDirPath, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  38. FAILED(StringCchCatEx(szFilePath, ARRAYSIZE(szFilePath), lpszFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  39. !FileExists(szFilePath))
  40. {
  41. return FALSE;
  42. }
  43. //The filename of the compressed text file should be the same as the name of the cab file
  44. _tsplitpath(lpszFileName, NULL, NULL, szTextFile, NULL);
  45. if(FAILED(StringCchCatEx(szTextFile, ARRAYSIZE(szTextFile), _T(".txt"), NULL, NULL, MISTSAFE_STRING_FLAGS)))
  46. {
  47. return FALSE;
  48. }
  49. //Verify the cab is signed with a Microsoft Cert and extract the file
  50. if (FAILED(VerifyFileTrust(szFilePath, NULL, FALSE, TRUE)) ||
  51. !IUExtractFiles(szFilePath, szWUDirPath, szTextFile))
  52. {
  53. return FALSE;
  54. }
  55. //Generate path to the txt file. The filename should be the same as the name of the cab file
  56. if (!ReplaceFileExtension(szFilePath, _T(".txt"), szTxtFilePath, ARRAYSIZE(szTxtFilePath)))
  57. {
  58. return FALSE;
  59. }
  60. //Check if it is a valid WU test file
  61. BOOL fRet = IsValidWUTestFile(szTxtFilePath);
  62. DeleteFile(szTxtFilePath); //Delete the uncabbed file
  63. return fRet;
  64. }
  65. /*****************************************************************************************
  66. //This function will open the specified file and parse it to make sure:
  67. // (1) The file has the WU Test Sentinel string at the top
  68. // (2) The time stamp on the file is not more than 2 weeks old and
  69. // that it is not a future time stamp.
  70. // The format of a valid file should be as follows:
  71. // WINDOWSUPDATE_SENTINEL_STRING
  72. // YYYY.MM.DD HH:MM:SS
  73. *****************************************************************************************/
  74. BOOL IsValidWUTestFile(LPCTSTR lpszFilePath)
  75. {
  76. USES_IU_CONVERSION;
  77. DWORD cbBytesRead = 0;
  78. const DWORD cbSentinel = ARRAYSIZE(WU_SENTINEL_STRING) - 1; //Size of the sentinel string
  79. //Ansi buffer to read file data
  80. CHAR szFileData[MAX_FILE_SIZE+1];
  81. ZeroMemory(szFileData, ARRAYSIZE(szFileData));
  82. BOOL fRet = FALSE;
  83. HANDLE hFile = CreateFile(lpszFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, NULL, NULL);
  84. if (hFile == INVALID_HANDLE_VALUE)
  85. {
  86. goto done;
  87. }
  88. //If the file size is greater than MAX_FILE_SIZE then bail out
  89. DWORD cbFile = GetFileSize(hFile, NULL);
  90. if(cbFile == INVALID_FILE_SIZE || cbFile > MAX_FILE_SIZE)
  91. {
  92. goto done;
  93. }
  94. if(!ReadFile(hFile, &szFileData, cbFile, &cbBytesRead, NULL) ||
  95. cbBytesRead != cbFile)
  96. {
  97. goto done;
  98. }
  99. //Compare with sentinel string
  100. if(0 != memcmp(szFileData, WU_SENTINEL_STRING, cbSentinel))
  101. {
  102. goto done;
  103. }
  104. LPTSTR tszTime = A2T(szFileData + cbSentinel);
  105. if(tszTime == NULL)
  106. {
  107. goto done;
  108. }
  109. SYSTEMTIME tmCur, tmFile;
  110. if(FAILED(String2SystemTime(tszTime, &tmFile)))
  111. {
  112. goto done;
  113. }
  114. GetSystemTime(&tmCur);
  115. int iSecs = TimeDiff(tmFile, tmCur);
  116. //If the time stamp is less than 2 weeks old and not newer than current time than it is valid
  117. fRet = iSecs > 0 && iSecs < TWO_WEEKS;
  118. done:
  119. if(hFile != INVALID_HANDLE_VALUE)
  120. {
  121. CloseHandle(hFile);
  122. }
  123. return fRet;
  124. }