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.

545 lines
17 KiB

  1. #define INITGUID
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <ole2.h>
  5. #define USE_CAPI2
  6. #if defined(USE_CAPI2)
  7. #include <wincrypt.h>
  8. #endif
  9. #include "admex.h"
  10. //
  11. // HRESULTTOWIN32() maps an HRESULT to a Win32 error. If the facility code
  12. // of the HRESULT is FACILITY_WIN32, then the code portion (i.e. the
  13. // original Win32 error) is returned. Otherwise, the original HRESULT is
  14. // returned unchagned.
  15. //
  16. #define HRESULTTOWIN32(hres) \
  17. ((HRESULT_FACILITY(hres) == FACILITY_WIN32) \
  18. ? HRESULT_CODE(hres) \
  19. : (hres))
  20. #define RETURNCODETOHRESULT(rc) \
  21. (((rc) < 0x10000) \
  22. ? HRESULT_FROM_WIN32(rc) \
  23. : (rc))
  24. #define PAD4(a) (((a)+3)&~3)
  25. VOID
  26. DisplayErrorMessage(
  27. DWORD dwErr,
  28. DWORD dwMsg = 0
  29. );
  30. /////////////////////////////////////////////////////
  31. VOID
  32. DisplayErrorMessage(
  33. DWORD dwErr,
  34. DWORD dwMsg
  35. )
  36. {
  37. LPSTR pErr;
  38. CHAR achMsg[2048];
  39. if ( dwMsg != 0 )
  40. {
  41. if ( LoadString( NULL, dwMsg, achMsg, sizeof(achMsg) ) )
  42. {
  43. printf( achMsg );
  44. }
  45. }
  46. if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  47. NULL,
  48. dwErr,
  49. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  50. (LPSTR)&pErr,
  51. 0,
  52. NULL ) )
  53. {
  54. puts( pErr );
  55. LocalFree( pErr );
  56. }
  57. }
  58. VOID
  59. Dump(
  60. LPSTR pszMsg,
  61. LPBYTE pb,
  62. DWORD dw
  63. )
  64. {
  65. printf( "%s size is %d\n", pszMsg, dw );
  66. for ( UINT x = 0 ; x < dw ; ++x )
  67. {
  68. printf( "%02x ", pb[x] );
  69. }
  70. if ( dw )
  71. {
  72. printf( "\n" );
  73. }
  74. }
  75. int __cdecl main( int argc, char*argv[] )
  76. {
  77. IMSAdminReplication* pIf;
  78. IMSAdminCryptoCapabilities* pIfS;
  79. IClassFactory* pcsfFactory = NULL;
  80. int iA;
  81. HRESULT hRes;
  82. COSERVERINFO csiMachineName;
  83. WCHAR awchComputer[64];
  84. BYTE abBuf[32768];
  85. DWORD dwReqSize;
  86. MULTI_QI rgmq;
  87. LPSTR pszMachineName = NULL;
  88. int arg;
  89. BOOL fDoTest = FALSE;
  90. HKEY hKey;
  91. CHAR achName[128];
  92. DWORD dwNameLen;
  93. DWORD dwValueLen;
  94. DWORD dwType;
  95. int iV, iV2;
  96. LPBYTE pbSerial;
  97. DWORD dwSerialLen, dwSerialLen2;
  98. DWORD dwErr;
  99. for ( arg = 1 ; arg < argc ; ++arg )
  100. {
  101. if ( argv[arg][0] == '-' )
  102. {
  103. switch ( argv[arg][1] )
  104. {
  105. case 'm':
  106. pszMachineName = argv[arg]+2;
  107. break;
  108. case 't':
  109. fDoTest = TRUE;
  110. break;
  111. }
  112. }
  113. }
  114. if ( argc < 1 )
  115. {
  116. CHAR achMsg[2048];
  117. if ( LoadString( NULL, 100, achMsg, sizeof(achMsg) ) )
  118. {
  119. printf( achMsg );
  120. }
  121. return 3;
  122. }
  123. //fill the structure for CoCreateInstanceEx
  124. ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
  125. // csiMachineName.pAuthInfo = NULL;
  126. // csiMachineName.dwFlags = 0;
  127. // csiMachineName.pServerInfoExt = NULL;
  128. if ( pszMachineName )
  129. {
  130. if ( !MultiByteToWideChar( CP_ACP,
  131. MB_PRECOMPOSED,
  132. pszMachineName,
  133. -1,
  134. awchComputer,
  135. sizeof(awchComputer) ) )
  136. {
  137. return FALSE;
  138. }
  139. csiMachineName.pwszName = awchComputer;
  140. }
  141. else
  142. {
  143. csiMachineName.pwszName = NULL;
  144. }
  145. CoInitializeEx( NULL, COINIT_MULTITHREADED );
  146. if ( fDoTest )
  147. {
  148. hRes = CoGetClassObject(CLSID_MSCryptoAdmEx, CLSCTX_SERVER, &csiMachineName,
  149. IID_IClassFactory, (void**) &pcsfFactory);
  150. if ( SUCCEEDED( hRes ) )
  151. {
  152. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminReplication, (void **) &rgmq.pItf);
  153. if ( SUCCEEDED( hRes ) )
  154. {
  155. rgmq.pItf->Release();
  156. }
  157. else
  158. {
  159. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  160. }
  161. pcsfFactory->Release();
  162. }
  163. else
  164. {
  165. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  166. }
  167. //
  168. // call replication I/F
  169. //
  170. rgmq.pIID = &IID_IMSAdminReplication;
  171. rgmq.pItf = NULL;
  172. rgmq.hr = 0;
  173. if ( SUCCEEDED( hRes = CoCreateInstanceEx( CLSID_MSCryptoAdmEx,
  174. NULL,
  175. CLSCTX_SERVER,
  176. &csiMachineName,
  177. 1,
  178. &rgmq ) ) &&
  179. SUCCEEDED( hRes = rgmq.hr ) )
  180. {
  181. pIf = (IMSAdminReplication*)rgmq.pItf;
  182. hRes = pIf->GetSignature( sizeof(abBuf), abBuf, &dwReqSize );
  183. if ( SUCCEEDED( hRes ) )
  184. {
  185. Dump( "GetSignature:", abBuf, dwReqSize );
  186. hRes = pIf->Serialize( sizeof(abBuf), abBuf, &dwReqSize );
  187. }
  188. if ( SUCCEEDED( hRes ) )
  189. {
  190. Dump( "Serialize:", abBuf, dwReqSize );
  191. hRes = pIf->DeSerialize( dwReqSize, abBuf );
  192. }
  193. pIf->Release();
  194. if ( FAILED( hRes ) )
  195. {
  196. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  197. }
  198. }
  199. else
  200. {
  201. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  202. }
  203. //
  204. // call crypto capabilities I/F
  205. //
  206. rgmq.pIID = &IID_IMSAdminCryptoCapabilities;
  207. rgmq.pItf = NULL;
  208. rgmq.hr = 0;
  209. if ( SUCCEEDED( hRes = CoCreateInstanceEx( CLSID_MSCryptoAdmEx,
  210. NULL,
  211. CLSCTX_SERVER,
  212. &csiMachineName,
  213. 1,
  214. &rgmq ) ) &&
  215. SUCCEEDED( hRes = rgmq.hr ) )
  216. {
  217. pIfS = (IMSAdminCryptoCapabilities*)rgmq.pItf;
  218. hRes = pIfS->GetProtocols( sizeof(abBuf), abBuf, &dwReqSize );
  219. if ( SUCCEEDED(hRes) )
  220. {
  221. Dump( "Protocols:", abBuf, dwReqSize );
  222. hRes = pIfS->GetSupportedAlgs( sizeof(abBuf), (LPDWORD)abBuf, &dwReqSize );
  223. }
  224. if ( SUCCEEDED(hRes) )
  225. {
  226. Dump( "Algs:", abBuf, dwReqSize );
  227. hRes = pIfS->GetRootCertificates( sizeof(abBuf), abBuf, &dwReqSize );
  228. }
  229. if ( SUCCEEDED(hRes) )
  230. {
  231. Dump( "CAs:", abBuf, dwReqSize );
  232. hRes = pIfS->GetMaximumCipherStrength( &dwReqSize );
  233. }
  234. if ( SUCCEEDED(hRes) )
  235. {
  236. Dump( "Cipher strength:", (LPBYTE)&dwReqSize, sizeof(DWORD) );
  237. }
  238. pIfS->Release();
  239. if ( FAILED( hRes ) )
  240. {
  241. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  242. }
  243. }
  244. else
  245. {
  246. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  247. }
  248. }
  249. else
  250. {
  251. //
  252. // Check full access to registry ( granted only to administrators )
  253. //
  254. if ( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  255. "SYSTEM\\CurrentControlSet\\Services\\InetInfo\\Parameters",
  256. 0,
  257. KEY_ALL_ACCESS,
  258. &hKey )) == ERROR_SUCCESS )
  259. {
  260. RegCloseKey( hKey );
  261. }
  262. else
  263. {
  264. hRes = RETURNCODETOHRESULT( dwErr );
  265. }
  266. if ( SUCCEEDED( hRes ) )
  267. {
  268. hRes = CoGetClassObject(CLSID_MSCryptoAdmEx, CLSCTX_SERVER, &csiMachineName,
  269. IID_IClassFactory, (void**) &pcsfFactory);
  270. }
  271. if ( SUCCEEDED( hRes ) )
  272. {
  273. hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminCryptoCapabilities, (void **) &pIfS);
  274. if ( FAILED( hRes ) )
  275. {
  276. DisplayErrorMessage( HRESULTTOWIN32( hRes ) );
  277. }
  278. else
  279. {
  280. //
  281. // get CA list
  282. //
  283. #if defined(USE_CAPI2)
  284. HCERTSTORE hStore = NULL;
  285. BOOL fReturn = FALSE;
  286. PCCERT_CONTEXT pCtx;
  287. hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A,
  288. 0,
  289. NULL,
  290. CERT_SYSTEM_STORE_CURRENT_USER,
  291. "ROOT" );
  292. if ( hStore )
  293. {
  294. for ( pCtx = NULL, dwSerialLen = 0 ;
  295. pCtx = CertEnumCertificatesInStore( hStore, pCtx ) ; )
  296. {
  297. // CertDeleteCertificateFromStore, CertAddSerializedElementToStore
  298. dwValueLen = sizeof(abBuf);
  299. if ( CertSerializeCertificateStoreElement( pCtx, 0, NULL, &dwValueLen ) )
  300. {
  301. dwSerialLen += sizeof(DWORD) + PAD4(dwValueLen);
  302. }
  303. else
  304. {
  305. hRes = RETURNCODETOHRESULT( GetLastError() );
  306. break;
  307. }
  308. }
  309. }
  310. else
  311. {
  312. hRes = RETURNCODETOHRESULT( GetLastError() );
  313. }
  314. if ( SUCCEEDED( hRes ) )
  315. {
  316. if ( pbSerial = (LPBYTE)LocalAlloc( LMEM_FIXED, dwSerialLen ) )
  317. {
  318. for ( pCtx = NULL, dwSerialLen2 = 0 ;
  319. pCtx = CertEnumCertificatesInStore( hStore, pCtx ) ; )
  320. {
  321. dwValueLen = dwSerialLen - dwSerialLen2 - sizeof(DWORD);
  322. if ( CertSerializeCertificateStoreElement( pCtx, 0, pbSerial + dwSerialLen2 + sizeof(DWORD), &dwValueLen ) )
  323. {
  324. *(LPDWORD)(pbSerial+dwSerialLen2) = dwValueLen;
  325. dwSerialLen2 += sizeof(DWORD) + PAD4(dwValueLen);
  326. }
  327. else
  328. {
  329. hRes = RETURNCODETOHRESULT( GetLastError() );
  330. break;
  331. }
  332. }
  333. if ( SUCCEEDED( hRes ) )
  334. {
  335. //
  336. // call deserialize. This will be invoked in IIS SYSTEM context
  337. //
  338. hRes = pIfS->SetCAList( dwSerialLen2, pbSerial );
  339. }
  340. LocalFree( pbSerial );
  341. }
  342. else
  343. {
  344. hRes = E_OUTOFMEMORY;
  345. }
  346. }
  347. if ( hStore )
  348. {
  349. CertCloseStore( hStore, CERT_CLOSE_STORE_FORCE_FLAG );
  350. }
  351. #else
  352. if ( (dwErr = RegOpenKeyEx( HKEY_CURRENT_USER,
  353. "Software\\Microsoft\\SystemCertificates\\ROOT\\Certificates",
  354. 0,
  355. KEY_READ,
  356. &hKey )) == ERROR_SUCCESS )
  357. {
  358. //
  359. // compute length of serialized CA list
  360. //
  361. for ( iV = 0, dwSerialLen = 0 ; ; ++iV )
  362. {
  363. dwNameLen = sizeof( achName );
  364. dwValueLen = sizeof(abBuf);
  365. if ( RegEnumValue( hKey,
  366. iV,
  367. achName,
  368. &dwNameLen,
  369. NULL,
  370. &dwType,
  371. abBuf,
  372. &dwValueLen ) != ERROR_SUCCESS )
  373. {
  374. break;
  375. }
  376. ++dwNameLen;
  377. dwSerialLen += sizeof(DWORD) + PAD4(dwNameLen) + sizeof(DWORD) + PAD4(dwValueLen);
  378. }
  379. if ( pbSerial = (LPBYTE)LocalAlloc( LMEM_FIXED, dwSerialLen ) )
  380. {
  381. //
  382. // build serialized list
  383. //
  384. for ( iV2 = 0, dwSerialLen2 = 0 ;; ++iV2 )
  385. {
  386. dwNameLen = sizeof( achName );
  387. dwValueLen = sizeof(abBuf);
  388. if ( RegEnumValue( hKey,
  389. iV2,
  390. achName,
  391. &dwNameLen,
  392. NULL,
  393. &dwType,
  394. abBuf,
  395. &dwValueLen ) != ERROR_SUCCESS )
  396. {
  397. break;
  398. }
  399. ++dwNameLen;
  400. if ( iV2 == iV ||
  401. dwSerialLen2 + sizeof(DWORD) + PAD4(dwNameLen) + sizeof(DWORD) + PAD4(dwValueLen) > dwSerialLen )
  402. {
  403. hRes = E_OUTOFMEMORY;
  404. break;
  405. }
  406. // each element ( name or content ) is stored prefixed by
  407. // a DWORD length. element actual storage is padded
  408. // so that length is multiple of 4, to make sure following
  409. // DWORDs are DWORD aligned.
  410. // store value name ( includes zero byte delimiter )
  411. *(LPDWORD)(pbSerial+dwSerialLen2) = dwNameLen;
  412. dwSerialLen2 += sizeof(DWORD);
  413. memcpy( pbSerial+dwSerialLen2, achName, dwNameLen );
  414. dwSerialLen2 += PAD4(dwNameLen);
  415. // store value content
  416. *(LPDWORD)(pbSerial+dwSerialLen2) = dwValueLen;
  417. dwSerialLen2 += sizeof(DWORD);
  418. memcpy( pbSerial+dwSerialLen2, abBuf, dwValueLen );
  419. dwSerialLen2 += PAD4(dwValueLen);
  420. }
  421. if ( SUCCEEDED( hRes ) )
  422. {
  423. //
  424. // call deserialize. This will be invoked in IIS SYSTEM context
  425. //
  426. hRes = pIfS->SetCAList( dwSerialLen2, pbSerial );
  427. }
  428. LocalFree( pbSerial );
  429. }
  430. else
  431. {
  432. hRes = E_OUTOFMEMORY;
  433. }
  434. RegCloseKey( hKey );
  435. }
  436. else
  437. {
  438. hRes = RETURNCODETOHRESULT( dwErr );
  439. }
  440. #endif
  441. if ( FAILED(hRes) )
  442. {
  443. DisplayErrorMessage( HRESULTTOWIN32( hRes ), 102 );
  444. }
  445. else
  446. {
  447. CHAR achMsg[2048];
  448. if ( LoadString( NULL, 101, achMsg, sizeof(achMsg) ) )
  449. {
  450. printf( achMsg );
  451. }
  452. }
  453. pIfS->Release();
  454. }
  455. pcsfFactory->Release();
  456. }
  457. else
  458. {
  459. DisplayErrorMessage( HRESULTTOWIN32( hRes ), 102 );
  460. }
  461. }
  462. CoUninitialize();
  463. return SUCCEEDED(hRes) ? 0 : 1;
  464. }