/*++ Copyright (c) 1996, 1997 Microsoft Corporation Module Name: misc.cpp Abstract: Functionality in this module: Globals management Author: Pete Skelly (petesk) 23-Mar-00 --*/ #include #pragma hdrstop // // Registry Setable Globals, and handlign goo // // Must access key via api's static HKEY g_hProtectedStorageKey = NULL; static HANDLE g_hProtectedStorageChangeEvent = NULL; static RTL_CRITICAL_SECTION g_csGlobals; static BOOL g_fcsGlobalsInitialized = FALSE; // key management globals static DWORD g_IterationCount = DEFAULT_MASTERKEY_ITERATION_COUNT; static BOOL g_LegacyMode = FALSE; static BOOL g_LegacyModeNt4Domain = FALSE; static BOOL g_DistributeDomainBackupKey = FALSE; static DWORD g_dwMasterKeyDefaultPolicy = 0; // define softcoded constants we use static DWORD g_dwDefaultCryptProvType = PROV_RSA_FULL; static DWORD g_dwAlgID_Encr_Alg = CALG_3DES; static DWORD g_dwAlgID_Encr_Alg_KeySize = -1; // any size static DWORD g_dwAlgID_MAC_Alg = CALG_SHA1; static DWORD g_dwAlgID_MAC_Alg_KeySize = -1; // any size typedef struct _ALG_TO_STRING { DWORD AlgId; LPCWSTR wszString; } ALG_TO_STRING; ALG_TO_STRING g_AlgToString[] = { { CALG_MD2, L"MD2-%d " }, { CALG_MD4, L"MD4-%d " }, { CALG_MD5, L"MD5-%d " }, { CALG_SHA1, L"SHA1-%d " }, { CALG_DES, L"DES-%d " }, { CALG_3DES_112, L"3DES-%d " }, { CALG_3DES, L"3DES-%d " }, { CALG_DESX, L"DESX-%d " }, { CALG_RC2, L"RC2-%d " }, { CALG_RC4, L"RC4-%d " }, { CALG_SEAL, L"SEAL-%d " }, { CALG_RSA_SIGN, L"RSA Signature-%d " }, { CALG_RSA_KEYX, L"RSA Exchange-%d " }, { CALG_DSS_SIGN, L"DSS-%d " }, { CALG_DH_SF, L"DH-%d " }, { CALG_DH_EPHEM, L"DH Ephemeral-%d " }, { CALG_KEA_KEYX, L"KEA Exchange-%d " }, { CALG_SKIPJACK, L"SKIPJACK-%d " }, { CALG_TEK, L"TEK-%d " }, { CALG_RC5, L"RC5-%d " }, { CALG_HMAC, L"HMAC-%d " } }; DWORD g_cAlgToString = sizeof(g_AlgToString)/sizeof(g_AlgToString[0]); // supply a new, delete operator void * __cdecl operator new(size_t cb) { return SSAlloc( cb ); } void __cdecl operator delete(void * pv) { SSFree( pv ); } DWORD AlgIDToString(LPWSTR wszString, DWORD dwAlgID, DWORD dwStrength) { DWORD i; for(i=0; i < g_cAlgToString; i++) { if(dwAlgID == g_AlgToString[i].AlgId) { return wsprintf(wszString, g_AlgToString[i].wszString, dwStrength); } } return wsprintf(wszString, L"Unknown 0x%lx - %d", dwAlgID, dwStrength); } DWORD UpdateGlobals(BOOL fForce) { DWORD lRet = ERROR_SUCCESS; DWORD dwDisposition; if(NULL == g_fcsGlobalsInitialized || NULL == g_hProtectedStorageKey || NULL == g_hProtectedStorageChangeEvent) { return ERROR_SUCCESS; } if(WAIT_OBJECT_0 == WaitForSingleObject(g_hProtectedStorageChangeEvent, 0)) { // Update the globals, as they have changed DWORD dwParameterValue; DWORD cbParameter = sizeof(dwParameterValue); DWORD dwValueType; RtlEnterCriticalSection(&g_csGlobals); lRet = RegQueryValueExU( g_hProtectedStorageKey, REGVAL_MK_DEFAULT_ITERATION_COUNT, NULL, &dwValueType, (LPBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // // Only allow policy to increase the iteration // count, never decrease it. // if( dwParameterValue > g_IterationCount) { g_IterationCount = dwParameterValue; } } lRet = RegQueryValueExU( g_hProtectedStorageKey, REGVAL_MK_LEGACY_COMPLIANCE, NULL, &dwValueType, (LPBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { if( dwParameterValue != 0) { g_LegacyMode = TRUE; } } lRet = RegQueryValueExU( g_hProtectedStorageKey, REGVAL_MK_LEGACY_NT4_DOMAIN, NULL, &dwValueType, (LPBYTE)&dwParameterValue, &cbParameter ); if((lRet == ERROR_SUCCESS) && (dwValueType == REG_DWORD) && (dwParameterValue != 0)) { g_LegacyModeNt4Domain = TRUE; } else { g_LegacyModeNt4Domain = FALSE; } lRet = RegQueryValueExU( g_hProtectedStorageKey, REGVAL_DISTRIBUTE_BACKUP_KEY, NULL, &dwValueType, (LPBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // User specified registry value, so do what it says. g_DistributeDomainBackupKey = (dwParameterValue != 0); D_DebugLog((DEB_TRACE, "Registry: distribute whistler domain backup key: %s\n", g_DistributeDomainBackupKey ? "TRUE" : "FALSE")); } else { // Registry entry does not exist, so check to see if // the domain is in "Whistler native mode" and if so // then distribute the whistler domain backup key. g_DistributeDomainBackupKey = LsaINoMoreWin2KDomain(); D_DebugLog((DEB_TRACE, "Policy: distribute whistler domain backup key: %s\n", g_DistributeDomainBackupKey ? "TRUE" : "FALSE")); } lRet = RegQueryValueExU( g_hProtectedStorageKey, REGVAL_POLICY_MK, NULL, &dwValueType, (LPBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { if( dwParameterValue == 1 ) { g_dwMasterKeyDefaultPolicy = POLICY_LOCAL_BACKUP; } } cbParameter = sizeof(DWORD); lRet = RegQueryValueExU( g_hProtectedStorageKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwAlgID_Encr_Alg = dwParameterValue; } cbParameter = sizeof(DWORD); lRet = RegQueryValueExU( g_hProtectedStorageKey, CRYPTPROTECT_DEFAULT_PROVIDER_ENCR_ALG_KEYSIZE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwAlgID_Encr_Alg_KeySize = dwParameterValue; } cbParameter = sizeof(DWORD); lRet = RegQueryValueExU( g_hProtectedStorageKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwAlgID_MAC_Alg = dwParameterValue; } cbParameter = sizeof(DWORD); lRet = RegQueryValueExU( g_hProtectedStorageKey, CRYPTPROTECT_DEFAULT_PROVIDER_MAC_ALG_KEYSIZE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwAlgID_MAC_Alg_KeySize = dwParameterValue; } cbParameter = sizeof(DWORD); lRet = RegQueryValueExU( g_hProtectedStorageKey, CRYPTPROTECT_DEFAULT_PROVIDER_CRYPT_PROV_TYPE, NULL, &dwValueType, (PBYTE)&dwParameterValue, &cbParameter ); if( lRet == ERROR_SUCCESS && dwValueType == REG_DWORD ) { // if successful, commit g_dwDefaultCryptProvType = dwParameterValue; } // Register to be notified of future registry changes. lRet = RegNotifyChangeKeyValue(g_hProtectedStorageKey, TRUE, // bWatchSubtree REG_NOTIFY_CHANGE_LAST_SET | REG_NOTIFY_CHANGE_NAME, g_hProtectedStorageChangeEvent, TRUE); if(ERROR_SUCCESS != lRet) { // // If notify failed, we no longer notify, so we don't need to handle anymore CloseHandle(g_hProtectedStorageChangeEvent); g_hProtectedStorageChangeEvent = NULL; } RtlLeaveCriticalSection(&g_csGlobals); } return lRet; } DWORD IntializeGlobals() { DWORD lRet = ERROR_SUCCESS; DWORD dwDisposition; static const WCHAR szProviderKeyName[] = REG_CRYPTPROTECT_LOC L"\\" REG_CRYPTPROTECT_PROVIDERS_SUBKEYLOC L"\\" CRYPTPROTECT_DEFAULT_PROVIDER_GUIDSZ ; lRet = RtlInitializeCriticalSection(&g_csGlobals); if(!NT_SUCCESS(lRet)) { return lRet; } g_fcsGlobalsInitialized = TRUE; lRet = RegCreateKeyExU( HKEY_LOCAL_MACHINE, szProviderKeyName, 0, NULL, 0, KEY_QUERY_VALUE | KEY_NOTIFY, NULL, &g_hProtectedStorageKey, &dwDisposition ); if(lRet != ERROR_SUCCESS) { goto error; } g_hProtectedStorageChangeEvent = CreateEvent(NULL, FALSE, TRUE, NULL); lRet = UpdateGlobals(TRUE); error: return lRet; } DWORD ShutdownGlobals() { DWORD lRet = ERROR_SUCCESS; DWORD dwDisposition; if(g_hProtectedStorageKey) { RegCloseKey(g_hProtectedStorageKey); g_hProtectedStorageKey = NULL; } if(g_hProtectedStorageChangeEvent) { CloseHandle(g_hProtectedStorageChangeEvent); g_hProtectedStorageChangeEvent = NULL; } if(g_fcsGlobalsInitialized) { RtlDeleteCriticalSection(&g_csGlobals); } return lRet; } DWORD GetIterationCount() { UpdateGlobals(FALSE); return g_IterationCount; } BOOL FIsLegacyCompliant() { UpdateGlobals(FALSE); return g_LegacyMode; } BOOL FIsLegacyNt4Domain() { UpdateGlobals(FALSE); return g_LegacyModeNt4Domain; } BOOL FDistributeDomainBackupKey() { UpdateGlobals(FALSE); return g_DistributeDomainBackupKey; } DWORD GetMasterKeyDefaultPolicy() { UpdateGlobals(FALSE); return g_dwMasterKeyDefaultPolicy; } DWORD GetDefaultAlgInfo(DWORD *pdwProvType, DWORD *pdwEncryptionAlg, DWORD *pdwEncryptionAlgSize, DWORD *pdwMACAlg, DWORD *pdwMACAlgSize) { BOOL fCritSec = FALSE; UpdateGlobals(FALSE); if(g_fcsGlobalsInitialized) { RtlEnterCriticalSection(&g_csGlobals); fCritSec = TRUE; } if(pdwProvType) { *pdwProvType = g_dwDefaultCryptProvType; } if(pdwEncryptionAlg) { *pdwEncryptionAlg = g_dwAlgID_Encr_Alg; } if(pdwEncryptionAlgSize) { *pdwEncryptionAlgSize = g_dwAlgID_Encr_Alg_KeySize; } if(pdwMACAlg) { *pdwMACAlg = g_dwAlgID_MAC_Alg; } if(pdwMACAlgSize) { *pdwMACAlgSize = g_dwAlgID_MAC_Alg_KeySize; } if(fCritSec) { RtlLeaveCriticalSection(&g_csGlobals); } return ERROR_SUCCESS; } void InitLsaString( PLSA_UNICODE_STRING LsaString, LPWSTR String ) { DWORD StringLength; if(String == NULL) { LsaString->Buffer = NULL; LsaString->Length = 0; LsaString->MaximumLength = 0; return; } StringLength = lstrlenW(String); LsaString->Buffer = String; LsaString->Length = (USHORT) StringLength * sizeof(WCHAR); LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR); }