//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1995 ** //********************************************************************* // // content.cpp - "Content" property sheet // // HISTORY: // // 5/17/97 t-ashlm created #include "inetcplp.h" #include #include #include #include #include // // Private Functions and Structures // // WINTRUST / SOFTPUB // definition from WINTRUST.H // extern "C" BOOL WINAPI OpenPersonalTrustDBDialog(HWND hwndParent); typedef BOOL (WINAPI *WINTRUSTDLGPROC)(HWND hwndParent); WINTRUSTDLGPROC g_WinTrustDlgProc = (WINTRUSTDLGPROC)NULL; SSL_EMPTY_CACHE_FN_W g_pfnSslEmptyCacheW = (SSL_EMPTY_CACHE_FN_W)NULL; #ifdef WALLET BOOL IsWallet3Installed(); BOOL IsWalletAddressAvailable(VOID); BOOL IsWalletPaymentAvailable(VOID); #endif HRESULT ShowModalDialog(HWND hwndParent, IMoniker *pmk, VARIANT *pvarArgIn, TCHAR* pchOptions, VARIANT *pvArgOut); HCERTSTORE PFXImportCertStore(CRYPT_DATA_BLOB* pPFX, LPCWSTR szPassword, DWORD dwFlags); BOOL PFXExportCertStore(HCERTSTORE hStore, CRYPT_DATA_BLOB* pPFX, LPCWSTR szPassword, DWORD dwFlags); BOOL _AorW_GetFileNameFromBrowse(HWND hDlg, LPWSTR pszFilename, UINT cchFilename, LPCWSTR pszWorkingDir, LPCWSTR pszExt, LPCWSTR pszFilter, LPCWSTR pszTitle); INT_PTR CALLBACK AutoSuggestDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); INT_PTR CALLBACK WalletDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); //BUBUG: The following prototype should be rermoved when we have updated our Crypto API to latest version BOOL WINAPI WTHelperIsInRootStore(PCCERT_CONTEXT pCertContext); ////////////////////////////////////////////// // stolen from \inet\schannel\sspi\spreg.h #define REG_SITECERT_BASE TEXT("System\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\CertificationAuthorities") #define REG_SITECERT_CERT_VAL TEXT("CACert") #define SITECERTKEYLEN 80 // FEATURE: should probably grab this value somewhere #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #include // Use the wallet "payment" guid for JIT (different for alpha and x86...) #ifdef _ALPHA_ // {B7FB4D5C-9FBE-11D0-8965-0000F822DEA9} DEFINE_GUID(CLSID_WalletPayment, 0xb7fb4d5c, 0x9fbe, 0x11d0, 0x89, 0x65, 0x0, 0x0, 0xf8, 0x22, 0xde, 0xa9); #else // {87D3CB66-BA2E-11CF-B9D6-00A0C9083362} DEFINE_GUID(CLSID_WalletPayment, 0x87d3cb66, 0xba2e, 0x11cf, 0xb9, 0xd6, 0x0, 0xa0, 0xc9, 0x08, 0x33, 0x62); #endif // WAB GUID for JIT DEFINE_GUID(CLSID_WAB, 0x32714800, 0x2E5F, 0x11d0, 0x8B, 0x85, 0x00, 0xAA, 0x00, 0x44, 0xF9, 0x41); #define EKU_CODESIGN_OFF 0 #define EKU_EMAIL_OFF 1 #define EKU_CLIENT_OFF 2 #define EKU_SERVER_OFF 3 #define EKU_DISABLE_OFF 4 const LPSTR g_rgszEnhkeyUsage[] = { szOID_PKIX_KP_CODE_SIGNING, szOID_PKIX_KP_EMAIL_PROTECTION, szOID_PKIX_KP_CLIENT_AUTH, szOID_PKIX_KP_SERVER_AUTH, szOID_YESNO_TRUST_ATTR, NULL }; typedef struct { HWND hDlg; // handle to window HRESULT hrUseRatings; // error=not installed; S_OK=enabled; S_FALSE=disabled HINSTANCE hWinTrust; // WINTRUST/SOFTPUB library handle HINSTANCE hSChannel; // schannel library handle } CONTENTPAGE, *LPCONTENTPAGE; BOOL ContentDlgApplyNow( LPCONTENTPAGE pCon ); BOOL ContentDlgEnableControls( IN HWND hDlg ); BOOL ContentDlgInit( IN HWND hDlg ); VOID DisplayWalletPaymentDialog(HWND hWnd); VOID DisplayWalletAddressDialog(HWND hWnd); STDAPI ResetProfileSharing(HWND hwnd); EXTERN_C HRESULT ClearAutoSuggestForForms(DWORD dwClear); // // SecurityDlgEnableControls() // // Does initalization for Security Dlg. // // History: // // 6/17/96 t-gpease moved // BOOL ContentDlgEnableControls( IN HWND hDlg ) { HKEY hkey=NULL; if( g_restrict.fRatings ) { EnableWindow( GetDlgItem(hDlg, IDC_RATINGS_TURN_ON), FALSE ); EnableWindow( GetDlgItem(hDlg, IDC_ADVANCED_RATINGS_BUTTON), FALSE ); #if 0 // don't diable the text EnableDlgItem( hDlg, IDC_RATINGS_TEXT, FALSE); EnableDlgItem( hDlg, IDC_ADVANCED_RATINGS_GROUPBOX, FALSE); #endif } if( g_restrict.fCertif || g_restrict.fCertifPub) EnableWindow( GetDlgItem(hDlg, IDC_SECURITY_PUBLISHERS_BUTTON), FALSE ); if( g_restrict.fCertif || g_restrict.fCertifPers || g_restrict.fCertifSite) EnableWindow( GetDlgItem(hDlg, IDC_SECURITY_SITES_BUTTON), FALSE ); if( g_restrict.fProfiles ) { EnableWindow(GetDlgItem(hDlg, IDC_EDIT_PROFILE), FALSE); } if (hkey) RegCloseKey(hkey); #ifdef WALLET if (g_restrict.fWallet) { EnableWindow(GetDlgItem(hDlg, IDC_PROGRAMS_WALLET_SETTINGS), FALSE); } #endif return TRUE; } void InitRatingsButton(HWND hDlg, HRESULT hrEnabled) { TCHAR szBuf[MAX_RES_LEN+1]; UINT idString; BOOL fEnableSettingsButton; if (FAILED(hrEnabled)) { /* Ratings are not installed. Disable the Settings button and * set the other button to say "Enable". */ idString = IDS_RATINGS_TURN_ON; fEnableSettingsButton = FALSE; } else { idString = (hrEnabled == S_OK) ? IDS_RATINGS_TURN_OFF : IDS_RATINGS_TURN_ON; fEnableSettingsButton = TRUE; } EnableWindow(GetDlgItem(hDlg, IDC_ADVANCED_RATINGS_BUTTON), fEnableSettingsButton); if (MLLoadString( idString, szBuf, sizeof(szBuf)) > 0) { SetDlgItemText(hDlg, IDC_RATINGS_TURN_ON, szBuf); } } // // ContentDlgInit() // // Does initalization for Content Dlg. // // BOOL ContentDlgInit( HWND hDlg) { LPCONTENTPAGE pCon; pCon = (LPCONTENTPAGE)LocalAlloc(LPTR, sizeof(*pCon)); if (!pCon) { EndDialog(hDlg, 0); return FALSE; // no memory? } // tell dialog where to get info SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pCon); // save the handle to the page pCon->hDlg = hDlg; // Load the Ratings DLL (if possible) g_hinstRatings = LoadLibrary(c_tszRatingsDLL); // if not.. if (!g_hinstRatings) g_restrict.fRatings = TRUE; // disable Ratings section // set ratings dialog items... // if MSRATING.DLL not around, then don't do this call. By not // doing this, it will keep the "Enable Ratings" text on the button // but greyed off. if (g_hinstRatings) pCon->hrUseRatings = RatingEnabledQuery(); InitRatingsButton(hDlg, pCon->hrUseRatings); // if we can't find WINTRUST or SOFTPUB disable the // "Publishers" button. pCon->hWinTrust = LoadLibrary(TEXT("wintrust.dll")); if ( pCon->hWinTrust ) { g_WinTrustDlgProc = (WINTRUSTDLGPROC) GetProcAddress(pCon->hWinTrust, "OpenPersonalTrustDBDialog"); // didn't find the procecdure if (!g_WinTrustDlgProc) { // release library and try the other DLL. FreeLibrary(pCon->hWinTrust); // // We can also find the same function on NT machines (and // possibly future Win95s) in SOFTPUB.DLL so make another // check there too. // pCon->hWinTrust = LoadLibrary(TEXT("softpub.dll")); } } if (pCon->hWinTrust && !g_WinTrustDlgProc) g_WinTrustDlgProc = (WINTRUSTDLGPROC) GetProcAddress(pCon->hWinTrust, "OpenPersonalTrustDBDialog"); // if after all this, we can't find the procedure... if (!g_WinTrustDlgProc) { // disable the button EnableDlgItem(hDlg, IDC_SECURITY_PUBLISHERS_BUTTON, FALSE); } // Only present UI for flushing the SSL cache on Whistler or greater // This is the minimum version which has the default behavior of // maintaining the SSL cache for all processes in a logon session. // // Note: This support was also added for Win2K SP2, but no cache // clearing functionality was added. It's also not enabled // by default. if (IsOS(OS_WHISTLERORGREATER)) { pCon->hSChannel = LoadLibrary(TEXT("SCHANNEL.DLL")); if (pCon->hSChannel) { g_pfnSslEmptyCacheW = (SSL_EMPTY_CACHE_FN_W) GetProcAddress(pCon->hSChannel, "SslEmptyCacheW"); } } if(!g_pfnSslEmptyCacheW) { ShowWindow(GetDlgItem(hDlg, IDC_SECURITY_CLEAR_SSL_CACHE_BUTTON), SW_HIDE); EnableWindow( GetDlgItem(hDlg, IDC_SECURITY_CLEAR_SSL_CACHE_BUTTON), FALSE ); } #ifdef WALLET EnableDlgItem(hDlg, IDC_PROGRAMS_WALLET_SETTINGS, TRUE); #endif ContentDlgEnableControls(hDlg); return TRUE; } // // ContentOnCommand() // // Handles Content Dialog's window messages // // History: // // 6/17/96 t-gpease created // void ContentOnCommand(LPCONTENTPAGE pCon, UINT id, UINT nCmd) { switch (id) { case IDC_ADVANCED_RATINGS_BUTTON: { RatingSetupUI(pCon->hDlg, (LPCSTR) NULL); } break; // IDC_ADVANCED_RATINGS_BUTTON case IDC_RATINGS_TURN_ON: { if (SUCCEEDED(RatingEnable(pCon->hDlg, (LPCSTR)NULL, pCon->hrUseRatings != S_OK))) { pCon->hrUseRatings = RatingEnabledQuery(); InitRatingsButton(pCon->hDlg, pCon->hrUseRatings); } } break; case IDC_SECURITY_CLEAR_SSL_CACHE_BUTTON: { if (g_pfnSslEmptyCacheW && (*g_pfnSslEmptyCacheW)(NULL, 0)) { DWORD dwCount; // Leverage a private cache header data counter // that was never used to avoid passing a reg value. if (IncrementUrlCacheHeaderData(CACHE_HEADER_DATA_DOWNLOAD_PARTIAL, &dwCount)) { // Display message about clearing the cache OK. TCHAR szText[MAX_PATH], szTitle[80]; MLLoadShellLangString(IDS_CLEAR_SSL_CACHE_TEXT, szText, ARRAYSIZE(szText)); MLLoadShellLangString(IDS_CLEAR_SSL_CACHE_TITLE, szTitle, ARRAYSIZE(szTitle)); MessageBox(pCon->hDlg, szText, szTitle, MB_ICONINFORMATION | MB_OK); } } } break; case IDC_SECURITY_SITES_BUTTON: { CRYPTUI_CERT_MGR_STRUCT ccm = {0}; ccm.dwSize = sizeof(ccm); ccm.hwndParent = pCon->hDlg; CryptUIDlgCertMgr(&ccm); // if (!g_hinstCryptui) // { // EnableWindow(GetDlgItem(pCon->hDlg, IDC_SECURITY_SITES_BUTTON), FALSE); // } } break; case IDC_SECURITY_PUBLISHERS_BUTTON: { if (g_WinTrustDlgProc) { g_WinTrustDlgProc(pCon->hDlg); } } break; #ifdef WALLET case IDC_PROGRAMS_WALLET_SETTINGS: { HRESULT hr = S_OK; // See if wallet is installed at all if (!IsWalletPaymentAvailable()) { uCLSSPEC clsspec; clsspec.tyspec = TYSPEC_CLSID; clsspec.tagged_union.clsid = CLSID_WalletPayment; // If wallet isn't installed, ask user if they'd like to install it hr = FaultInIEFeature(NULL, &clsspec, NULL, FIEF_FLAG_FORCE_JITUI); } if (SUCCEEDED(hr)) { // Wallet is installed if (IsWallet3Installed()) { // if wallet 3.0 is installed, we want to invoke the wallet UI directly DisplayWalletPaymentDialog(pCon->hDlg); } else { // otherwise we need to pop up this intermediate dialog DialogBox(MLGetHinst(), MAKEINTRESOURCE(IDD_WALLET_SETTINGS), pCon->hDlg, WalletDlgProc); } } } break; #endif case IDC_AUTOSUGGEST_SETTINGS: { DialogBox(MLGetHinst(), MAKEINTRESOURCE(IDD_AUTOSUGGEST_SETTINGS), pCon->hDlg, AutoSuggestDlgProc); } break; case IDC_EDIT_PROFILE: { HMODULE hInstWAB = NULL; LPWABOBJECT lpWABObject = NULL; LPADRBOOK lpAdrBook = NULL; HRESULT hr=S_OK; // Ask user to JIT in WAB if it's not installed uCLSSPEC clsspec; clsspec.tyspec = TYSPEC_CLSID; clsspec.tagged_union.clsid = CLSID_WAB; // If WAB isn't installed, ask user if they'd like to install it hr = FaultInIEFeature(NULL, &clsspec, NULL, FIEF_FLAG_FORCE_JITUI); if (FAILED(hr)) { break; } // Figure out the location of the wab dll and try opening it. TCHAR szWABDllPath[MAX_PATH]; DWORD dwType = 0; ULONG cbData = sizeof(szWABDllPath); HKEY hKey = NULL; SBinary SBMe = { 0, 0}; *szWABDllPath = '\0'; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey)) { RegQueryValueEx( hKey, TEXT(""), NULL, &dwType, (LPBYTE) szWABDllPath, &cbData); RegCloseKey(hKey); } if (lstrlen(szWABDllPath) > 0 ) { hInstWAB = LoadLibrary(szWABDllPath); } if (hInstWAB) { LPWABOPEN lpfnWABOpen = (LPWABOPEN) GetProcAddress(hInstWAB, "WABOpen"); if (lpfnWABOpen) { hr = lpfnWABOpen(&lpAdrBook, &lpWABObject, NULL, 0); if (NULL == lpAdrBook || NULL == lpWABObject) hr = E_UNEXPECTED; } else { hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); // Not the right dll anyway!! } } else { hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND); } DWORD dwAction = 0; // Good so far, call GetMe. WAB may create a new entry in this call. if (SUCCEEDED(hr)) { hr = lpWABObject->GetMe(lpAdrBook, 0, &dwAction, &SBMe, 0); if (0 == SBMe.cb || NULL == SBMe.lpb) hr = E_UNEXPECTED; } // This shows the final UI. If WAB created a new entry in GetMe, they // already showed this UI and we don't need to do it again. if (SUCCEEDED(hr) && !(dwAction & WABOBJECT_ME_NEW)) { hr = lpAdrBook->Details( (LPULONG) &pCon->hDlg, NULL, NULL, SBMe.cb, (LPENTRYID)SBMe.lpb, NULL, NULL, NULL, 0); } if (lpWABObject) { if (SBMe.lpb != NULL) lpWABObject->FreeBuffer(SBMe.lpb); lpWABObject->Release(); } if (lpAdrBook) lpAdrBook->Release(); if (hInstWAB) FreeLibrary(hInstWAB); } } } // ContentOnCommand() /**************************************************************** Name: ContentDlgProc SYNOPSIS: Set various security issue settings. ****************************************************************/ INT_PTR CALLBACK ContentDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { LPCONTENTPAGE pCon; if (uMsg == WM_INITDIALOG) return ContentDlgInit( hDlg ); else pCon = (LPCONTENTPAGE) GetWindowLongPtr(hDlg, DWLP_USER); if (!pCon) return FALSE; switch (uMsg) { case WM_COMMAND: ContentOnCommand(pCon, LOWORD(wParam), HIWORD(wParam)); return TRUE; case WM_NOTIFY: { NMHDR *lpnm = (NMHDR *) lParam; ASSERT(lpnm); switch (lpnm->code) { case PSN_QUERYCANCEL: case PSN_KILLACTIVE: case PSN_RESET: SetWindowLongPtr( pCon->hDlg, DWLP_MSGRESULT, FALSE ); return TRUE; case PSN_APPLY: break; } break; } case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_DESTROY: ASSERT(pCon); if (pCon) { if (pCon->hWinTrust) { FreeLibrary(pCon->hWinTrust); g_WinTrustDlgProc = NULL; } if (pCon->hSChannel) { FreeLibrary(pCon->hSChannel); g_pfnSslEmptyCacheW = NULL; } LocalFree(pCon); } SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL); break; } return FALSE; } typedef struct tagSITECERTDIALOGINFO { HWND hDlg; HWND hwndList; HWND hwndCombo; int iSel; HCERTSTORE hCertStore; BOOL fInitializing; } SITECERTDIALOGINFO, *LPSITECERTDIALOGINFO; BOOL _SearchKeyUsage(CERT_ENHKEY_USAGE *pUsage, LPSTR pszUsageIdentifier) { DWORD i; for (i = 0; i < pUsage->cUsageIdentifier; i++) { if (StrCmpA(pUsage->rgpszUsageIdentifier[i], pszUsageIdentifier) == 0) { return(TRUE); } } return(FALSE); } BOOL _IsKnownUsage(char *pszTest) { char **ppszKnown; ppszKnown = (char **)g_rgszEnhkeyUsage; while (*ppszKnown) { if (StrCmpA(*ppszKnown, pszTest) == 0) { return(TRUE); } ppszKnown++; } return(FALSE); } void __AddAllKnownEKU(PCCERT_CONTEXT pCert) { char **ppszKnown; ppszKnown = (char **)g_rgszEnhkeyUsage; while (*ppszKnown) { CertAddEnhancedKeyUsageIdentifier(pCert, *ppszKnown); ppszKnown++; } } BOOL _AnyKnownUsage(CERT_ENHKEY_USAGE *pUsage) { DWORD i; for (i = 0; i < pUsage->cUsageIdentifier; i++) { if (_IsKnownUsage(pUsage->rgpszUsageIdentifier[i])) { return(TRUE); } } return(FALSE); } BOOL _IsUsageEnabled(PCCERT_CONTEXT pCertContext, LPSTR pszUsageIdentifier, BOOL * pfFound) { CERT_ENHKEY_USAGE *pUsage; DWORD cbUsage; *pfFound = FALSE; // // first, check the Extensions to see if we should even display it! // cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage > 0) { // // we have some... make sure ours is in the list // if (!(pUsage = (CERT_ENHKEY_USAGE *)LocalAlloc(LPTR, cbUsage))) { return(FALSE); } CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage); if (!(_SearchKeyUsage(pUsage, pszUsageIdentifier))) { LocalFree((void *)pUsage); return(FALSE); } LocalFree((void *)pUsage); } *pfFound = TRUE; // the cert should go in the list! // // ethier there where no assertions made by the CA or we found it! continue on... // // // second, check the properties to see if we should check the box // cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage > 0) { // // we have properties... make sure we aren't disabled // if (!(pUsage = (CERT_ENHKEY_USAGE *)LocalAlloc(LPTR, cbUsage))) { return(FALSE); } CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage); if (_SearchKeyUsage(pUsage, g_rgszEnhkeyUsage[EKU_DISABLE_OFF])) { // // the user has disabled the cert... keep it in the list un-checked // LocalFree((void *)pUsage); return(FALSE); } if (!(_SearchKeyUsage(pUsage, pszUsageIdentifier))) { // // the user has set some, but, disabled this one... keep in the list un-checked // LocalFree((void *)pUsage); return(FALSE); } LocalFree((void *)pUsage); } return(TRUE); } BOOL SiteCert_InitListView(LPSITECERTDIALOGINFO pscdi) { PCCERT_CONTEXT pCertContext = NULL; // delete all items currently in the listview // we'll get called back via LVN_DELETEITEM with the lParam so we can free the cert context ListView_DeleteAllItems(pscdi->hwndList); pscdi->hCertStore = CertOpenSystemStoreA(NULL, "ROOT"); if (pscdi->hCertStore) { LPSTR pszEnhkeyUsage; INT_PTR iSel; iSel = SendMessage(pscdi->hwndCombo, CB_GETCURSEL, 0,0); pszEnhkeyUsage = (LPSTR)SendMessage(pscdi->hwndCombo, CB_GETITEMDATA, iSel, 0); while (pCertContext = CertEnumCertificatesInStore(pscdi->hCertStore, pCertContext)) { CHAR szCertA[MAX_PATH]; TCHAR szCert[MAX_PATH]; DWORD cbszCert = ARRAYSIZE(szCertA); DWORD dwEnabled; BOOL fFound; dwEnabled = _IsUsageEnabled(pCertContext, (LPSTR)pszEnhkeyUsage, &fFound); // if not found, then continue with next if (!fFound) continue; //ParseX509EncodedCertificateForListBoxEntry(pCertContext->pbCertEncoded, pCertContext->cbCertEncoded, szCert, &cbszCert); ParseX509EncodedCertificateForListBoxEntry((BYTE *)pCertContext, -1, szCertA, &cbszCert); #ifdef UNICODE SHAnsiToUnicode(szCertA, szCert, ARRAYSIZE(szCert)); #else StrCpy(szCert, szCertA); #endif LV_ITEM lvi = { 0 }; lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM; lvi.iItem = -1; lvi.pszText = szCert; // (LPSTR)pCertContext->pCertInfo->Subject.pbData; lvi.cchTextMax = ARRAYSIZE(szCert); // pCertContext->pCertInfo->Subject.cbData; lvi.stateMask = LVIS_STATEIMAGEMASK; lvi.state = dwEnabled ? 0x00002000 : 0x00001000; lvi.lParam = (LPARAM)CertDuplicateCertificateContext(pCertContext); // insert and set state ListView_SetItemState(pscdi->hwndList, ListView_InsertItem(pscdi->hwndList, &lvi), dwEnabled ? 0x00002000 : 0x00001000, LVIS_STATEIMAGEMASK); } // show the items ListView_RedrawItems(pscdi->hwndList, 0, ListView_GetItemCount(pscdi->hwndList)); } return TRUE; } ////////////////////////////////////////////////////////////////////////// //// //// 08-Sep-1997: pberkman //// //// PRIVATE function: _SiteCertAdjustProperties //// //// based on what the user just checked/unchecked, set the //// appropriate OID usage or remove it. //// void _SiteCertAdjustProperties(LPSITECERTDIALOGINFO pscdi, NM_LISTVIEW *pListView) { DWORD_PTR dwSel; char *pszOID; DWORD cbUsage; CERT_ENHKEY_USAGE *pUsage; // // if we are in the initdialog get out! // if (pscdi->fInitializing) { return; } // // make sure we have the property set // dwSel = SendMessage(pscdi->hwndCombo, CB_GETCURSEL, 0, 0); if (dwSel == CB_ERR) { return; } pszOID = (char*) SendMessage(pscdi->hwndCombo, CB_GETITEMDATA, (WPARAM)dwSel, 0); if (!(pszOID) || ((DWORD_PTR)pszOID == CB_ERR)) { return; } if (pListView->uNewState & 0x00001000) // unchecked { // // the user unchecked one of the certs. // // 1. if there are no properties, add all others -- HACKHACK! // cbUsage = 0; CertGetEnhancedKeyUsage((PCCERT_CONTEXT)pListView->lParam, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage == 0) { // add all __AddAllKnownEKU((PCCERT_CONTEXT)pListView->lParam); // remove this one CertRemoveEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, pszOID); } else { if (!(pUsage = (CERT_ENHKEY_USAGE *)LocalAlloc(LPTR, cbUsage))) { return; } CertGetEnhancedKeyUsage((PCCERT_CONTEXT)pListView->lParam, CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage); // // 2. if there are properties. // a. if this is the last known one, and it matches this, delete it and add the "disable" // if (pUsage->cUsageIdentifier == 1) { if (StrCmpA(pUsage->rgpszUsageIdentifier[0], pszOID) == 0) { CertRemoveEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, pszOID); CertAddEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, g_rgszEnhkeyUsage[EKU_DISABLE_OFF]); } } else { // // b. if there are more than one, just try to remove this one // CertRemoveEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, pszOID); } LocalFree((void *)pUsage); } return; } if (pListView->uNewState & 0x00002000) // checked { CertAddEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, pszOID); // // just in case, remove the disable! // CertRemoveEnhancedKeyUsageIdentifier((PCCERT_CONTEXT)pListView->lParam, g_rgszEnhkeyUsage[EKU_DISABLE_OFF]); } } BOOL SiteCert_OnNotify(LPSITECERTDIALOGINFO pscdi, WPARAM wParam, LPARAM lParam) { NM_LISTVIEW *pnmlv = (NM_LISTVIEW *)lParam; switch (pnmlv->hdr.code) { case LVN_ITEMCHANGED: { // check the current state of selection int iSel = ListView_GetNextItem(pscdi->hwndList, -1, LVNI_SELECTED); // check to see if we need to enable/disable the "DELETE" and "VIEW" buttons EnableWindow(GetDlgItem(pscdi->hDlg, IDC_DELETECERT), iSel != -1); EnableWindow(GetDlgItem(pscdi->hDlg, IDC_VIEWCERT), iSel != -1); if ((pnmlv->uChanged & LVIF_STATE) && (GetFocus() == pscdi->hwndList)) { _SiteCertAdjustProperties(pscdi, pnmlv); } break; } case LVN_DELETEITEM: CertFreeCertificateContext((PCCERT_CONTEXT)pnmlv->lParam); break; } return TRUE; } typedef struct tagNEWSITECERTINFO { LPVOID lpvCertData; DWORD cbCert; BOOL fCertEnabled; BOOL fNetworkClient; BOOL fNetworkServer; BOOL fSecureEmail; BOOL fSoftwarePublishing; } NEWSITECERTINFO, *LPNEWSITECERTINFO; BOOL NewSiteCert_AddCert(LPNEWSITECERTINFO pnsci) { HCERTSTORE hCertStore = NULL; PCCERT_CONTEXT pCertContext; BOOL fRet = FALSE; hCertStore = CertOpenSystemStoreA(NULL, "ROOT"); if (hCertStore) { pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, (LPBYTE)(pnsci->lpvCertData), pnsci->cbCert); if (pCertContext) { if (CertCompareCertificateName(X509_ASN_ENCODING, &pCertContext->pCertInfo->Subject, &pCertContext->pCertInfo->Issuer)) { CertFreeCertificateContext(pCertContext); fRet = CertAddEncodedCertificateToStore(hCertStore, X509_ASN_ENCODING, (LPBYTE)(pnsci->lpvCertData), pnsci->cbCert, CERT_STORE_ADD_REPLACE_EXISTING, &pCertContext); if (fRet) { # define l_USAGE_MAX 24 CERT_ENHKEY_USAGE ceku = {0}; LPSTR rgpszUsageIdentifier[l_USAGE_MAX]; if (pnsci->fNetworkClient) { rgpszUsageIdentifier[ceku.cUsageIdentifier] = g_rgszEnhkeyUsage[EKU_CLIENT_OFF]; if (rgpszUsageIdentifier[ceku.cUsageIdentifier]) ceku.cUsageIdentifier++; } if (pnsci->fNetworkServer) { rgpszUsageIdentifier[ceku.cUsageIdentifier] = g_rgszEnhkeyUsage[EKU_SERVER_OFF]; if (rgpszUsageIdentifier[ceku.cUsageIdentifier]) ceku.cUsageIdentifier++; } if (pnsci->fSecureEmail) { rgpszUsageIdentifier[ceku.cUsageIdentifier] = g_rgszEnhkeyUsage[EKU_EMAIL_OFF]; if (rgpszUsageIdentifier[ceku.cUsageIdentifier]) ceku.cUsageIdentifier++; } if (pnsci->fSoftwarePublishing) { rgpszUsageIdentifier[ceku.cUsageIdentifier] = g_rgszEnhkeyUsage[EKU_CODESIGN_OFF]; if (rgpszUsageIdentifier[ceku.cUsageIdentifier]) ceku.cUsageIdentifier++; } if (!(pnsci->fCertEnabled)) { // turn everything off!!! rgpszUsageIdentifier[ceku.cUsageIdentifier] = g_rgszEnhkeyUsage[EKU_DISABLE_OFF]; if (rgpszUsageIdentifier[ceku.cUsageIdentifier]) ceku.cUsageIdentifier++; } // // now, add any "unknown" extensions that the CA may have put on just // so verification will succeed! // CERT_ENHKEY_USAGE *pUsage; DWORD cbUsage; DWORD i; pUsage = NULL; cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &cbUsage); if (cbUsage > 0) { if (pUsage = (PCERT_ENHKEY_USAGE)LocalAlloc(LMEM_FIXED, cbUsage)) { CertGetEnhancedKeyUsage(pCertContext, CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &cbUsage); for (i = 0; i < pUsage->cUsageIdentifier; i++) { if (ceku.cUsageIdentifier >= l_USAGE_MAX) { break; } if (pUsage->rgpszUsageIdentifier[i]) { if (!(_IsKnownUsage(pUsage->rgpszUsageIdentifier[i]))) { rgpszUsageIdentifier[ceku.cUsageIdentifier] = pUsage->rgpszUsageIdentifier[i]; ceku.cUsageIdentifier++; } } } } } ceku.rgpszUsageIdentifier = (LPSTR *)rgpszUsageIdentifier; fRet = CertSetEnhancedKeyUsage(pCertContext, &ceku); if (pUsage) { LocalFree((void *)pUsage); } CertFreeCertificateContext(pCertContext); } } } CertCloseStore(hCertStore, CERT_CLOSE_STORE_CHECK_FLAG); } return fRet; } ////////////////////////////////////////////////////////////////////////// //// //// 15-Aug-1997: pberkman //// //// PRIVATE function: NewSiteCert_SetAvailableAuthorityCheckboxes //// //// set the check boxes in the "New Site Certificate" dialog box //// based on the Authority Extensions and Properties. //// //// if there are no Authority Ext or Prop's, then the certificate //// has the potential for the user to enable for all. Otherwise, //// the user can ONLY select the ones that the issuer (or MS) has //// entrusted the certificate for. //// typedef struct l_CERTUSAGES_ { char *pszOID; DWORD dwControlId; BOOL fEnabled; } l_CERTUSAGES; BOOL NewSiteCert_SetAvailableAuthorityCheckboxes(HWND hDlg, LPNEWSITECERTINFO pnsci, BOOL fInitialize) { l_CERTUSAGES asUsages[] = { szOID_PKIX_KP_CLIENT_AUTH, IDC_CHECK_NETWORK_CLIENT, FALSE, szOID_PKIX_KP_SERVER_AUTH, IDC_CHECK_NETWORK_SERVER, FALSE, szOID_PKIX_KP_EMAIL_PROTECTION, IDC_CHECK_SECURE_EMAIL, FALSE, szOID_PKIX_KP_CODE_SIGNING, IDC_CHECK_SOFTWARE_PUBLISHING, FALSE, NULL, 0, FALSE }; l_CERTUSAGES *psUsages; PCCERT_CONTEXT pCertContext; DWORD cbUsage; PCERT_ENHKEY_USAGE pUsage; if (fInitialize) { CheckDlgButton(hDlg, IDC_CHECK_ENABLE_CERT, BST_CHECKED); CheckDlgButton(hDlg, IDC_CHECK_NETWORK_CLIENT, BST_CHECKED); CheckDlgButton(hDlg, IDC_CHECK_NETWORK_SERVER, BST_CHECKED); CheckDlgButton(hDlg, IDC_CHECK_SECURE_EMAIL, BST_CHECKED); CheckDlgButton(hDlg, IDC_CHECK_SOFTWARE_PUBLISHING, BST_CHECKED); } pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, (LPBYTE)(pnsci->lpvCertData), pnsci->cbCert); if (!(pCertContext)) { psUsages = &asUsages[0]; while (psUsages->pszOID) { EnableWindow(GetDlgItem(hDlg, psUsages->dwControlId), TRUE); psUsages++; } return(FALSE); } cbUsage = 0; CertGetEnhancedKeyUsage(pCertContext, 0, NULL, &cbUsage); if (cbUsage < 1) { // none defined... leave all enabled. CertFreeCertificateContext(pCertContext); psUsages = &asUsages[0]; while (psUsages->pszOID) { EnableWindow(GetDlgItem(hDlg, psUsages->dwControlId), TRUE); psUsages++; } return(TRUE); } if (!(pUsage = (PCERT_ENHKEY_USAGE)LocalAlloc(LMEM_FIXED, cbUsage))) { CertFreeCertificateContext(pCertContext); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return(FALSE); } if (!(CertGetEnhancedKeyUsage(pCertContext, 0, pUsage, &cbUsage))) { CertFreeCertificateContext(pCertContext); LocalFree(pUsage); return(FALSE); } if (pUsage->cUsageIdentifier == 0) { CertFreeCertificateContext(pCertContext); LocalFree(pUsage); // none defined... leave all enabled. return(TRUE); } CertFreeCertificateContext(pCertContext); for (int i = 0; i < (int)pUsage->cUsageIdentifier; i++) { psUsages = &asUsages[0]; while (psUsages->pszOID) { if (StrCmpA(pUsage->rgpszUsageIdentifier[i], psUsages->pszOID) == 0) { psUsages->fEnabled = TRUE; } psUsages++; } } LocalFree(pUsage); psUsages = &asUsages[0]; while (psUsages->pszOID) { if (fInitialize) { CheckDlgButton(hDlg, psUsages->dwControlId, (psUsages->fEnabled) ? BST_CHECKED : BST_UNCHECKED); } EnableWindow(GetDlgItem(hDlg, psUsages->dwControlId), psUsages->fEnabled); psUsages++; } return(TRUE); } void NewSiteCert_CenterDialog(HWND hDlg) { RECT rcDlg; RECT rcArea; RECT rcCenter; HWND hWndParent; HWND hWndCenter; DWORD dwStyle; int w_Dlg; int h_Dlg; int xLeft; int yTop; GetWindowRect(hDlg, &rcDlg); dwStyle = (DWORD)GetWindowLong(hDlg, GWL_STYLE); if (dwStyle & WS_CHILD) { hWndCenter = GetParent(hDlg); hWndParent = GetParent(hDlg); GetClientRect(hWndParent, &rcArea); GetClientRect(hWndCenter, &rcCenter); MapWindowPoints(hWndCenter, hWndParent, (POINT *)&rcCenter, 2); } else { hWndCenter = GetWindow(hDlg, GW_OWNER); if (hWndCenter) { dwStyle = (DWORD)GetWindowLong(hWndCenter, GWL_STYLE); if (!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE)) { hWndCenter = NULL; } } SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); if (hWndCenter) { GetWindowRect(hWndCenter, &rcCenter); } else { rcCenter = rcArea; } } w_Dlg = rcDlg.right - rcDlg.left; h_Dlg = rcDlg.bottom - rcDlg.top; xLeft = (rcCenter.left + rcCenter.right) / 2 - w_Dlg / 2; yTop = (rcCenter.top + rcCenter.bottom) / 2 - h_Dlg / 2; if (xLeft < rcArea.left) { xLeft = rcArea.left; } else if ((xLeft + w_Dlg) > rcArea.right) { xLeft = rcArea.right - w_Dlg; } if (yTop < rcArea.top) { yTop = rcArea.top; } else if ((yTop + h_Dlg) > rcArea.bottom) { yTop = rcArea.bottom - h_Dlg; } SetWindowPos(hDlg, NULL, xLeft, yTop, -1, -1, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); } INT_PTR CALLBACK NewSiteCert_DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { LPNEWSITECERTINFO pnsci = (LPNEWSITECERTINFO)GetWindowLongPtr(hDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { DWORD dwFileSize; DWORD cbRead; HANDLE hf; LPTSTR lpszCmdLine = (LPTSTR)lParam; DWORD dwError; hf = CreateFile(lpszCmdLine, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hf == INVALID_HANDLE_VALUE) { dwError = GetLastError(); goto initError; } dwFileSize = GetFileSize(hf, NULL); if (dwFileSize == (unsigned)-1) goto initError; pnsci = (LPNEWSITECERTINFO)LocalAlloc(LPTR, sizeof(*pnsci)); if (!pnsci) goto initError; pnsci->lpvCertData = LocalAlloc(LPTR, dwFileSize); if (!pnsci->lpvCertData) goto initError; pnsci->cbCert = dwFileSize; if (!ReadFile(hf, pnsci->lpvCertData, dwFileSize, &cbRead, NULL) || cbRead != dwFileSize) goto initError; SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pnsci); // save pointer to cert // // ok check to make sure that 1) it's a cert file and 2) it's a root! // PCCERT_CONTEXT pCertContext; dwError = S_FALSE; pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, (LPBYTE)(pnsci->lpvCertData), pnsci->cbCert); if (pCertContext) { if (CertCompareCertificateName(X509_ASN_ENCODING, &pCertContext->pCertInfo->Subject, &pCertContext->pCertInfo->Issuer)) { dwError = S_OK; } CertFreeCertificateContext(pCertContext); } if (dwError != S_OK) { goto initError; } NewSiteCert_SetAvailableAuthorityCheckboxes(hDlg, pnsci, TRUE); NewSiteCert_CenterDialog(hDlg); break; initError: TCHAR szTitle[MAX_PATH + 1]; TCHAR szError[MAX_PATH + 1]; MLLoadShellLangString(IDS_CERT_FILE_INVALID, &szError[0], MAX_PATH); MLLoadShellLangString(IDS_ERROR, &szTitle[0], MAX_PATH); MessageBox(GetFocus(), &szError[0], &szTitle[0], MB_OK | MB_ICONERROR); EndDialog(hDlg, IDCANCEL); return FALSE; } case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: { pnsci->fCertEnabled = IsDlgButtonChecked(hDlg, IDC_CHECK_ENABLE_CERT); pnsci->fNetworkClient = IsDlgButtonChecked(hDlg, IDC_CHECK_NETWORK_CLIENT); pnsci->fNetworkServer = IsDlgButtonChecked(hDlg, IDC_CHECK_NETWORK_SERVER); pnsci->fSecureEmail = IsDlgButtonChecked(hDlg, IDC_CHECK_SECURE_EMAIL); pnsci->fSoftwarePublishing = IsDlgButtonChecked(hDlg, IDC_CHECK_SOFTWARE_PUBLISHING); NewSiteCert_AddCert(pnsci); EndDialog(hDlg, IDOK); break; } case IDCANCEL: EndDialog(hDlg, IDCANCEL); break; case IDC_VIEWCERT: ShowX509EncodedCertificate(hDlg, (LPBYTE)pnsci->lpvCertData, pnsci->cbCert); break; case IDC_CHECK_ENABLE_CERT: if (HIWORD(wParam) == BN_CLICKED) { BOOL fEnableCert; fEnableCert = IsDlgButtonChecked(hDlg, IDC_CHECK_ENABLE_CERT); if (!(fEnableCert)) { EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NETWORK_CLIENT), fEnableCert); EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NETWORK_SERVER), fEnableCert); EnableWindow(GetDlgItem(hDlg, IDC_CHECK_SECURE_EMAIL), fEnableCert); EnableWindow(GetDlgItem(hDlg, IDC_CHECK_SOFTWARE_PUBLISHING), fEnableCert); } else { NewSiteCert_SetAvailableAuthorityCheckboxes(hDlg, pnsci, FALSE); } } return(FALSE); default: return FALSE; } return TRUE; break; case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_DESTROY: if (pnsci) { if (pnsci->lpvCertData) LocalFree(pnsci->lpvCertData); LocalFree(pnsci); } break; } return FALSE; } STDAPI SiteCert_RunFromCmdLine(HINSTANCE hinst, HINSTANCE hPrevInstance, LPTSTR lpszCmdLine, int nCmdShow) { if ((!lpszCmdLine) || (*lpszCmdLine == TEXT('\0'))) return -1; DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_NEWSITECERT), NULL, NewSiteCert_DlgProc, (LPARAM)lpszCmdLine); return 0; } // Helper function for ExportPFX #define NUM_KNOWN_STORES 5 BOOL OpenAndAllocKnownStores(DWORD *pchStores, HCERTSTORE **ppahStores) { HCERTSTORE hStore; int i; static const LPCTSTR rszStoreNames[NUM_KNOWN_STORES] = { TEXT("ROOT"), TEXT("TRUST"), TEXT("CA"), TEXT("MY"), TEXT("SPC") }; *pchStores = 0; if (NULL == ((*ppahStores) = (HCERTSTORE *) LocalAlloc(LPTR, sizeof(HCERTSTORE) * NUM_KNOWN_STORES))) { return (FALSE); } for (i=0; i< NUM_KNOWN_STORES; i++) { (*ppahStores)[i] = NULL; if (hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG | CERT_STORE_NO_CRYPT_RELEASE_FLAG, rszStoreNames[i])) (*ppahStores)[(*pchStores)++] = hStore; } return(TRUE); } // Helper function for ExportPFX void CloseAndFreeKnownStores(HCERTSTORE *pahStores) { int i; for (i=0; ipszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { goto Cleanup; } dwAddFlags = (pImp->fUseExisting) ? CERT_STORE_ADD_USE_EXISTING : CERT_STORE_ADD_REPLACE_EXISTING; sData.cbData = GetFileSize(hFile, NULL); sData.pbData = (PBYTE)LocalAlloc(LMEM_FIXED, sData.cbData); if (!(sData.pbData)) { goto Cleanup; } if (!(ReadFile(hFile, sData.pbData, sData.cbData, &cbRead, NULL))) { goto Cleanup; } if ((pImp->pwszPassword) && (!(*pImp->pwszPassword))) // if no password, use null. { pImp->pwszPassword = NULL; } if (!(hCertStore = PFXImportCertStore(&sData, pImp->pwszPassword, dwImportFlags))) { goto Cleanup; } // // now we have in memory hStore enumerate the cert contexts // and drop them into destination store // if (!(pahStores[MY_STORE] = CertOpenSystemStoreA(NULL, "MY")) || !(pahStores[CA_STORE] = CertOpenSystemStoreA(NULL, "CA")) || !(pahStores[ROOT_STORE] = CertOpenSystemStoreA(NULL, "ROOT"))) { goto Cleanup; } while (pCertCtxt = CertEnumCertificatesInStore(hCertStore, pCertCtxt)) { fAdded = FALSE; cbRead = 0; CertGetCertificateContextProperty(pCertCtxt, CERT_KEY_PROV_INFO_PROP_ID, NULL, &cbRead); if (cbRead > 0) // pfx added a public key prop { CertAddCertificateContextToStore(pahStores[MY_STORE], pCertCtxt, dwAddFlags, NULL); continue; } // // first, check if we already have this cert in one of our stores // for (i = 0; i < MAX_STORE; i++) { if (__IsCertInStore(pCertCtxt, pahStores[i])) { // // the same cert, exactly, is already in one of our stores! // fAdded = TRUE; break; } } if (!(fAdded)) { CertAddCertificateContextToStore(pahStores[CA_STORE], pCertCtxt, dwAddFlags, NULL); } } fRet = TRUE; Cleanup: if (sData.pbData) { LocalFree(sData.pbData); } if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } if (hCertStore) { CertCloseStore(hCertStore, 0); } for (i = 0; i < MAX_STORE; i++) { if (pahStores[i]) { CertCloseStore(pahStores[i], 0); } } return(fRet); } typedef PCCERT_CONTEXT (* PFNWTHELPER) (PCCERT_CONTEXT /* pChildContext */, DWORD /* chStores */, HCERTSTORE * /* pahStores */, FILETIME * /* psftVerifyAsOf*/, DWORD /* dwEncoding */, DWORD * /* pdwConfidence */, DWORD * /* pdwError */ ); BOOL ExportPFX(LPIMPORTEXPORT pImp) { BOOL fRet = FALSE; HANDLE hFile = NULL; CRYPT_DATA_BLOB sData; DWORD cbRead; HCERTSTORE hSrcCertStore; DWORD dwExportFlags = 4; // 4 == EXPORT_PRIVATE_KEYS; TCHAR szText[MAX_PATH], szTitle[80]; PCCERT_CONTEXT pTempCertContext; HCERTSTORE *phCertStores = NULL; DWORD chCertStores = 0; DWORD dwConfidence; DWORD dwError; HINSTANCE hiWintrust = NULL; PFNWTHELPER WTHelperCertFindIssuerCertificate; if (!pImp->pCertContext) return FALSE; ZeroMemory(&sData, sizeof(CRYPT_DATA_BLOB)); // create an in memory store hSrcCertStore = CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, NULL); if (!CertAddCertificateContextToStore(hSrcCertStore, pImp->pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL)) goto Cleanup; // Load helper function from wintrust.dll hiWintrust = LoadLibrary(TEXT("WINTRUST.DLL")); WTHelperCertFindIssuerCertificate = (PFNWTHELPER) GetProcAddress(hiWintrust,"WTHelperCertFindIssuerCertificate"); if (WTHelperCertFindIssuerCertificate) { // Load all the top level stores, so we can export from them if necessary if (OpenAndAllocKnownStores(&chCertStores, &phCertStores)) { // Find the intermediate certifcates, and add them to the store that we will be exporting pTempCertContext = pImp->pCertContext; while (NULL != ( pTempCertContext = WTHelperCertFindIssuerCertificate(pTempCertContext, chCertStores, phCertStores, NULL, X509_ASN_ENCODING, &dwConfidence, &dwError))) { CertAddCertificateContextToStore(hSrcCertStore, pTempCertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL); // Break out if we find a root (self-signed) cert if (CertCompareCertificateName(X509_ASN_ENCODING, &pTempCertContext->pCertInfo->Subject, &pTempCertContext->pCertInfo->Issuer)) break; } CloseAndFreeKnownStores(phCertStores); } } // // This first call simply gets the size of the crypt blob // if (!PFXExportCertStore(hSrcCertStore, &sData, pImp->pwszPassword, dwExportFlags)) { goto Cleanup; } // Alloc based on cbData sData.pbData = (PBYTE)LocalAlloc(LMEM_FIXED, sData.cbData); // // Now actually get the data // if (!(*pImp->pwszPassword)) // no password use null pImp->pwszPassword = NULL; if (!PFXExportCertStore(hSrcCertStore, &sData, pImp->pwszPassword, dwExportFlags)) { goto Cleanup; } // Open the PFX file hFile = CreateCertFile(pImp->pszPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { goto Cleanup; } // Write to it if (!WriteFile(hFile, sData.pbData, sData.cbData, &cbRead, NULL)) { goto Cleanup; } // Display message about certs exporting OK. MLLoadShellLangString(IDS_CERT_EXPORTOKTEXT, szText, ARRAYSIZE(szText)); MLLoadShellLangString(IDS_CERT_EXPORTOKTITLE, szTitle, ARRAYSIZE(szTitle)); MessageBox(pImp->hDlg, szText, szTitle, MB_ICONINFORMATION | MB_OK); fRet = TRUE; Cleanup: if (hiWintrust) FreeLibrary(hiWintrust); if (hSrcCertStore) CertCloseStore(hSrcCertStore, 0); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); if (sData.pbData) LocalFree(sData.pbData); return fRet; } INT_PTR CALLBACK ImportExportDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { LPIMPORTEXPORT pImp; if (uMsg == WM_INITDIALOG) { pImp = (LPIMPORTEXPORT)lParam; // this is passed in to us if (!pImp) { EndDialog(hDlg, 0); return FALSE; } // tell dialog where to get info SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pImp); // save handle to the page pImp->hDlg = hDlg; // limit the password to 32 chars SendMessage(GetDlgItem(hDlg, IDC_PASSWORD), EM_LIMITTEXT, MAX_PASSWORD, 0); // // 03-Oct-1997 pberkman: always verify password! // if (pImp->dwImportExport == PFX_EXPORT) { SendMessage(GetDlgItem(hDlg, IDC_PASSWORD2), EM_LIMITTEXT, MAX_PASSWORD, 0); } SHAutoComplete(GetDlgItem(hDlg, IDC_FILENAME), SHACF_DEFAULT); // This control exists in both IDD_PFX_IMPORT and IDD_PFX_EXPORT // only set these on import, since they don't exist on export =) // ========================================================================= // 03-Oct-1997 pberkman: no user decisions! // // if (pImp->dwImportExport == PFX_IMPORT) // { // CheckRadioButton(hDlg, IDC_USE_EXISTING, IDC_USE_FILE, IDC_USE_EXISTING); // } // ========================================================================== SetFocus(GetDlgItem(hDlg, IDC_PASSWORD)); } // WM_INITDIALOG else pImp = (LPIMPORTEXPORT)GetWindowLongPtr(hDlg, DWLP_USER); if (!pImp) return FALSE; switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CERT_BROWSE: { TCHAR szFilenameBrowse[MAX_PATH]; TCHAR szExt[MAX_PATH]; TCHAR szFilter[MAX_PATH]; int ret; LPITEMIDLIST pidl; TCHAR szWorkingDir[MAX_PATH]; szFilenameBrowse[0] = 0; MLLoadString(IDS_PFX_EXT, szExt, ARRAYSIZE(szExt)); int cchFilter = MLLoadString(IDS_PFX_FILTER, szFilter, ARRAYSIZE(szFilter)-1); // Make sure we have a double null termination on the filter szFilter[cchFilter + 1] = 0; if (SHGetSpecialFolderLocation(hDlg, CSIDL_PERSONAL, &pidl) == NOERROR) { SHGetPathFromIDList(pidl, szWorkingDir); ILFree(pidl); } ret = _AorW_GetFileNameFromBrowse(hDlg, szFilenameBrowse, ARRAYSIZE(szFilenameBrowse), szWorkingDir, szExt, szFilter, NULL); if (ret > 0) { SetDlgItemText(hDlg, IDC_FILENAME, szFilenameBrowse); } break; } case IDOK: { TCHAR szPassword[MAX_PASSWORD]; TCHAR szPassword2[MAX_PASSWORD]; TCHAR szPath[MAX_PATH]; BOOL bRet; szPassword[0] = NULL; GetWindowText(GetDlgItem(hDlg, IDC_PASSWORD), szPassword, ARRAYSIZE(szPassword)); GetWindowText(GetDlgItem(hDlg, IDC_FILENAME), szPath, ARRAYSIZE(szPath)); // // 03-Oct-1997 pberkman: always double check password! // if (pImp->dwImportExport == PFX_EXPORT) { szPassword2[0] = NULL; GetWindowText(GetDlgItem(hDlg, IDC_PASSWORD2), szPassword2, ARRAYSIZE(szPassword2)); if (StrCmp(szPassword, szPassword2) != 0) { TCHAR szTitle[MAX_PATH + 1]; TCHAR szError[MAX_PATH + 1]; MLLoadShellLangString(IDS_PASSWORDS_NOMATCH, &szError[0], MAX_PATH); MLLoadShellLangString(IDS_ERROR, &szTitle[0], MAX_PATH); MessageBox(GetFocus(), &szError[0], &szTitle[0], MB_OK | MB_ICONERROR); SetFocus(GetDlgItem(hDlg, IDC_PASSWORD)); break; } } // Add a default extension on export if (pImp->dwImportExport == PFX_EXPORT) if (szPath[0] != TEXT('\0') && PathAddExtension(szPath, TEXT(".PFX"))) SetWindowText(GetDlgItem(hDlg, IDC_FILENAME), szPath); #ifndef UNICODE WCHAR wszPassword[MAX_PASSWORD]; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPassword, -1, wszPassword, ARRAYSIZE(wszPassword)); pImp->pwszPassword = wszPassword; #else pImp->pwszPassword = szPassword; #endif pImp->pszPath = szPath; if (pImp->dwImportExport == PFX_IMPORT) { // ========================================================================= // 03-Oct-1997 pberkman: no user decisions! // // pImp->fUseExisting = IsDlgButtonChecked(hDlg, IDC_USE_EXISTING); // ========================================================================= pImp->fUseExisting = FALSE; bRet = ImportPFX(pImp); if (!(bRet) && (GetLastError() == NTE_BAD_DATA)) { // message.... } } else { bRet = ExportPFX(pImp); } EndDialog(hDlg, bRet); break; } case IDCANCEL: EndDialog(hDlg, TRUE); // Cancel is not an error break; } break; case WM_NOTIFY: break; // No context sensitive help yet... #if 0 case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; #endif case WM_DESTROY: SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NULL); break; } return FALSE; } #ifdef UNIX EXTERN_C #endif INT_PTR ImportExportPFX(HWND hwndParent, DWORD dwImportExport, LPBYTE pbCert, DWORD cbCert) { IMPORTEXPORT imp; if (pbCert) { CRYPT_HASH_BLOB hashBlob; HCERTSTORE hMy = CertOpenSystemStoreA(NULL, "MY"); DWORD cbSHA1Hash; LPBYTE pbSHA1Hash; if (!hMy) return FALSE; if (CryptHashCertificate(NULL, 0, 0, pbCert, cbCert, NULL, &cbSHA1Hash)) { pbSHA1Hash = (LPBYTE)LocalAlloc(LPTR, cbSHA1Hash); if (!pbSHA1Hash) return FALSE; if (CryptHashCertificate(NULL, 0, 0, pbCert, cbCert, pbSHA1Hash, &cbSHA1Hash)) { hashBlob.cbData = cbSHA1Hash; hashBlob.pbData = pbSHA1Hash; imp.pCertContext = CertFindCertificateInStore(hMy, X509_ASN_ENCODING, 0, CERT_FIND_HASH, &hashBlob, NULL); if (!(imp.pCertContext)) return FALSE; } LocalFree(pbSHA1Hash); } CertCloseStore(hMy, 0); } imp.dwImportExport = dwImportExport; return DialogBoxParam(MLGetHinst(), dwImportExport == PFX_IMPORT ? MAKEINTRESOURCE(IDD_PFX_IMPORT) : MAKEINTRESOURCE(IDD_PFX_EXPORT), hwndParent, ImportExportDlgProc, (LPARAM)&imp); } //BUBUG: The following function should be rermoved when we have updated our Crypto API to latest BOOL WINAPI WTHelperIsInRootStore(PCCERT_CONTEXT pCertContext) { HCERTSTORE hStore; if (!(hStore = CertOpenStore( CERT_STORE_PROV_SYSTEM_A, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_READONLY_FLAG | CERT_STORE_NO_CRYPT_RELEASE_FLAG, "ROOT"))) { return(FALSE); } // // can't do it the fast way -- do it the slow way! // BYTE *pbHash; DWORD cbHash; CRYPT_HASH_BLOB sBlob; PCCERT_CONTEXT pWorkContext; cbHash = 0; if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, NULL, &cbHash))) { CertCloseStore(hStore, 0); return(FALSE); } if (cbHash < 1) { CertCloseStore(hStore, 0); return(FALSE); } if (!(pbHash = new BYTE[cbHash])) { CertCloseStore(hStore, 0); return(FALSE); } if (!(CertGetCertificateContextProperty(pCertContext, CERT_SHA1_HASH_PROP_ID, pbHash, &cbHash))) { delete pbHash; CertCloseStore(hStore, 0); return(FALSE); } sBlob.cbData = cbHash; sBlob.pbData = pbHash; pWorkContext = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SHA1_HASH, &sBlob, NULL); delete pbHash; if (pWorkContext) { CertFreeCertificateContext(pWorkContext); CertCloseStore(hStore, 0); return(TRUE); } CertCloseStore(hStore, 0); return(FALSE); } //============================================================================ const TCHAR c_szRegKeySMIEM[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main"); const TCHAR c_szRegValFormSuggest[] = TEXT("Use FormSuggest"); const TCHAR c_szRegValFormSuggestPW[] = TEXT("FormSuggest Passwords"); const TCHAR c_szRegValFormSuggestPWAsk[] = TEXT("FormSuggest PW Ask"); const TCHAR c_szYes[] = TEXT("yes"); const TCHAR c_szNo[] = TEXT("no"); inline void SetValueHelper(HWND hDlg, int id, LPTSTR *ppszData, DWORD *pcbData) { if (IsDlgButtonChecked(hDlg, id)) { *ppszData = (LPTSTR)c_szYes; *pcbData = sizeof(c_szYes); } else { *ppszData = (LPTSTR)c_szNo; *pcbData = sizeof(c_szNo); } } INT_PTR CALLBACK AutoSuggestDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { CheckDlgButton(hDlg, IDC_AUTOSUGGEST_ENABLEADDR, (SHRegGetBoolUSValue(REGSTR_PATH_AUTOCOMPLETE, REGSTR_VAL_USEAUTOSUGGEST, FALSE, /*default:*/TRUE)) ? BST_CHECKED : BST_UNCHECKED); if (g_restrict.fFormSuggest) { EnableDlgItem(hDlg, IDC_AUTOSUGGEST_ENABLEFORM, FALSE); } else { CheckDlgButton(hDlg, IDC_AUTOSUGGEST_ENABLEFORM, (SHRegGetBoolUSValue(c_szRegKeySMIEM, c_szRegValFormSuggest, FALSE, /*default:*/FALSE)) ? BST_CHECKED : BST_UNCHECKED); } if (g_restrict.fFormPasswords) { EnableDlgItem(hDlg, IDC_AUTOSUGGEST_SAVEPASSWORDS, FALSE); EnableDlgItem(hDlg, IDC_AUTOSUGGEST_PROMPTPASSWORDS, FALSE); } else { CheckDlgButton(hDlg, IDC_AUTOSUGGEST_PROMPTPASSWORDS, (SHRegGetBoolUSValue(c_szRegKeySMIEM, c_szRegValFormSuggestPWAsk, FALSE, /*default:*/TRUE)) ? BST_CHECKED : BST_UNCHECKED); if (SHRegGetBoolUSValue(c_szRegKeySMIEM, c_szRegValFormSuggestPW, FALSE, /*default:*/TRUE)) { CheckDlgButton(hDlg, IDC_AUTOSUGGEST_SAVEPASSWORDS, BST_CHECKED); } else { EnableDlgItem(hDlg, IDC_AUTOSUGGEST_PROMPTPASSWORDS, FALSE); } } } return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_AUTOSUGGEST_SAVEPASSWORDS: EnableDlgItem(hDlg, IDC_AUTOSUGGEST_PROMPTPASSWORDS, IsDlgButtonChecked(hDlg, IDC_AUTOSUGGEST_SAVEPASSWORDS)); break; case IDC_AUTOSUGGEST_CLEARFORM: case IDC_AUTOSUGGEST_CLEARPASSWORDS: { BOOL fPasswords = (LOWORD(wParam) == IDC_AUTOSUGGEST_CLEARPASSWORDS); DWORD dwClear = (fPasswords) ? IECMDID_ARG_CLEAR_FORMS_PASSWORDS_ONLY : IECMDID_ARG_CLEAR_FORMS_ALL_BUT_PASSWORDS; if (IDOK == MsgBox(hDlg, ((fPasswords) ? IDS_CLEAR_FORMPASSWORDS : IDS_CLEAR_FORMSUGGEST), MB_ICONQUESTION, MB_OKCANCEL)) { HCURSOR hOldCursor = NULL; HCURSOR hNewCursor = NULL; #ifndef UNIX hNewCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)); #else // IEUNIX - Getting rid of redundant MAKEINTRESOURCE hNewCursor = LoadCursor(NULL, IDC_WAIT); #endif if (hNewCursor) hOldCursor = SetCursor(hNewCursor); // Clear all strings ClearAutoSuggestForForms(dwClear); // Also reset profile assistant sharing (very discoverable here) if (!g_restrict.fProfiles) { ResetProfileSharing(hDlg); } if(hOldCursor) SetCursor(hOldCursor); } } break; case IDOK: { DWORD cbData; LPTSTR pszData; SetValueHelper(hDlg, IDC_AUTOSUGGEST_ENABLEADDR, &pszData, &cbData); SHSetValue(HKEY_CURRENT_USER, REGSTR_PATH_AUTOCOMPLETE, REGSTR_VAL_USEAUTOSUGGEST, REG_SZ, pszData, cbData); if (!g_restrict.fFormSuggest) { SetValueHelper(hDlg, IDC_AUTOSUGGEST_ENABLEFORM, &pszData, &cbData); SHSetValue(HKEY_CURRENT_USER, c_szRegKeySMIEM, c_szRegValFormSuggest, REG_SZ, pszData, cbData); } if (!g_restrict.fFormPasswords) { SetValueHelper(hDlg, IDC_AUTOSUGGEST_SAVEPASSWORDS, &pszData, &cbData); SHSetValue(HKEY_CURRENT_USER, c_szRegKeySMIEM, c_szRegValFormSuggestPW, REG_SZ, pszData, cbData); SetValueHelper(hDlg, IDC_AUTOSUGGEST_PROMPTPASSWORDS, &pszData, &cbData); SHSetValue(HKEY_CURRENT_USER, c_szRegKeySMIEM, c_szRegValFormSuggestPWAsk, REG_SZ, pszData, cbData); } } // fall through case IDCANCEL: { EndDialog(hDlg, LOWORD(wParam)); } break; } } return TRUE; case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_DESTROY: break; } return FALSE; } #ifdef WALLET // This intermediate dialog is only displayed for wallet 2.x users INT_PTR CALLBACK WalletDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: { EnableDlgItem(hDlg, IDC_PROGRAMS_WALLET_PAYBUTTON, IsWalletPaymentAvailable()); EnableDlgItem(hDlg, IDC_PROGRAMS_WALLET_ADDRBUTTON, IsWalletAddressAvailable()); } return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_PROGRAMS_WALLET_PAYBUTTON: DisplayWalletPaymentDialog(hDlg); break; case IDC_PROGRAMS_WALLET_ADDRBUTTON: DisplayWalletAddressDialog(hDlg); break; case IDOK: case IDCANCEL: { EndDialog(hDlg, LOWORD(wParam)); } break; } } return TRUE; case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_DESTROY: break; } return FALSE; } #endif