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.

791 lines
28 KiB

  1. //-----------------------------------------------------------------------------
  2. // America Online for Windows
  3. //-----------------------------------------------------------------------------
  4. // Copyright (c) 1987-2001 America Online, Inc. All rights reserved. This
  5. // software contains valuable confidential and proprietary information of
  6. // America Online and is subject to applicable licensing agreements.
  7. // Unauthorized reproduction, transmission, or distribution of this file and
  8. // its contents is a violation of applicable laws.
  9. //-----------------------------------------------------------------------------
  10. // $Workfile: AOLInstall.cpp $ $Author: RobrtLarson $
  11. // $Date: 05/02/01 $
  12. //-----------------------------------------------------------------------------
  13. #include "precomp.h"
  14. #include <Softpub.h>
  15. #include <WinCrypt.h>
  16. #include <WinTrust.h>
  17. #include <ImageHlp.h>
  18. #include "LegalStr.h"
  19. #include "AOLFindBundledInstaller_AOLCode.h"
  20. #ifdef _DEBUG
  21. #define new DEBUG_NEW
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. #define SWAPWORDS(x) (((x) << 16) | ((x) >> 16))
  26. // define encoding method
  27. #define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
  28. #define INSTALLER 0x0001
  29. #define CLIENT 0x0002
  30. #define COUNTRY_PICKER 0x0004
  31. #define SERVICE_AOL 0x0010
  32. #define SERVICE_CS 0x0020
  33. // Local function prototypes
  34. BOOL GetExeType(LPSTR lpszExePath, WORD &wExeType);
  35. BOOL ExtractCertificateInfo(LPSTR lpszFileName, HCERTSTORE *hCertStore);
  36. PCCERT_CONTEXT WINAPI CryptGetSignerCertificateCallback(void *pvGetArg,
  37. DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hCertStore);
  38. BOOL CheckCertificateName(HCERTSTORE hCertStore);
  39. LPSTR GetCommonName(CERT_NAME_BLOB pCertNameBlob);
  40. BOOL VerifyFileInfo(WORD &ExeType, LPSTR lpszInstaller, PBOOL pbOldClient);
  41. BOOL VerifyCertificate(LPSTR lpszInstaller);
  42. _pfn_CertCloseStore g_pfn_CertCloseStore = NULL;
  43. _pfn_CryptVerifyMessageSignature g_pfn_CryptVerifyMessageSignature = NULL;
  44. _pfn_ImageGetCertificateData g_pfn_ImageGetCertificateData = NULL;
  45. _pfn_ImageGetCertificateHeader g_pfn_ImageGetCertificateHeader = NULL;
  46. _pfn_CertGetSubjectCertificateFromStore g_pfn_CertGetSubjectCertificateFromStore = NULL;
  47. _pfn_CertDuplicateStore g_pfn_CertDuplicateStore = NULL;
  48. _pfn_CertEnumCertificatesInStore g_pfn_CertEnumCertificatesInStore = NULL;
  49. _pfn_CertRDNValueToStrA g_pfn_CertRDNValueToStrA = NULL;
  50. _pfn_CertFindRDNAttr g_pfn_CertFindRDNAttr = NULL;
  51. _pfn_CryptDecodeObject g_pfn_CryptDecodeObject = NULL;
  52. _pfn_VerQueryValueA g_pfn_VerQueryValueA = NULL;
  53. _pfn_GetFileVersionInfoA g_pfn_GetFileVersionInfoA = NULL;
  54. _pfn_GetFileVersionInfoSizeA g_pfn_GetFileVersionInfoSizeA = NULL;
  55. _pfn_WinVerifyTrust g_pfn_WinVerifyTrust = NULL;
  56. HMODULE g_hCRYPT32 = NULL;
  57. HMODULE g_hWINTRUST = NULL;
  58. HMODULE g_hVERSION = NULL;
  59. HMODULE g_hIMAGEHLP = NULL;
  60. void UnloadDependencies()
  61. {
  62. g_pfn_CertCloseStore = NULL;
  63. g_pfn_CryptVerifyMessageSignature = NULL;
  64. g_pfn_ImageGetCertificateData = NULL;
  65. g_pfn_ImageGetCertificateHeader = NULL;
  66. g_pfn_CertGetSubjectCertificateFromStore = NULL;
  67. g_pfn_CertDuplicateStore = NULL;
  68. g_pfn_CertEnumCertificatesInStore = NULL;
  69. g_pfn_CertRDNValueToStrA = NULL;
  70. g_pfn_CertFindRDNAttr = NULL;
  71. g_pfn_CryptDecodeObject = NULL;
  72. g_pfn_VerQueryValueA = NULL;
  73. g_pfn_GetFileVersionInfoA = NULL;
  74. g_pfn_GetFileVersionInfoSizeA = NULL;
  75. g_pfn_WinVerifyTrust = NULL;
  76. if (g_hCRYPT32) {
  77. FreeLibrary(g_hCRYPT32);
  78. g_hCRYPT32 = NULL;
  79. }
  80. if (g_hWINTRUST) {
  81. FreeLibrary(g_hWINTRUST);
  82. g_hWINTRUST = NULL;
  83. }
  84. if (g_hVERSION) {
  85. FreeLibrary(g_hVERSION);
  86. g_hVERSION = NULL;
  87. }
  88. if (g_hIMAGEHLP) {
  89. FreeLibrary(g_hIMAGEHLP);
  90. g_hIMAGEHLP = NULL;
  91. }
  92. }
  93. BOOL LoadDependencies()
  94. {
  95. BOOL bSuccess = FALSE;
  96. if (!(g_hCRYPT32 = LoadLibraryA("CRYPT32.DLL"))) {
  97. goto eh;
  98. }
  99. if (!(g_hWINTRUST = LoadLibraryA("WINTRUST.DLL"))) {
  100. goto eh;
  101. }
  102. if (!(g_hVERSION = LoadLibraryA("VERSION.DLL"))) {
  103. goto eh;
  104. }
  105. if (!(g_hIMAGEHLP = LoadLibraryA("IMAGEHLP.DLL"))) {
  106. goto eh;
  107. }
  108. if (!(g_pfn_CertCloseStore = (_pfn_CertCloseStore) GetProcAddress(g_hCRYPT32, "CertCloseStore"))) { goto eh; }
  109. if (!(g_pfn_CryptVerifyMessageSignature = (_pfn_CryptVerifyMessageSignature) GetProcAddress(g_hCRYPT32, "CryptVerifyMessageSignature"))) { goto eh; }
  110. if (!(g_pfn_ImageGetCertificateData = (_pfn_ImageGetCertificateData) GetProcAddress(g_hIMAGEHLP, "ImageGetCertificateData"))) { goto eh; }
  111. if (!(g_pfn_ImageGetCertificateHeader = (_pfn_ImageGetCertificateHeader) GetProcAddress(g_hIMAGEHLP, "ImageGetCertificateHeader"))) { goto eh; }
  112. if (!(g_pfn_CertGetSubjectCertificateFromStore = (_pfn_CertGetSubjectCertificateFromStore) GetProcAddress(g_hCRYPT32, "CertGetSubjectCertificateFromStore"))) { goto eh; }
  113. if (!(g_pfn_CertDuplicateStore = (_pfn_CertDuplicateStore) GetProcAddress(g_hCRYPT32, "CertDuplicateStore"))) { goto eh; }
  114. if (!(g_pfn_CertEnumCertificatesInStore = (_pfn_CertEnumCertificatesInStore) GetProcAddress(g_hCRYPT32, "CertEnumCertificatesInStore"))) { goto eh; }
  115. if (!(g_pfn_CertRDNValueToStrA = (_pfn_CertRDNValueToStrA) GetProcAddress(g_hCRYPT32, "CertRDNValueToStrA"))) { goto eh; }
  116. if (!(g_pfn_CertFindRDNAttr = (_pfn_CertFindRDNAttr) GetProcAddress(g_hCRYPT32, "CertFindRDNAttr"))) { goto eh; }
  117. if (!(g_pfn_CryptDecodeObject = (_pfn_CryptDecodeObject) GetProcAddress(g_hCRYPT32, "CryptDecodeObject"))) { goto eh; }
  118. if (!(g_pfn_VerQueryValueA = (_pfn_VerQueryValueA) GetProcAddress(g_hVERSION, "VerQueryValueA"))) { goto eh; }
  119. if (!(g_pfn_GetFileVersionInfoA = (_pfn_GetFileVersionInfoA) GetProcAddress(g_hVERSION, "GetFileVersionInfoA"))) { goto eh; }
  120. if (!(g_pfn_GetFileVersionInfoSizeA = (_pfn_GetFileVersionInfoSizeA) GetProcAddress(g_hVERSION, "GetFileVersionInfoSizeA"))) { goto eh; }
  121. if (!(g_pfn_WinVerifyTrust = (_pfn_WinVerifyTrust) GetProcAddress(g_hWINTRUST, "WinVerifyTrust"))) { goto eh; }
  122. bSuccess = TRUE;
  123. eh:
  124. if (!bSuccess) {
  125. UnloadDependencies();
  126. }
  127. return bSuccess;
  128. }
  129. //-----------------------------------------------------------------------------
  130. // LocateInstaller
  131. // This functions searches for a valid AOL or CompuServe install program
  132. // based on the default value found in a registry key. This install program
  133. // is then validated by checking the Certificates and verifying that the
  134. // program file has not been modified since being signed by America Online.
  135. //
  136. // AOL Registry Key:
  137. // HKLM\Software\America Online\Installers
  138. //
  139. // CompuServe Registry Key:
  140. // HKLM\Software\CompuServe\Installers
  141. //-----------------------------------------------------------------------------
  142. // Function parameters:
  143. // LPSTR lpszInstaller Returned installer command line,
  144. // NULL if no valid installer located
  145. // Note: allowance should be made in the
  146. // length of this string for an optional
  147. // parameter on the command line of MAX_PATH
  148. // length.
  149. // UINT uiPathSize Length of lpszInstaller parameter
  150. // BOOL *pbMessage TRUE - display App Compat message
  151. // FALSE - do not display App Compat message
  152. //-----------------------------------------------------------------------------
  153. BOOL LocateInstaller_Internal(LPSTR lpszInstaller, UINT uiPathSize, BOOL *pbMessage)
  154. {
  155. BOOL bResult = FALSE,
  156. bCheckCert = TRUE,
  157. bOldClient = FALSE;
  158. HKEY hKey;
  159. LONG lRet;
  160. CHAR szModuleName[MAX_PATH];
  161. WORD wExeType = 0;
  162. // Default to no App Compat message
  163. *pbMessage = FALSE;
  164. // Get the name of the file that is executing
  165. DWORD dwLen = GetModuleFileNameA(NULL, szModuleName, sizeof(szModuleName));
  166. if (0 == dwLen)
  167. { return FALSE; }
  168. // Determine the type of exe this is
  169. bResult = GetExeType(szModuleName, wExeType);
  170. if (bResult)
  171. {
  172. // Check if this is the uninstaller calling the client
  173. if ((CLIENT & wExeType) && (NULL != strstr(_strlwr(GetCommandLineA()), "regall")))
  174. { return FALSE; }
  175. // If the program we are running is valid, then let it run
  176. if (VerifyFileInfo(wExeType, szModuleName, &bOldClient))
  177. { return FALSE; }
  178. // If this is an client <= 4.0 then display message if not bundled installer found
  179. if (bOldClient)
  180. { *pbMessage = TRUE; }
  181. // Open registry key
  182. if (SERVICE_AOL & wExeType)
  183. {
  184. lRet = RegOpenKeyA(HKEY_LOCAL_MACHINE,
  185. "Software\\America Online\\Installers", &hKey);
  186. }
  187. else if (SERVICE_CS & wExeType)
  188. {
  189. lRet = RegOpenKeyA(HKEY_LOCAL_MACHINE,
  190. "Software\\CompuServe\\Installers", &hKey);
  191. }
  192. else
  193. { return FALSE; } // Don't know what this is
  194. if (ERROR_SUCCESS != lRet)
  195. { return FALSE; } // No bundled version of AOL/CS located in registry
  196. // Get size of registry key data
  197. ULONG cbSize;
  198. DWORD dwType;
  199. lRet = RegQueryValueExA(hKey, NULL, NULL, &dwType, NULL, &cbSize);
  200. if ((ERROR_SUCCESS != lRet) ||
  201. (cbSize > uiPathSize) ||
  202. (REG_SZ != dwType))
  203. { return FALSE; }
  204. // See if we need to check the certificate for the installer
  205. lRet = RegQueryValueExA(hKey, "CC", NULL, &dwType, NULL, &cbSize);
  206. if ((ERROR_SUCCESS == lRet) && (cbSize > 0))
  207. { bCheckCert = FALSE; }
  208. lpszInstaller[0] = '\"';
  209. // Get registry key data
  210. cbSize = uiPathSize - 1;
  211. lRet = RegQueryValueExA(hKey, NULL, NULL, NULL, (UCHAR *)&lpszInstaller[1], &cbSize);
  212. RegCloseKey(hKey);
  213. if (ERROR_SUCCESS == lRet)
  214. {
  215. // Check for correct installer version
  216. bResult = VerifyFileInfo(wExeType, &lpszInstaller[1], NULL);
  217. if (bResult && bCheckCert)
  218. {
  219. // Get certificate store
  220. HCERTSTORE hCertStore = NULL;
  221. bResult = ExtractCertificateInfo(&lpszInstaller[1], &hCertStore);
  222. if (bResult)
  223. {
  224. // Check certificates for AOL/CS signature
  225. bResult = CheckCertificateName(hCertStore);
  226. if (bResult)
  227. {
  228. // Check that file has not been modified
  229. bResult = VerifyCertificate(&lpszInstaller[1]);
  230. }
  231. }
  232. // Close the certificate store
  233. if (NULL != hCertStore)
  234. { (*g_pfn_CertCloseStore)(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG); }
  235. }
  236. }
  237. }
  238. if (bResult)
  239. {
  240. strcat(lpszInstaller, "\"") ;
  241. // Check if Message should be displayed to user
  242. if (CLIENT & wExeType)
  243. { *pbMessage = TRUE; }
  244. else
  245. {
  246. // Add command line parameter
  247. if (COUNTRY_PICKER & wExeType)
  248. {
  249. if ((strlen(lpszInstaller) + strlen(szModuleName) + 6) <= uiPathSize)
  250. { sprintf(lpszInstaller, "%s -p \"%s\"", lpszInstaller, szModuleName); }
  251. }
  252. }
  253. }
  254. else
  255. { lpszInstaller[0] = '\0'; }
  256. return bResult;
  257. }
  258. BOOL LocateInstaller(LPSTR lpszInstaller, UINT uiPathSize, BOOL *pbMessage)
  259. {
  260. BOOL bSuccess = FALSE;
  261. if (!LoadDependencies()) {
  262. goto eh;
  263. }
  264. if (!LocateInstaller_Internal(lpszInstaller, uiPathSize, pbMessage)) {
  265. goto eh;
  266. }
  267. bSuccess = TRUE;
  268. eh:
  269. UnloadDependencies();
  270. return bSuccess;
  271. }
  272. //-----------------------------------------------------------------------------
  273. // GetExeType
  274. // This functions determines whether the executible is an AOL/CS client or
  275. // and AOL/CS installer.
  276. //-----------------------------------------------------------------------------
  277. // Function parameters:
  278. // LPSTR lpszExePath Fully qualified path to executible
  279. // WORD &wExeType Returned executible type
  280. // AOL or CS
  281. // Client or Installer
  282. //-----------------------------------------------------------------------------
  283. BOOL GetExeType(LPSTR lpszExePath, WORD &wExeType)
  284. {
  285. // Set string to lower case for comparisons
  286. _strlwr(lpszExePath);
  287. LPSTR pszTemp = strrchr(lpszExePath, '\\');
  288. if (NULL == pszTemp)
  289. { return FALSE; }
  290. pszTemp++; // Get to beginning of exe name
  291. // Determine if this is an AOL/CS client
  292. if (0 == _stricmp(pszTemp, "waol.exe"))
  293. {
  294. wExeType = SERVICE_AOL | CLIENT;
  295. return TRUE;
  296. }
  297. else if ((0 == _stricmp(pszTemp, "wcs2000.exe")) ||
  298. (0 == _stricmp(pszTemp, "cs3.exe")))
  299. {
  300. wExeType = SERVICE_CS | CLIENT;
  301. return TRUE;
  302. }
  303. else if ((NULL != strstr(pszTemp, "cs2000")) ||
  304. (NULL != strstr(pszTemp, "setupcs2k")) ||
  305. (NULL != strstr(pszTemp, "setupcs2000")) ||
  306. (0 == _stricmp(pszTemp, "d41000b.exe")) ||
  307. (0 == _stricmp(pszTemp, "d41510b.exe")) ||
  308. (0 == _stricmp(pszTemp, "d41540b.exe")))
  309. {
  310. // These are CS installers w/ "America Online, Inc." in version info.
  311. wExeType = SERVICE_CS | INSTALLER;
  312. return TRUE;
  313. }
  314. else if (0 == _stricmp(pszTemp, "wgw.exe"))
  315. { return FALSE; } // There is no bundled installer for Gateway
  316. else if (0 == _stricmp(pszTemp, "wwm.exe"))
  317. { return FALSE; } // There is no bundled installer for Wal-Mart
  318. // Determine AOL/CS installer
  319. // Get size of version info in file
  320. DWORD dwHandle = 0;
  321. DWORD dwVerInfoSize = (*g_pfn_GetFileVersionInfoSizeA)(lpszExePath, &dwHandle);
  322. // Allocate memory for version info
  323. BYTE *lpVerInfo = NULL;
  324. __try
  325. {
  326. lpVerInfo = (BYTE *)HeapAlloc(GetProcessHeap(), 0, dwVerInfoSize);
  327. if (NULL == lpVerInfo)
  328. { __leave; }
  329. // Get version info from file
  330. BOOL bResult = (*g_pfn_GetFileVersionInfoA)(lpszExePath, NULL, dwVerInfoSize, lpVerInfo);
  331. if (!bResult)
  332. { __leave; }
  333. // Get Language code page
  334. DWORD *pdwTrans;
  335. UINT uiBytes;
  336. DWORD dwLangCodepage = 0;
  337. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, "\\VarFileInfo\\Translation", (VOID **)&pdwTrans, &uiBytes);
  338. if (bResult)
  339. { dwLangCodepage = SWAPWORDS(*pdwTrans); } // Translate language code page to something we can use
  340. else
  341. { dwLangCodepage = 0x040904e4; } // Try English multilanguage code page
  342. // Obtain the "CompanyName" from the version info
  343. CHAR szQuery[MAX_PATH];
  344. PCHAR pszVerInfo;
  345. sprintf(szQuery, "\\StringFileInfo\\%08X\\CompanyName", dwLangCodepage);
  346. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, szQuery, (VOID **)&pszVerInfo, &uiBytes);
  347. if (!bResult)
  348. { __leave; }
  349. // Check "CompanyName"
  350. if ((NULL != strstr(pszVerInfo, "America Online")) ||
  351. (NULL != strstr(pszVerInfo, "AOL")))
  352. {
  353. wExeType = SERVICE_AOL | INSTALLER;
  354. return TRUE;
  355. }
  356. if (0 == strcmp("CompuServe Interactive Services, Inc.", pszVerInfo))
  357. {
  358. wExeType = SERVICE_CS | INSTALLER;
  359. return TRUE;
  360. }
  361. }
  362. __finally
  363. {
  364. if (NULL != lpVerInfo)
  365. { HeapFree(GetProcessHeap(), 0, lpVerInfo); }
  366. }
  367. return FALSE;
  368. }
  369. //-----------------------------------------------------------------------------
  370. // ExtractCertificateInfo
  371. // This functions obtains and verifies the certificate store for the
  372. // installer.
  373. //-----------------------------------------------------------------------------
  374. // Function parameters:
  375. // LPSTR lpszFileName Fully qualified path to installer
  376. // HCERTSTORE *hCertStore Handle to the certificate store
  377. //-----------------------------------------------------------------------------
  378. BOOL ExtractCertificateInfo(LPSTR lpszFileName, HCERTSTORE *hCertStore)
  379. {
  380. WIN_CERTIFICATE CertificateHeader;
  381. LPWIN_CERTIFICATE pbCertificate = NULL;
  382. BOOL bResult = FALSE;
  383. HANDLE hFile = NULL;
  384. DWORD dwSize;
  385. CRYPT_VERIFY_MESSAGE_PARA CryptVerifyMessagePara;
  386. __try
  387. {
  388. // Open file
  389. hFile = CreateFileA(lpszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
  390. FILE_ATTRIBUTE_NORMAL, NULL);
  391. if (hFile == INVALID_HANDLE_VALUE)
  392. { return FALSE; }
  393. // Get Certificate Header
  394. bResult = (*g_pfn_ImageGetCertificateHeader)(hFile, 0, &CertificateHeader);
  395. if (!bResult)
  396. { __leave; }
  397. // Allocate Memory for Certificate Blob
  398. pbCertificate = (LPWIN_CERTIFICATE)HeapAlloc(GetProcessHeap(), 0,
  399. CertificateHeader.dwLength);
  400. if (NULL == pbCertificate)
  401. {
  402. bResult = FALSE;
  403. __leave;
  404. }
  405. // Get Certificate Blob
  406. dwSize = CertificateHeader.dwLength;
  407. bResult = (*g_pfn_ImageGetCertificateData)(hFile, 0, pbCertificate, &dwSize);
  408. if (!bResult)
  409. { __leave; }
  410. // Zero out CRYPT_VERIFY_MESSAGE_PARA structure
  411. ZeroMemory(&CryptVerifyMessagePara, sizeof(CryptVerifyMessagePara));
  412. CryptVerifyMessagePara.cbSize = sizeof(CryptVerifyMessagePara);
  413. CryptVerifyMessagePara.dwMsgAndCertEncodingType = ENCODING;
  414. CryptVerifyMessagePara.pfnGetSignerCertificate = CryptGetSignerCertificateCallback;
  415. // Pass Address of certificate store to callback
  416. CryptVerifyMessagePara.pvGetArg = (LPVOID)hCertStore;
  417. // Verify the message and call callback
  418. bResult = (*g_pfn_CryptVerifyMessageSignature)(&CryptVerifyMessagePara, 0,
  419. pbCertificate->bCertificate, dwSize, NULL, NULL, NULL);
  420. }
  421. __finally
  422. {
  423. if (NULL != pbCertificate)
  424. { HeapFree(GetProcessHeap(), 0, pbCertificate); }
  425. if (NULL != hFile)
  426. { CloseHandle(hFile); }
  427. }
  428. return bResult;
  429. }
  430. //-----------------------------------------------------------------------------
  431. // CryptGetSignerCertificateCallback
  432. // This functions is the callback function for CryptVerifyMessageSignature.
  433. //-----------------------------------------------------------------------------
  434. // Function parameters:
  435. // See MicroSoft documentation for details.
  436. //-----------------------------------------------------------------------------
  437. PCCERT_CONTEXT WINAPI CryptGetSignerCertificateCallback(void *pvGetArg,
  438. DWORD dwCertEncodingType, PCERT_INFO pSignerId, HCERTSTORE hCertStore)
  439. {
  440. if (NULL == hCertStore)
  441. { return FALSE; }
  442. *((HCERTSTORE *)pvGetArg) = (*g_pfn_CertDuplicateStore)(hCertStore);
  443. return (*g_pfn_CertGetSubjectCertificateFromStore)(hCertStore, dwCertEncodingType,
  444. pSignerId);
  445. }
  446. //-----------------------------------------------------------------------------
  447. // CheckCertificateName
  448. // This functions checks the certificate name to verify that it is signed by
  449. // America Online.
  450. //-----------------------------------------------------------------------------
  451. // Function parameters:
  452. // HCERTSTORE hCertStore Handle to the certificate store
  453. //-----------------------------------------------------------------------------
  454. BOOL CheckCertificateName(HCERTSTORE hCertStore)
  455. {
  456. BOOL bReturn = FALSE;
  457. PCCERT_CONTEXT pCertContext = NULL;
  458. PCCERT_CONTEXT pPrevContext = NULL;
  459. LPSTR szSubject = NULL;
  460. if (NULL != hCertStore)
  461. {
  462. do
  463. {
  464. pCertContext = (*g_pfn_CertEnumCertificatesInStore)(hCertStore, pPrevContext);
  465. if (NULL != pCertContext)
  466. {
  467. // Get Subject common name, if not then get organization name
  468. szSubject = GetCommonName(pCertContext->pCertInfo->Subject);
  469. if (NULL != szSubject)
  470. {
  471. // Check name of certificate signer
  472. if (0 == strcmp(szSubject, "America Online, Inc."))
  473. { bReturn = TRUE; }
  474. HeapFree(GetProcessHeap(), 0, szSubject);
  475. }
  476. pPrevContext = pCertContext;
  477. }
  478. } while (pCertContext);
  479. }
  480. return bReturn;
  481. }
  482. //-----------------------------------------------------------------------------
  483. // GetCommonName
  484. // This functions obtains the common name from the certificate store
  485. //-----------------------------------------------------------------------------
  486. // Function parameters:
  487. // CERT_NAME_BLOB pCertNameBlob Pointer to the blob that contains the name
  488. //-----------------------------------------------------------------------------
  489. LPSTR GetCommonName(CERT_NAME_BLOB pCertNameBlob)
  490. {
  491. BOOL bReturn = FALSE;
  492. BOOL bResult;
  493. PCERT_NAME_INFO pCertName = NULL;
  494. PCERT_RDN_ATTR pCertAttr;
  495. LPSTR szName = NULL;
  496. DWORD dwSize;
  497. __try
  498. {
  499. // Find out size of decrypted blob
  500. (*g_pfn_CryptDecodeObject)(ENCODING, X509_NAME, pCertNameBlob.pbData,
  501. pCertNameBlob.cbData, 0, NULL, &dwSize);
  502. // Allocate memory for decrypted blob
  503. pCertName = (PCERT_NAME_INFO)HeapAlloc(GetProcessHeap(), 0, dwSize);
  504. if (NULL == pCertName)
  505. { __leave; }
  506. // Decode the certificate blob
  507. bResult = (*g_pfn_CryptDecodeObject)(ENCODING, X509_NAME, pCertNameBlob.pbData,
  508. pCertNameBlob.cbData, 0, pCertName, &dwSize);
  509. if (!bResult)
  510. { __leave; }
  511. // Get common name
  512. pCertAttr = (*g_pfn_CertFindRDNAttr)(szOID_COMMON_NAME, pCertName);
  513. if (NULL == pCertAttr)
  514. {
  515. // Get organization name if no common name found
  516. pCertAttr = (*g_pfn_CertFindRDNAttr)(szOID_ORGANIZATION_NAME, pCertName);
  517. if (NULL == pCertAttr)
  518. { __leave; }
  519. }
  520. // Find out size of name
  521. dwSize = (*g_pfn_CertRDNValueToStrA)(pCertAttr->dwValueType, &pCertAttr->Value, NULL, 0);
  522. // Allocate memory for name
  523. szName = (LPSTR)HeapAlloc(GetProcessHeap(), 0, dwSize);
  524. if (NULL == szName)
  525. { __leave; }
  526. // Obtain name from decrypted blob
  527. (*g_pfn_CertRDNValueToStrA)(pCertAttr->dwValueType, &pCertAttr->Value, szName, dwSize);
  528. bReturn = TRUE;
  529. }
  530. __finally
  531. {
  532. if (NULL != pCertName)
  533. { HeapFree(GetProcessHeap(), 0, pCertName); }
  534. if (!bReturn)
  535. {
  536. if (NULL != szName)
  537. { HeapFree(GetProcessHeap(), 0, szName); }
  538. }
  539. }
  540. if (bReturn)
  541. { return szName; }
  542. else
  543. { return NULL; }
  544. }
  545. //-----------------------------------------------------------------------------
  546. // VerifyFileInfo
  547. // This functions verifies that the installer is valid based on the version
  548. // information stored in the file.
  549. //-----------------------------------------------------------------------------
  550. // Function parameters:
  551. // INSTALLER_TYPE InstallerType Specifies whether to look for AOL or CS
  552. // LPSTR lpszInstaller Fully qualified path to installer
  553. // PBOOL pbOldClient Is is a client older then 5.0
  554. //-----------------------------------------------------------------------------
  555. BOOL VerifyFileInfo(WORD &wExeType, LPSTR lpszInstaller, PBOOL pbOldClient)
  556. {
  557. BOOL bReturn = FALSE;
  558. BOOL bResult;
  559. BYTE *lpVerInfo = NULL;
  560. __try
  561. {
  562. // Get size of version info in file
  563. DWORD dwHandle = 0;
  564. DWORD dwVerInfoSize = (*g_pfn_GetFileVersionInfoSizeA)(lpszInstaller, &dwHandle);
  565. // Allocate memory for version info
  566. lpVerInfo = (BYTE *)HeapAlloc(GetProcessHeap(), 0, dwVerInfoSize);
  567. if (NULL == lpVerInfo)
  568. { __leave; }
  569. // Get version info from file
  570. bResult = (*g_pfn_GetFileVersionInfoA)(lpszInstaller, NULL, dwVerInfoSize, lpVerInfo);
  571. if (!bResult)
  572. { __leave; }
  573. // Get Language code page
  574. DWORD *pdwTrans;
  575. UINT uiBytes;
  576. DWORD dwLangCodepage = 0;
  577. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, "\\VarFileInfo\\Translation", (VOID **)&pdwTrans, &uiBytes);
  578. if (bResult)
  579. { dwLangCodepage = SWAPWORDS(*pdwTrans); } // Translate language code page to something we can use
  580. else
  581. { dwLangCodepage = 0x040904e4; } // Try English multilanguage code page
  582. // Obtain the "CompanyName" from the version info
  583. CHAR szQuery[MAX_PATH];
  584. PCHAR pszVerInfo;
  585. sprintf(szQuery, "\\StringFileInfo\\%08X\\CompanyName", dwLangCodepage);
  586. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, szQuery, (VOID **)&pszVerInfo, &uiBytes);
  587. if (!bResult)
  588. { __leave; }
  589. // Check "CompanyName"
  590. if (SERVICE_AOL & wExeType)
  591. {
  592. if ((NULL == strstr(pszVerInfo, "America Online")) &&
  593. (NULL == strstr(pszVerInfo, "AOL")))
  594. { __leave; }
  595. }
  596. else if (SERVICE_CS & wExeType)
  597. {
  598. if (0 != strcmp("CompuServe Interactive Services, Inc.", pszVerInfo))
  599. { __leave; }
  600. }
  601. else
  602. { __leave; }
  603. // Get fixed file info
  604. VS_FIXEDFILEINFO* pVS_FFI;
  605. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, "\\", (VOID **)&pVS_FFI, &uiBytes);
  606. if (!bResult)
  607. { __leave; }
  608. // Check if this is the Country Picker
  609. sprintf(szQuery, "\\StringFileInfo\\%08X\\ProductName", dwLangCodepage);
  610. bResult = (*g_pfn_VerQueryValueA)(lpVerInfo, szQuery, (VOID **)&pszVerInfo, &uiBytes);
  611. if ((bResult) && (NULL != strstr(pszVerInfo, "Country Picker")))
  612. {
  613. wExeType |= COUNTRY_PICKER;
  614. if (0x00010005 > pVS_FFI->dwProductVersionMS)
  615. { __leave; }
  616. }
  617. else
  618. {
  619. if ((0x00060000 > pVS_FFI->dwProductVersionMS) ||
  620. ((0x00060000 >= pVS_FFI->dwProductVersionMS) &&
  621. (0x00020000 > pVS_FFI->dwProductVersionLS)))
  622. {
  623. if ((NULL != pbOldClient) &&
  624. (CLIENT & wExeType) &&
  625. (0x00050000 > pVS_FFI->dwProductVersionMS))
  626. { *pbOldClient = TRUE; }
  627. __leave;
  628. }
  629. }
  630. bReturn = TRUE;
  631. }
  632. __finally
  633. {
  634. if (NULL != lpVerInfo)
  635. { HeapFree(GetProcessHeap(), 0, lpVerInfo); }
  636. }
  637. return bReturn;
  638. }
  639. //-----------------------------------------------------------------------------
  640. // VerifyCertificate
  641. // This functions verifies that the install has not been modified since
  642. // being signed by America Online.
  643. //-----------------------------------------------------------------------------
  644. // Function parameters:
  645. // LPSTR lpszInstaller Fully qualified path to installer
  646. //-----------------------------------------------------------------------------
  647. BOOL VerifyCertificate(LPSTR lpszInstaller)
  648. {
  649. GUID ActionGUID = WIN_SPUB_ACTION_PUBLISHED_SOFTWARE;
  650. GUID SubjectPeImage = WIN_TRUST_SUBJTYPE_PE_IMAGE;
  651. WIN_TRUST_SUBJECT_FILE Subject;
  652. // Subject.lpPath is a WCHAR string, must convert
  653. LPWSTR lpwszInstaller = NULL;
  654. int cchUnicodeSize = 0;
  655. cchUnicodeSize = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
  656. lpszInstaller, -1, NULL, 0);
  657. lpwszInstaller = (LPWSTR)malloc(cchUnicodeSize * sizeof(WCHAR));
  658. if (0 == MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, lpszInstaller,
  659. -1, lpwszInstaller, cchUnicodeSize))
  660. {
  661. if (lpwszInstaller)
  662. { free(lpwszInstaller); }
  663. return FALSE;
  664. }
  665. Subject.lpPath = lpwszInstaller;
  666. Subject.hFile = INVALID_HANDLE_VALUE; // Open the using the lpPath field
  667. WIN_TRUST_ACTDATA_CONTEXT_WITH_SUBJECT ActionData;
  668. ActionData.Subject = &Subject;
  669. ActionData.hClientToken = NULL;
  670. ActionData.SubjectType = &SubjectPeImage;
  671. // Verify the file has not be changed since being signed
  672. HRESULT hr = (*g_pfn_WinVerifyTrust)((HWND)INVALID_HANDLE_VALUE, &ActionGUID, (WINTRUST_DATA *) &ActionData);
  673. if (lpwszInstaller)
  674. { free(lpwszInstaller); }
  675. if (S_OK == hr)
  676. { return TRUE; }
  677. else
  678. { return FALSE; }
  679. }