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.

331 lines
9.3 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1996
  6. //
  7. // File: updroots.cpp
  8. //
  9. // Contents: Updates LocalMachine roots. Pre-whistler, HKLM "Root" store.
  10. // Otherwise, HKLM "AuthRoot" store.
  11. //
  12. // See Usage() for list of options.
  13. //
  14. //
  15. // Functions: main
  16. //
  17. // History: 30-Aug-00 philh created
  18. //
  19. //--------------------------------------------------------------------------
  20. #include <windows.h>
  21. #include "wincrypt.h"
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <memory.h>
  26. #include <time.h>
  27. #define SHA1_HASH_LEN 20
  28. //+-------------------------------------------------------------------------
  29. // crypt32.dll Whistler version numbers
  30. //
  31. // Doesn't need to be the official Whistler release #. Any build # after
  32. // the "AuthRoot" store was added.
  33. //--------------------------------------------------------------------------
  34. #define WHISTLER_CRYPT32_DLL_VER_MS (( 5 << 16) | 131 )
  35. #define WHISTLER_CRYPT32_DLL_VER_LS (( 2257 << 16) | 1 )
  36. BOOL fLocalMachine = FALSE;
  37. void PrintLastError(LPCSTR pszMsg)
  38. {
  39. DWORD dwErr = GetLastError();
  40. char buf[512];
  41. sprintf(buf, "%s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
  42. MessageBoxA(
  43. NULL, // hWnd
  44. buf,
  45. "UpdRoots",
  46. MB_OK | MB_ICONERROR | MB_TASKMODAL
  47. );
  48. }
  49. void PrintMsg(LPCSTR pszMsg)
  50. {
  51. MessageBoxA(
  52. NULL, // hWnd
  53. pszMsg,
  54. "UpdRoots",
  55. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
  56. );
  57. }
  58. static void Usage(void)
  59. {
  60. MessageBoxA(
  61. NULL, // hWnd
  62. "Usage: UpdRoots [options] <SrcStoreFilename>\n"
  63. "Options are:\n"
  64. "-h -\tThis message\n"
  65. "-d -\tDelete (default is to add)\n"
  66. "-l -\tLocal Machine (default is Third Party)\n"
  67. "\n",
  68. "UpdRoots",
  69. MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL
  70. );
  71. }
  72. PCCERT_CONTEXT FindCertificateInOtherStore(
  73. IN HCERTSTORE hOtherStore,
  74. IN PCCERT_CONTEXT pCert
  75. )
  76. {
  77. BYTE rgbHash[SHA1_HASH_LEN];
  78. CRYPT_DATA_BLOB HashBlob;
  79. HashBlob.pbData = rgbHash;
  80. HashBlob.cbData = SHA1_HASH_LEN;
  81. if (!CertGetCertificateContextProperty(
  82. pCert,
  83. CERT_SHA1_HASH_PROP_ID,
  84. rgbHash,
  85. &HashBlob.cbData
  86. ) || SHA1_HASH_LEN != HashBlob.cbData)
  87. return NULL;
  88. return CertFindCertificateInStore(
  89. hOtherStore,
  90. 0, // dwCertEncodingType
  91. 0, // dwFindFlags
  92. CERT_FIND_SHA1_HASH,
  93. (const void *) &HashBlob,
  94. NULL //pPrevCertContext
  95. );
  96. }
  97. BOOL DeleteCertificateFromOtherStore(
  98. IN HCERTSTORE hOtherStore,
  99. IN PCCERT_CONTEXT pCert
  100. )
  101. {
  102. BOOL fResult;
  103. PCCERT_CONTEXT pOtherCert;
  104. if (pOtherCert = FindCertificateInOtherStore(hOtherStore, pCert))
  105. fResult = CertDeleteCertificateFromStore(pOtherCert);
  106. else
  107. fResult = TRUE;
  108. return fResult;
  109. }
  110. typedef BOOL (WINAPI *PFN_CRYPT_GET_FILE_VERSION)(
  111. IN LPCWSTR pwszFilename,
  112. OUT DWORD *pdwFileVersionMS, /* e.g. 0x00030075 = "3.75" */
  113. OUT DWORD *pdwFileVersionLS /* e.g. 0x00000031 = "0.31" */
  114. );
  115. #define NO_LOGICAL_STORE_VERSION 0
  116. #define LOGICAL_STORE_VERSION 1
  117. #define AUTH_STORE_VERSION 2
  118. // Note, I_CryptGetFileVersion and logical stores, not supported in all
  119. // versions of crypt32.dll
  120. //
  121. // Returns one of the above defined version constants
  122. DWORD GetCrypt32Version()
  123. {
  124. DWORD dwVersion;
  125. DWORD dwFileVersionMS;
  126. DWORD dwFileVersionLS;
  127. HMODULE hModule;
  128. PFN_CRYPT_GET_FILE_VERSION pfnCryptGetFileVersion;
  129. hModule = GetModuleHandleA("crypt32.dll");
  130. if (NULL == hModule)
  131. return NO_LOGICAL_STORE_VERSION;
  132. if (NULL == GetProcAddress(hModule, "CertEnumPhysicalStore"))
  133. return NO_LOGICAL_STORE_VERSION;
  134. if (fLocalMachine)
  135. return LOGICAL_STORE_VERSION;
  136. pfnCryptGetFileVersion = (PFN_CRYPT_GET_FILE_VERSION) GetProcAddress(
  137. hModule, "I_CryptGetFileVersion");
  138. if (NULL == pfnCryptGetFileVersion)
  139. return LOGICAL_STORE_VERSION;
  140. dwVersion = LOGICAL_STORE_VERSION;
  141. if (pfnCryptGetFileVersion(
  142. L"crypt32.dll",
  143. &dwFileVersionMS,
  144. &dwFileVersionLS)) {
  145. if (WHISTLER_CRYPT32_DLL_VER_MS < dwFileVersionMS)
  146. dwVersion = AUTH_STORE_VERSION;
  147. else if (WHISTLER_CRYPT32_DLL_VER_MS == dwFileVersionMS &&
  148. WHISTLER_CRYPT32_DLL_VER_LS <= dwFileVersionLS)
  149. dwVersion = AUTH_STORE_VERSION;
  150. }
  151. return dwVersion;
  152. }
  153. int _cdecl main(int argc, char * argv[])
  154. {
  155. BOOL fResult;
  156. int ReturnStatus = 0;
  157. LPSTR pszSrcStoreFilename = NULL; // not allocated
  158. HANDLE hSrcStore = NULL;
  159. HANDLE hRootStore = NULL;
  160. BOOL fDelete = FALSE;
  161. DWORD dwVersion;
  162. PCCERT_CONTEXT pSrcCert;
  163. while (--argc>0)
  164. {
  165. if (**++argv == '-')
  166. {
  167. switch(argv[0][1])
  168. {
  169. case 'd':
  170. fDelete = TRUE;
  171. break;
  172. case 'l':
  173. fLocalMachine = TRUE;
  174. break;
  175. case 'h':
  176. default:
  177. goto BadUsage;
  178. }
  179. } else {
  180. if (pszSrcStoreFilename == NULL)
  181. pszSrcStoreFilename = argv[0];
  182. else {
  183. PrintMsg("too many store filenames\n");
  184. goto BadUsage;
  185. }
  186. }
  187. }
  188. if (NULL == pszSrcStoreFilename) {
  189. PrintMsg("missing store filename\n");
  190. goto BadUsage;
  191. }
  192. // Attempt to open the source store
  193. hSrcStore = CertOpenStore(
  194. CERT_STORE_PROV_FILENAME_A,
  195. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  196. 0, // hCryptProv
  197. CERT_STORE_READONLY_FLAG,
  198. (const void *) pszSrcStoreFilename
  199. );
  200. if (NULL == hSrcStore) {
  201. PrintLastError("Open SrcStore");
  202. goto ErrorReturn;
  203. }
  204. // Attempt to open the destination root store. For Whistler and beyond its
  205. // the HKLM "AuthRoot" store. Pre-Whistler its the HKLM "Root" store.
  206. // Also, earlier versions of crypt32 didn't support logical stores.
  207. // For -l option, force it to be the HKLM "Root" store.
  208. dwVersion = GetCrypt32Version();
  209. if (NO_LOGICAL_STORE_VERSION == dwVersion) {
  210. // Need to open the registry to bypass the add root message boxes
  211. HKEY hKey = NULL;
  212. LONG lErr;
  213. if (ERROR_SUCCESS != (lErr = RegOpenKeyExA(
  214. HKEY_CURRENT_USER,
  215. "Software\\Microsoft\\SystemCertificates\\Root",
  216. 0, // dwReserved
  217. KEY_ALL_ACCESS,
  218. &hKey))) {
  219. SetLastError(lErr);
  220. PrintLastError("RegOpenKeyExA(root)\n");
  221. goto ErrorReturn;
  222. }
  223. hRootStore = CertOpenStore(
  224. CERT_STORE_PROV_REG,
  225. 0, // dwEncodingType
  226. 0, // hCryptProv
  227. 0, // dwFlags
  228. (const void *) hKey
  229. );
  230. RegCloseKey(hKey);
  231. } else {
  232. LPCSTR pszRootStoreName;
  233. if (AUTH_STORE_VERSION == dwVersion)
  234. pszRootStoreName = "AuthRoot";
  235. else
  236. pszRootStoreName = "Root";
  237. hRootStore = CertOpenStore(
  238. CERT_STORE_PROV_SYSTEM_REGISTRY_A,
  239. 0, // dwEncodingType
  240. 0, // hCryptProv
  241. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  242. (const void *) pszRootStoreName
  243. );
  244. }
  245. if (NULL == hRootStore) {
  246. PrintLastError("Open RootStore");
  247. goto ErrorReturn;
  248. }
  249. // Iterate through all the certificates in the source store. Add or delete
  250. // from the root store.
  251. fResult = TRUE;
  252. pSrcCert = NULL;
  253. while (pSrcCert = CertEnumCertificatesInStore(hSrcStore, pSrcCert)) {
  254. if (fDelete) {
  255. if (!DeleteCertificateFromOtherStore(hRootStore, pSrcCert)) {
  256. fResult = FALSE;
  257. PrintLastError("DeleteCert");
  258. }
  259. } else {
  260. // Note, earlier versions of crypt32.dll didn't support
  261. // CERT_STORE_ADD_REPLACE_EXISTING_INHERIT_PROPERTIES
  262. if (!CertAddCertificateContextToStore(
  263. hRootStore,
  264. pSrcCert,
  265. CERT_STORE_ADD_REPLACE_EXISTING,
  266. NULL)) {
  267. fResult = FALSE;
  268. PrintLastError("AddCert");
  269. }
  270. }
  271. }
  272. if (!fResult)
  273. goto ErrorReturn;
  274. ReturnStatus = 0;
  275. CommonReturn:
  276. if (hSrcStore)
  277. CertCloseStore(hSrcStore, 0);
  278. if (hRootStore)
  279. CertCloseStore(hRootStore, 0);
  280. return ReturnStatus;
  281. BadUsage:
  282. Usage();
  283. ErrorReturn:
  284. ReturnStatus = -1;
  285. goto CommonReturn;
  286. }