#define INITGUID #include #include #include #define USE_CAPI2 #if defined(USE_CAPI2) #include #endif #include "admex.h" // // HRESULTTOWIN32() maps an HRESULT to a Win32 error. If the facility code // of the HRESULT is FACILITY_WIN32, then the code portion (i.e. the // original Win32 error) is returned. Otherwise, the original HRESULT is // returned unchagned. // #define HRESULTTOWIN32(hres) \ ((HRESULT_FACILITY(hres) == FACILITY_WIN32) \ ? HRESULT_CODE(hres) \ : (hres)) #define RETURNCODETOHRESULT(rc) \ (((rc) < 0x10000) \ ? HRESULT_FROM_WIN32(rc) \ : (rc)) #define PAD4(a) (((a)+3)&~3) VOID DisplayErrorMessage( DWORD dwErr, DWORD dwMsg = 0 ); ///////////////////////////////////////////////////// VOID DisplayErrorMessage( DWORD dwErr, DWORD dwMsg ) { LPSTR pErr; CHAR achMsg[2048]; if ( dwMsg != 0 ) { if ( LoadString( NULL, dwMsg, achMsg, sizeof(achMsg) ) ) { printf( achMsg ); } } if ( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&pErr, 0, NULL ) ) { puts( pErr ); LocalFree( pErr ); } } VOID Dump( LPSTR pszMsg, LPBYTE pb, DWORD dw ) { printf( "%s size is %d\n", pszMsg, dw ); for ( UINT x = 0 ; x < dw ; ++x ) { printf( "%02x ", pb[x] ); } if ( dw ) { printf( "\n" ); } } int __cdecl main( int argc, char*argv[] ) { IMSAdminReplication* pIf; IMSAdminCryptoCapabilities* pIfS; IClassFactory* pcsfFactory = NULL; int iA; HRESULT hRes; COSERVERINFO csiMachineName; WCHAR awchComputer[64]; BYTE abBuf[32768]; DWORD dwReqSize; MULTI_QI rgmq; LPSTR pszMachineName = NULL; int arg; BOOL fDoTest = FALSE; HKEY hKey; CHAR achName[128]; DWORD dwNameLen; DWORD dwValueLen; DWORD dwType; int iV, iV2; LPBYTE pbSerial; DWORD dwSerialLen, dwSerialLen2; DWORD dwErr; for ( arg = 1 ; arg < argc ; ++arg ) { if ( argv[arg][0] == '-' ) { switch ( argv[arg][1] ) { case 'm': pszMachineName = argv[arg]+2; break; case 't': fDoTest = TRUE; break; } } } if ( argc < 1 ) { CHAR achMsg[2048]; if ( LoadString( NULL, 100, achMsg, sizeof(achMsg) ) ) { printf( achMsg ); } return 3; } //fill the structure for CoCreateInstanceEx ZeroMemory( &csiMachineName, sizeof(csiMachineName) ); // csiMachineName.pAuthInfo = NULL; // csiMachineName.dwFlags = 0; // csiMachineName.pServerInfoExt = NULL; if ( pszMachineName ) { if ( !MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszMachineName, -1, awchComputer, sizeof(awchComputer) ) ) { return FALSE; } csiMachineName.pwszName = awchComputer; } else { csiMachineName.pwszName = NULL; } CoInitializeEx( NULL, COINIT_MULTITHREADED ); if ( fDoTest ) { hRes = CoGetClassObject(CLSID_MSCryptoAdmEx, CLSCTX_SERVER, &csiMachineName, IID_IClassFactory, (void**) &pcsfFactory); if ( SUCCEEDED( hRes ) ) { hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminReplication, (void **) &rgmq.pItf); if ( SUCCEEDED( hRes ) ) { rgmq.pItf->Release(); } else { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } pcsfFactory->Release(); } else { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } // // call replication I/F // rgmq.pIID = &IID_IMSAdminReplication; rgmq.pItf = NULL; rgmq.hr = 0; if ( SUCCEEDED( hRes = CoCreateInstanceEx( CLSID_MSCryptoAdmEx, NULL, CLSCTX_SERVER, &csiMachineName, 1, &rgmq ) ) && SUCCEEDED( hRes = rgmq.hr ) ) { pIf = (IMSAdminReplication*)rgmq.pItf; hRes = pIf->GetSignature( sizeof(abBuf), abBuf, &dwReqSize ); if ( SUCCEEDED( hRes ) ) { Dump( "GetSignature:", abBuf, dwReqSize ); hRes = pIf->Serialize( sizeof(abBuf), abBuf, &dwReqSize ); } if ( SUCCEEDED( hRes ) ) { Dump( "Serialize:", abBuf, dwReqSize ); hRes = pIf->DeSerialize( dwReqSize, abBuf ); } pIf->Release(); if ( FAILED( hRes ) ) { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } } else { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } // // call crypto capabilities I/F // rgmq.pIID = &IID_IMSAdminCryptoCapabilities; rgmq.pItf = NULL; rgmq.hr = 0; if ( SUCCEEDED( hRes = CoCreateInstanceEx( CLSID_MSCryptoAdmEx, NULL, CLSCTX_SERVER, &csiMachineName, 1, &rgmq ) ) && SUCCEEDED( hRes = rgmq.hr ) ) { pIfS = (IMSAdminCryptoCapabilities*)rgmq.pItf; hRes = pIfS->GetProtocols( sizeof(abBuf), abBuf, &dwReqSize ); if ( SUCCEEDED(hRes) ) { Dump( "Protocols:", abBuf, dwReqSize ); hRes = pIfS->GetSupportedAlgs( sizeof(abBuf), (LPDWORD)abBuf, &dwReqSize ); } if ( SUCCEEDED(hRes) ) { Dump( "Algs:", abBuf, dwReqSize ); hRes = pIfS->GetRootCertificates( sizeof(abBuf), abBuf, &dwReqSize ); } if ( SUCCEEDED(hRes) ) { Dump( "CAs:", abBuf, dwReqSize ); hRes = pIfS->GetMaximumCipherStrength( &dwReqSize ); } if ( SUCCEEDED(hRes) ) { Dump( "Cipher strength:", (LPBYTE)&dwReqSize, sizeof(DWORD) ); } pIfS->Release(); if ( FAILED( hRes ) ) { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } } else { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } } else { // // Check full access to registry ( granted only to administrators ) // if ( (dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\InetInfo\\Parameters", 0, KEY_ALL_ACCESS, &hKey )) == ERROR_SUCCESS ) { RegCloseKey( hKey ); } else { hRes = RETURNCODETOHRESULT( dwErr ); } if ( SUCCEEDED( hRes ) ) { hRes = CoGetClassObject(CLSID_MSCryptoAdmEx, CLSCTX_SERVER, &csiMachineName, IID_IClassFactory, (void**) &pcsfFactory); } if ( SUCCEEDED( hRes ) ) { hRes = pcsfFactory->CreateInstance(NULL, IID_IMSAdminCryptoCapabilities, (void **) &pIfS); if ( FAILED( hRes ) ) { DisplayErrorMessage( HRESULTTOWIN32( hRes ) ); } else { // // get CA list // #if defined(USE_CAPI2) HCERTSTORE hStore = NULL; BOOL fReturn = FALSE; PCCERT_CONTEXT pCtx; hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, "ROOT" ); if ( hStore ) { for ( pCtx = NULL, dwSerialLen = 0 ; pCtx = CertEnumCertificatesInStore( hStore, pCtx ) ; ) { // CertDeleteCertificateFromStore, CertAddSerializedElementToStore dwValueLen = sizeof(abBuf); if ( CertSerializeCertificateStoreElement( pCtx, 0, NULL, &dwValueLen ) ) { dwSerialLen += sizeof(DWORD) + PAD4(dwValueLen); } else { hRes = RETURNCODETOHRESULT( GetLastError() ); break; } } } else { hRes = RETURNCODETOHRESULT( GetLastError() ); } if ( SUCCEEDED( hRes ) ) { if ( pbSerial = (LPBYTE)LocalAlloc( LMEM_FIXED, dwSerialLen ) ) { for ( pCtx = NULL, dwSerialLen2 = 0 ; pCtx = CertEnumCertificatesInStore( hStore, pCtx ) ; ) { dwValueLen = dwSerialLen - dwSerialLen2 - sizeof(DWORD); if ( CertSerializeCertificateStoreElement( pCtx, 0, pbSerial + dwSerialLen2 + sizeof(DWORD), &dwValueLen ) ) { *(LPDWORD)(pbSerial+dwSerialLen2) = dwValueLen; dwSerialLen2 += sizeof(DWORD) + PAD4(dwValueLen); } else { hRes = RETURNCODETOHRESULT( GetLastError() ); break; } } if ( SUCCEEDED( hRes ) ) { // // call deserialize. This will be invoked in IIS SYSTEM context // hRes = pIfS->SetCAList( dwSerialLen2, pbSerial ); } LocalFree( pbSerial ); } else { hRes = E_OUTOFMEMORY; } } if ( hStore ) { CertCloseStore( hStore, CERT_CLOSE_STORE_FORCE_FLAG ); } #else if ( (dwErr = RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft\\SystemCertificates\\ROOT\\Certificates", 0, KEY_READ, &hKey )) == ERROR_SUCCESS ) { // // compute length of serialized CA list // for ( iV = 0, dwSerialLen = 0 ; ; ++iV ) { dwNameLen = sizeof( achName ); dwValueLen = sizeof(abBuf); if ( RegEnumValue( hKey, iV, achName, &dwNameLen, NULL, &dwType, abBuf, &dwValueLen ) != ERROR_SUCCESS ) { break; } ++dwNameLen; dwSerialLen += sizeof(DWORD) + PAD4(dwNameLen) + sizeof(DWORD) + PAD4(dwValueLen); } if ( pbSerial = (LPBYTE)LocalAlloc( LMEM_FIXED, dwSerialLen ) ) { // // build serialized list // for ( iV2 = 0, dwSerialLen2 = 0 ;; ++iV2 ) { dwNameLen = sizeof( achName ); dwValueLen = sizeof(abBuf); if ( RegEnumValue( hKey, iV2, achName, &dwNameLen, NULL, &dwType, abBuf, &dwValueLen ) != ERROR_SUCCESS ) { break; } ++dwNameLen; if ( iV2 == iV || dwSerialLen2 + sizeof(DWORD) + PAD4(dwNameLen) + sizeof(DWORD) + PAD4(dwValueLen) > dwSerialLen ) { hRes = E_OUTOFMEMORY; break; } // each element ( name or content ) is stored prefixed by // a DWORD length. element actual storage is padded // so that length is multiple of 4, to make sure following // DWORDs are DWORD aligned. // store value name ( includes zero byte delimiter ) *(LPDWORD)(pbSerial+dwSerialLen2) = dwNameLen; dwSerialLen2 += sizeof(DWORD); memcpy( pbSerial+dwSerialLen2, achName, dwNameLen ); dwSerialLen2 += PAD4(dwNameLen); // store value content *(LPDWORD)(pbSerial+dwSerialLen2) = dwValueLen; dwSerialLen2 += sizeof(DWORD); memcpy( pbSerial+dwSerialLen2, abBuf, dwValueLen ); dwSerialLen2 += PAD4(dwValueLen); } if ( SUCCEEDED( hRes ) ) { // // call deserialize. This will be invoked in IIS SYSTEM context // hRes = pIfS->SetCAList( dwSerialLen2, pbSerial ); } LocalFree( pbSerial ); } else { hRes = E_OUTOFMEMORY; } RegCloseKey( hKey ); } else { hRes = RETURNCODETOHRESULT( dwErr ); } #endif if ( FAILED(hRes) ) { DisplayErrorMessage( HRESULTTOWIN32( hRes ), 102 ); } else { CHAR achMsg[2048]; if ( LoadString( NULL, 101, achMsg, sizeof(achMsg) ) ) { printf( achMsg ); } } pIfS->Release(); } pcsfFactory->Release(); } else { DisplayErrorMessage( HRESULTTOWIN32( hRes ), 102 ); } } CoUninitialize(); return SUCCEEDED(hRes) ? 0 : 1; }