|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
schnlui.cxx
Abstract:
Contains immplimentation of generic Windows Dialog Manipulation Code. This code supports SCHANNEL (Secure Channel SSL/PCT) specific UI for Certifcates.
Contents: CertPickDialogProc
Author:
Arthur L Bierer (arthurbi) 27-Jun-1996
Revision History:
27-Jun-1996 arthurbi Created
--*/
#include <wininetp.h>
#include <ntsecapi.h>
#include "resource.h"
#include "ierrui.hxx"
#include "inethelp.h"
#include <softpub.h>
#include <htmlhelp.h>
#define USE_NT5_CRYPTOUI
#ifdef USE_NT5_CRYPTOUI
#include <cryptui.h>
HINSTANCE g_hCryptoUI = NULL; // handle for cryptui.dll
#endif
//
// private prototypes, and defines.
//
#define TYPICAL_MD5_HASH_SIZE 16
#define NUM_DN_UNITS 6
#define MAX_ITEM_LEN 1000
#define DN_COMMON_NAME 0
#define DN_COUNTRY 1
#define DN_ORG 2
#define DN_ORGUNIT 3
#define DN_LOCALE 4
#define DN_STATE 5
#define MAX_CERT_FIELDS 20
typedef struct _ATTR_MAP { DWORD dwAttr; DWORD dwStringID; } ATTR_MAP;
// Now for some common attribute maps
ATTR_MAP ProtocolAttrMap[] = { {SP_PROT_SSL2_CLIENT, IDS_PROTOCOL_SSL2}, {SP_PROT_SSL3_CLIENT, IDS_PROTOCOL_SSL3}, {SP_PROT_PCT1_CLIENT, IDS_PROTOCOL_PCT1}, {SP_PROT_TLS1_CLIENT, IDS_PROTOCOL_TLS1} };
ATTR_MAP AlgAttrMap[] = { {CALG_MD2, IDS_ALG_MD2}, {CALG_MD4, IDS_ALG_MD4}, {CALG_MD5, IDS_ALG_MD5}, {CALG_SHA, IDS_ALG_SHA}, {CALG_SHA1, IDS_ALG_SHA}, {CALG_MAC, IDS_ALG_MAC}, {CALG_HMAC, IDS_ALG_HMAC}, {CALG_RSA_SIGN, IDS_ALG_RSA_SIGN}, {CALG_DSS_SIGN, IDS_ALG_DSS_SIGN}, {CALG_RSA_KEYX, IDS_ALG_RSA_KEYX}, {CALG_DES, IDS_ALG_DES}, {CALG_3DES_112, IDS_ALG_3DES_112}, {CALG_3DES, IDS_ALG_3DES}, {CALG_RC2, IDS_ALG_RC2}, {CALG_RC4, IDS_ALG_RC4}, {CALG_RC5, IDS_ALG_RC5}, {CALG_SEAL, IDS_ALG_SEAL}, {CALG_DH_SF, IDS_ALG_DH_SF}, {CALG_DH_EPHEM, IDS_ALG_DH_EPHEM}, {CALG_KEA_KEYX, IDS_ALG_KEA_KEYX}, {CALG_SKIPJACK, IDS_ALG_SKIPJACK}, {CALG_TEK, IDS_ALG_TEK} };
typedef struct { LPWSTR lpszListBoxText; LPWSTR lpszEditBoxText; DWORD dwSpcCtlId; // special id for item to be placed in ctl.
} ShowCertMapping;
#define szHelpFile "iexplore.hlp"
//
// private function declariations
//
PRIVATE BOOL PlaceCertContextsInListBox( IN HWND hWndListBox, IN HWND hWndViewCertButton, IN HWND hWndExportButton, IN CERT_CONTEXT_ARRAY* pCertContexts );
PRIVATE BOOL PlaceCertificateDataIntoListBox( IN HWND hWndDlg, IN HWND hWndListBox, IN ShowCertMapping *pMapCertFields );
PRIVATE DWORD OnSelectionOfACertField( IN HWND hWndListBox, IN HWND hWndEditBox, IN ShowCertMapping *pMapCertFields );
PRIVATE BOOL CALLBACK ViewCertDlgProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam );
LPWSTR GetCertStatus(LPINTERNET_SECURITY_INFO pciCert); //
// public functions
//
#ifdef USE_NT5_CRYPTOUI
//+-------------------------------------------------------------------------
// Returns TRUE if cryptui.dll was found
//--------------------------------------------------------------------------
BOOL UseCryptoUI() { static long fTriedOnce = FALSE;
// Only try to load the dll once
if (!fTriedOnce) { //
// Note: if this gets called by multiple threads the worst that will
// happen is that load library will be called twice. Apparently,
// there is is no danger of the global getting mangled because
// writes are atomic.
//
g_hCryptoUI = LoadLibrary("cryptui.dll"); fTriedOnce = TRUE; }
return (g_hCryptoUI != NULL); }
//+-------------------------------------------------------------------------
// Delay load version of the function in cryptui.dll
//--------------------------------------------------------------------------
BOOL _CryptUIDlgViewCertificate( IN PCCRYPTUI_VIEWCERTIFICATE_STRUCT pCertViewInfo, OUT BOOL *pfPropertiesChanged // OPTIONAL
) { // Caller must call UseCryptoUI() first to load the dll!
INET_ASSERT(g_hCryptoUI); typedef BOOL (CALLBACK* CRYPTUIDLGVIEWCERTIFICATE)(PCCRYPTUI_VIEWCERTIFICATE_STRUCT, BOOL*);
static CRYPTUIDLGVIEWCERTIFICATE fnCryptUIDlgViewCertificate = NULL;
if (fnCryptUIDlgViewCertificate == NULL) { //
// Note: if this gets called by multiple threads the worst that will
// happen is that GetProcAddress will be called twice. Apparently,
// there is is no danger of the global getting mangled because
// writes are atomic.
//
fnCryptUIDlgViewCertificate = (CRYPTUIDLGVIEWCERTIFICATE)GetProcAddress(g_hCryptoUI, "CryptUIDlgViewCertificateA"); if (fnCryptUIDlgViewCertificate == NULL) { return FALSE; } }
// Call the real function
return fnCryptUIDlgViewCertificate(pCertViewInfo, pfPropertiesChanged); } #endif USE_NT5_CRYPTOUI
INTERNETAPI_(BOOL) InternetAlgIdToStringA( IN ALG_ID ai, IN LPSTR lpstr, IN OUT LPDWORD lpdwstrLength, IN DWORD dwReserved /* Must be 0 */ ) /*++
Routine Description:
Converts a algid to a user-displayable string.
Arguments:
ai - Algorithm identifiers ( defined in wincrypt.h)
lpstr - Buffer to copy string into.
lpdwstrLength - pass in num of characters, return no of characters copied if successful, else no of chars required (including null terminator)
dwReserved = Must be 0
Return Value: DWORD Win32 or WININET error code. --*/ { DEBUG_ENTER_API((DBG_API, Bool, "InternetAlgIdToStringA", "%#x, %q, %#x, %#x", ai, lpstr, lpdwstrLength, dwReserved ));
DWORD error = ERROR_SUCCESS;
if ((dwReserved!=0) || (lpdwstrLength == NULL)) { error = ERROR_INVALID_PARAMETER; goto quit; }
if (lpstr == NULL) *lpdwstrLength = 0;
int i; for (i=0; i < ARRAY_ELEMENTS(AlgAttrMap) ; i++ ) { if (ai == AlgAttrMap[i].dwAttr) break; }
if ( i == ARRAY_ELEMENTS(AlgAttrMap) ) { INET_ASSERT(FALSE); // Could be because our table is not up to date.
error = ERROR_INVALID_PARAMETER; goto quit; }
CHAR szTempBuffer[100];
int nRet; nRet = LoadStringA(GlobalDllHandle, AlgAttrMap[i].dwStringID, szTempBuffer, ARRAY_ELEMENTS(szTempBuffer) );
// If the return value is within one less than the arraysize, it implies the
// string could have been terminated by LoadString. This should not happen
// since we have allocated a large enough buffer. If it does we need to bump the
// size of the temporary array above.
INET_ASSERT(nRet < ARRAY_ELEMENTS(szTempBuffer) - 1);
if (*lpdwstrLength > (DWORD)nRet) { memcpy(lpstr, szTempBuffer, (nRet + 1)); *lpdwstrLength = nRet; error = ERROR_SUCCESS; } else { *lpdwstrLength = nRet + 1; error = ERROR_INSUFFICIENT_BUFFER; }
quit: if (ERROR_SUCCESS != error) { SetLastError(error); DEBUG_ERROR(API, error); } DEBUG_LEAVE_API(error==ERROR_SUCCESS); return (error == ERROR_SUCCESS); }
INTERNETAPI_(BOOL) InternetSecurityProtocolToStringA( IN DWORD dwProtocol, IN LPSTR lpstr, IN OUT LPDWORD lpdwstrLength, IN DWORD dwReserved /* Must be 0 */ ) /*++
Routine Description:
Converts a security protocol to a user-displayable string.
Arguments:
dwProtocol - Security protocol identifier ( defined in wincrypt.h)
lpstr - Buffer to copy string into.
lpdwstrLength - pass in num of characters, return no of characters copied if successful, else no of chars required (including null terminator)
dwReserved = Must be 0
Return Value: DWORD Win32 or WININET error code. --*/ { DEBUG_ENTER_API((DBG_API, Bool, "InternetSecurityProtocolToStringA", "%d, %q, %#x, %#x", dwProtocol, lpstr, lpdwstrLength, dwReserved ));
DWORD error = ERROR_SUCCESS;
if ((dwReserved!=0) || (lpdwstrLength == NULL)) { error = ERROR_INVALID_PARAMETER; goto quit; }
if (lpstr == NULL) *lpdwstrLength = 0;
int i; for (i=0; i < ARRAY_ELEMENTS(ProtocolAttrMap) ; i++ ) { if (dwProtocol == ProtocolAttrMap[i].dwAttr) break; }
if ( i == ARRAY_ELEMENTS(ProtocolAttrMap) ) { INET_ASSERT(FALSE); // Could be because our table is not up to date.
error = ERROR_INVALID_PARAMETER; goto quit; }
CHAR szTempBuffer[100];
int nRet; nRet = LoadStringA(GlobalDllHandle, ProtocolAttrMap[i].dwStringID, szTempBuffer, ARRAY_ELEMENTS(szTempBuffer) );
// If the return value is within one less than the arraysize, it implies the
// string could have been terminated by LoadString. This should not happen
// since we have allocated a large enough buffer. If it does we need to bump the
// size of the temporary array above.
INET_ASSERT(nRet < ARRAY_ELEMENTS(szTempBuffer) - 1);
if (*lpdwstrLength > (DWORD)nRet) { memcpy(lpstr, szTempBuffer, (nRet + 1)); *lpdwstrLength = nRet; error = ERROR_SUCCESS; } else { *lpdwstrLength = nRet + 1; error = ERROR_INSUFFICIENT_BUFFER; }
quit: if (ERROR_SUCCESS != error) { SetLastError(error); DEBUG_ERROR(API, error); } DEBUG_LEAVE_API(error==ERROR_SUCCESS); return (error == ERROR_SUCCESS); }
LPWSTR DupAnsiToUnicode( char *lpszAnsi, INT iLen ) { DWORD cbSize = (iLen > 0 ) ? iLen : (lstrlen(lpszAnsi) + 1); WCHAR *pwszUnicode = NULL; pwszUnicode = new WCHAR[cbSize]; if(pwszUnicode) { SHAnsiToUnicode(lpszAnsi, pwszUnicode, cbSize); } return pwszUnicode; }
DWORD ShowSecurityInfo( IN HWND hWndParent, IN LPINTERNET_SECURITY_INFO pSecurityInfo )
/*++
Routine Description:
Displays a dialog box that shows the information found inside of a certificate.
Arguments:
hWndParent - Parent Window Handle
pCertInfoEx - Certificate Information structure, containing the fields of info to show.
Return Value:
DWORD Win32 or WININET error code. --*/
{ #ifdef USE_NT5_CRYPTOUI
//
// For now, we use the new UI only if we can load the DLL. Otherwise we
// resort to the old UI. Eventually, we may nuke the old UI.
//
if (UseCryptoUI()) { CRYPTUI_VIEWCERTIFICATE_STRUCT cert;
if(pWTHelperProvDataFromStateData && g_fDoSpecialMagicForSGCCerts) { WINTRUST_DATA sWTD; WINTRUST_CERT_INFO sWTCI; HTTPSPolicyCallbackData polHttps; LPCSTR pszPurpose = szOID_PKIX_KP_SERVER_AUTH; DWORD status;
memset(&sWTD, 0x00, sizeof(WINTRUST_DATA)); sWTD.cbStruct = sizeof(WINTRUST_DATA); sWTD.dwUIChoice = WTD_UI_NONE; sWTD.pPolicyCallbackData = (LPVOID)&polHttps; sWTD.dwUnionChoice = WTD_CHOICE_CERT; sWTD.pCert = &sWTCI; sWTD.pwszURLReference = NULL; sWTD.dwStateAction = WTD_STATEACTION_VERIFY; memset(&sWTCI, 0x00, sizeof(WINTRUST_CERT_INFO)); sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO); sWTCI.psCertContext = (CERT_CONTEXT *)pSecurityInfo->pCertificate; sWTCI.chStores = 1; sWTCI.pahStores = (HCERTSTORE *)&pSecurityInfo->pCertificate->hCertStore;
memset(&polHttps, 0x00, sizeof(HTTPSPolicyCallbackData)); polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); polHttps.dwAuthType = AUTHTYPE_SERVER; polHttps.fdwChecks = INTERNET_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_WRONG_USAGE; polHttps.pwszServerName = NULL;
status = WinVerifySecureChannel(NULL, &sWTD);
ZeroMemory(&cert, sizeof(cert)); cert.dwSize = sizeof(cert); cert.hwndParent = hWndParent; cert.pCertContext = pSecurityInfo->pCertificate; cert.hWVTStateData = pWTHelperProvDataFromStateData(sWTD.hWVTStateData); cert.fpCryptProviderDataTrustedUsage = (status == ERROR_SUCCESS) ? TRUE : FALSE; cert.rgszPurposes = &pszPurpose; cert.cPurposes = 1;
status = _CryptUIDlgViewCertificate(&cert, NULL);
sWTD.dwStateAction = WTD_STATEACTION_CLOSE; WinVerifySecureChannel(NULL, &sWTD);
return status; } else { ZeroMemory(&cert, sizeof(cert)); cert.dwSize = sizeof(cert); cert.hwndParent = hWndParent; cert.pCertContext = pSecurityInfo->pCertificate; cert.cStores = 1; cert.rghStores = (HCERTSTORE *) & (cert.pCertContext->hCertStore);
return _CryptUIDlgViewCertificate(&cert, NULL); }
} #endif
#ifdef _WIN64
return ERROR_INTERNET_INTERNAL_ERROR; #else
LPTSTR szResult = NULL; PLOCAL_STRINGS plszStrings; ShowCertMapping MapCertFields[MAX_CERT_FIELDS];
WCHAR szTempBuffer[100];
INT i = 0, j=0; DWORD error; LPTSTR lpszSubject = NULL; LPWSTR lpwszTempSubject = NULL; LPTSTR lpszIssuer = NULL; LPWSTR lpwszTempIssuer = NULL;
WCHAR lpszProtocol[100]; LPWSTR lpwszCipher = NULL; LPWSTR lpwszHash = NULL; LPWSTR lpwszExch = NULL; LPTSTR szFrom = NULL; LPWSTR pwszTempFrom = NULL; LPTSTR szUntil = NULL; LPWSTR pwszTempUntil = NULL; LPWSTR pwszStatus = NULL; LPSTR lpszHashStr = NULL; LPWSTR pwszTempHashStr = NULL;
DWORD adwFormatParams[3];
PCERT_INFO pCertInfo = NULL; DWORD dwProtocolID = IDS_PROTOCOL_UNKNOWN; DWORD dwHashID = IDS_HASH_UNKNOWN; DWORD dwCipherID = IDS_CIPHER_UNKNOWN; DWORD dwExchID = IDS_EXCH_UNKNOWN; DWORD cbSize;
error = ERROR_SUCCESS;
if((pSecurityInfo == NULL) || (pSecurityInfo->pCertificate == NULL)) { return ERROR_INTERNET_INTERNAL_ERROR; }
pCertInfo = pSecurityInfo->pCertificate->pCertInfo;
if(pCertInfo == NULL) { return ERROR_INTERNET_INTERNAL_ERROR; }
//
// Get the Certificate Information.
//
plszStrings = FetchLocalStrings();
if ( plszStrings == NULL ) { error = ERROR_NOT_ENOUGH_MEMORY; goto quit; }
szFrom = FTtoString(&pCertInfo->NotBefore); szUntil = FTtoString(&pCertInfo->NotAfter);
//
// Put a comment string about the certificate if there is one availble.
//
//
// BUGBUG [arthurbi] This is broken. We never determnine the host name,
// so therefore we never show a Comment for bad CA certificates.
//
pwszStatus = GetCertStatus(pSecurityInfo);
if(pwszStatus) { MapCertFields[i].lpszListBoxText = plszStrings->szCertComment; MapCertFields[i].lpszEditBoxText = pwszStatus; MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_COMMENT;
i++;
}
if ( pCertInfo->Subject.cbData ) { cbSize = CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType, &pCertInfo->Subject, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG | CERT_NAME_STR_NO_PLUS_FLAG, NULL, 0);
lpszSubject = new TCHAR[cbSize];
if ( lpszSubject ) { CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType, &pCertInfo->Subject, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG | CERT_NAME_STR_NO_PLUS_FLAG , lpszSubject, cbSize); MapCertFields[i].lpszListBoxText = plszStrings->szCertSubject; lpwszTempSubject = DupAnsiToUnicode(lpszSubject, cbSize); MapCertFields[i].lpszEditBoxText = lpwszTempSubject; MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_SUBJECT;
i++; } }
if ( pCertInfo->Issuer.cbData ) { cbSize = CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType, &pCertInfo->Issuer, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG | CERT_NAME_STR_NO_PLUS_FLAG, NULL, 0);
lpszIssuer = new TCHAR[cbSize];
if ( lpszIssuer ) { CertNameToStr(pSecurityInfo->pCertificate->dwCertEncodingType, &pCertInfo->Issuer, CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG | CERT_NAME_STR_NO_PLUS_FLAG , lpszIssuer, cbSize); MapCertFields[i].lpszListBoxText = plszStrings->szCertIssuer; lpwszTempIssuer = DupAnsiToUnicode(lpszIssuer, cbSize); MapCertFields[i].lpszEditBoxText = lpwszTempIssuer; MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_ISSUER;
i++; } }
if ( szFrom ) { MapCertFields[i].lpszListBoxText = plszStrings->szCertEffectiveDate; pwszTempFrom = DupAnsiToUnicode(szFrom, 0); MapCertFields[i].lpszEditBoxText = pwszTempFrom; MapCertFields[i].dwSpcCtlId = 0; i++; }
if ( szUntil ) { MapCertFields[i].lpszListBoxText = plszStrings->szCertExpirationDate; pwszTempUntil = DupAnsiToUnicode(szUntil, 0); MapCertFields[i].lpszEditBoxText = pwszTempUntil;
MapCertFields[i].dwSpcCtlId = 0;//IDC_CERT_EXPIRES;
i++; }
//
// Get the fingerprint... aka MD5 Hash
//
{ CHAR lpMD5Hash[TYPICAL_MD5_HASH_SIZE]; DWORD dwMD5HashSize = TYPICAL_MD5_HASH_SIZE; BOOL fSuccess;
fSuccess = CertGetCertificateContextProperty( pSecurityInfo->pCertificate, CERT_MD5_HASH_PROP_ID, (LPVOID) lpMD5Hash, &dwMD5HashSize );
if ( fSuccess ) { CertHashToStr( lpMD5Hash, dwMD5HashSize, &lpszHashStr );
if ( lpszHashStr ) { MapCertFields[i].lpszListBoxText = plszStrings->szFingerprint; pwszTempHashStr = DupAnsiToUnicode(lpszHashStr, 0); MapCertFields[i].lpszEditBoxText = pwszTempHashStr;
MapCertFields[i].dwSpcCtlId = 0; i++; } } }
// Now fill in the connection attributes
if(pSecurityInfo->dwProtocol) {
for(j=0; j < sizeof(ProtocolAttrMap)/sizeof(ProtocolAttrMap[0]); j++) { if(ProtocolAttrMap[j].dwAttr == pSecurityInfo->dwProtocol) { dwProtocolID = ProtocolAttrMap[j].dwStringID; break; } } if(LoadStringWrapW(GlobalDllHandle, dwProtocolID, lpszProtocol, sizeof(lpszProtocol)/sizeof(lpszProtocol[0]))) {
MapCertFields[i].lpszEditBoxText = lpszProtocol; MapCertFields[i].lpszListBoxText = plszStrings->szCertProtocol; MapCertFields[i].dwSpcCtlId = 0; i++; } }
if(pSecurityInfo->aiCipher) { for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++) { if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiCipher) { dwCipherID = AlgAttrMap[j].dwStringID; break; } }
LoadStringWrapW(GlobalDllHandle, dwCipherID, szTempBuffer, sizeof(szTempBuffer)/sizeof(szTempBuffer[0])); adwFormatParams[0] = (DWORD)szTempBuffer; adwFormatParams[1] = (DWORD)pSecurityInfo->dwCipherStrength;
if (96 <= pSecurityInfo->dwCipherStrength) // Recommended Key strength
adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh; else if (64 <= pSecurityInfo->dwCipherStrength) // Passable key strength
adwFormatParams[2] = (DWORD)plszStrings->szStrengthMedium; else // Ick! Low key strength.
adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, plszStrings->szCiphMsg, 0, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpwszCipher, 0, (va_list *)adwFormatParams)) { MapCertFields[i].lpszEditBoxText = lpwszCipher; MapCertFields[i].lpszListBoxText = plszStrings->szHttpsEncryptAlg; MapCertFields[i].dwSpcCtlId = 0;
i++; } }
if(pSecurityInfo->aiHash) { for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++) { if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiHash) { dwHashID = AlgAttrMap[j].dwStringID; break; } } LoadStringWrapW(GlobalDllHandle, dwHashID, szTempBuffer, sizeof(szTempBuffer)/sizeof(szTempBuffer[0])); adwFormatParams[0] = (DWORD)szTempBuffer; adwFormatParams[1] = (DWORD)pSecurityInfo->dwHashStrength;
if (96 <= pSecurityInfo->dwHashStrength) // Recommended Key strength
adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh; else if (64 <= pSecurityInfo->dwHashStrength) // Passable key strength
adwFormatParams[2] = (DWORD)plszStrings->szStrengthMedium; else // Ick! Low key strength.
adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, plszStrings->szHashMsg, 0, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpwszHash, 0, (va_list *)adwFormatParams)) { MapCertFields[i].lpszEditBoxText = lpwszHash; MapCertFields[i].lpszListBoxText = plszStrings->szHttpsHashAlg; MapCertFields[i].dwSpcCtlId = 0; i++; } } if(pSecurityInfo->aiExch) { for(j=0; j < sizeof(AlgAttrMap)/sizeof(AlgAttrMap[0]); j++) { if(AlgAttrMap[j].dwAttr == pSecurityInfo->aiExch) { dwExchID = AlgAttrMap[j].dwStringID; break; } } LoadStringWrapW(GlobalDllHandle, dwExchID, szTempBuffer, sizeof(szTempBuffer)/sizeof(szTempBuffer[0])); adwFormatParams[0] = (DWORD)szTempBuffer; adwFormatParams[1] = (DWORD)pSecurityInfo->dwExchStrength;
if (1024 <= pSecurityInfo->dwExchStrength) // Recommended Key strength
adwFormatParams[2] = (DWORD)plszStrings->szStrengthHigh; else // Ick! Low key strength.
adwFormatParams[2] = (DWORD)plszStrings->szStrengthLow;
if(FormatMessageWrapW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY, plszStrings->szExchMsg, 0, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&lpwszExch, 0, (va_list *)adwFormatParams)) { MapCertFields[i].lpszEditBoxText = lpwszExch; MapCertFields[i].lpszListBoxText = plszStrings->szHttpsExchAlg; MapCertFields[i].dwSpcCtlId = 0; i++; } }
//
// Last Array Item is marked with 2 NULLs
//
MapCertFields[i].lpszListBoxText = NULL; MapCertFields[i].lpszEditBoxText = NULL; MapCertFields[i].dwSpcCtlId = 0;
INET_ASSERT(i < MAX_CERT_FIELDS);
//
// Now Launch the Dlg so we can show it.
//
ERRORINFODLGTYPE CertDlgInfo;
CertDlgInfo.dwDlgFlags = DLG_FLAGS_HAS_CERT_INFO; CertDlgInfo.dwDlgId = IDD_SHOW_CERT; CertDlgInfo.hInternetMapped = NULL; CertDlgInfo.lpVoid = (LPVOID) MapCertFields;
LaunchDlg( hWndParent, (LPVOID) &CertDlgInfo, IDD_VIEW_CERT, ViewCertDlgProc );
quit: if(lpszIssuer) { FREE_MEMORY(lpszIssuer); } if(lpwszTempIssuer) { FREE_MEMORY(lpwszTempIssuer); } if(lpszSubject) { FREE_MEMORY(lpszSubject); } if(lpwszTempSubject) { FREE_MEMORY(lpwszTempSubject); } if (szFrom) { FREE_MEMORY(szFrom); } if(pwszTempFrom) { FREE_MEMORY(pwszTempFrom); } if (szUntil) { FREE_MEMORY(szUntil); } if(pwszTempUntil) { FREE_MEMORY(pwszTempUntil); } if (lpwszCipher) { FREE_MEMORY(lpwszCipher); } if (lpwszHash) { FREE_MEMORY(lpwszHash); } if (lpwszExch) { FREE_MEMORY(lpwszExch); }
if (lpszHashStr) { delete lpszHashStr; } if(pwszTempHashStr) { FREE_MEMORY(pwszTempHashStr); }
return error; #endif
}
STDAPI_(DWORD) ShowCertificate( IN HWND hWndParent, IN LPVOID pCertInfoEx )
/*++
Routine Description:
Displays a dialog box that shows the information found inside of a certificate.
Arguments:
hWndParent - Parent Window Handle
pCertInfoEx - Certificate Information structure, containing the fields of info to show.
Return Value:
DWORD Win32 or WININET error code. --*/
{ //DWORD error = ShowSecurityInfo(
// hWndParent,
// (LPINTERNET_SECURITY_INFO) pCertInfoEx // BAD..
// );
//return error;
return ERROR_INTERNET_INTERNAL_ERROR; }
BOOL CALLBACK ViewCertDlgProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
/*++
Routine Description:
Shows a Certificate, and relevent security information to the user.
Arguments:
hwnd - standard dialog params
msg - "
wparam - "
lparam - "
Return Value:
BOOL TRUE - we handled message
FALSE - Windows should handle message
--*/
{ PERRORINFODLGTYPE pDlgInfo;
const static DWORD mapIDCsToIDHs[] = { IDC_CERTPICKLIST ,IDH_LIST_CERT, ID_SHOW_CERTIFICATE ,IDH_VIEW_CERT, IDC_DELETE_CERT ,IDH_DEL_CERT, 0,0 };
switch (msg) {
case WM_INITDIALOG:
INET_ASSERT(lparam);
pDlgInfo = (PERRORINFODLGTYPE)lparam;
(void)SetWindowLongPtr(hwnd, DWLP_USER, lparam);
INET_ASSERT(pDlgInfo->dwDlgFlags & DLG_FLAGS_HAS_CERT_INFO ); INET_ASSERT(pDlgInfo->lpVoid);
PlaceCertificateDataIntoListBox( hwnd, GetDlgItem(hwnd,IDC_FIELDLIST), (ShowCertMapping *) pDlgInfo->lpVoid );
OnSelectionOfACertField( GetDlgItem(hwnd,IDC_FIELDLIST), GetDlgItem(hwnd,IDC_DETAILSLIST), (ShowCertMapping *) pDlgInfo->lpVoid );
return TRUE;
case WM_HELP: // F1
WinHelp( (HWND)((LPHELPINFO)lparam)->hItemHandle, szHelpFile, HELP_WM_HELP, (ULONG_PTR)(LPSTR)mapIDCsToIDHs ); break;
case WM_CONTEXTMENU: // right mouse click
WinHelp( (HWND) wparam, szHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)(LPSTR)mapIDCsToIDHs ); break;
case WM_COMMAND: {
WORD wID = LOWORD(wparam); WORD wNotificationCode = HIWORD(wparam); HWND hWndCtrl = (HWND) lparam;
pDlgInfo = (PERRORINFODLGTYPE) GetWindowLongPtr(hwnd,DWLP_USER);
switch (wID) { case ID_TELL_ME_ABOUT_SECURITY:
//
// Launches help for this button.
//
WinHelp( hwnd, szHelpFile, HELP_CONTEXT, (ULONG_PTR)HELP_TOPIC_SECURITY ); break;
case IDC_FIELDLIST:
//
// If the user changes the selection of the listbox
// move the edit control field data to the correct
// entry.
//
if ( wNotificationCode == LBN_SELCHANGE ) { OnSelectionOfACertField( hWndCtrl, GetDlgItem(hwnd,IDC_DETAILSLIST), (ShowCertMapping *) pDlgInfo->lpVoid ); }
break;
case IDOK: case IDYES:
INET_ASSERT(pDlgInfo); INET_ASSERT(pDlgInfo->dwDlgId != 0);
EndDialog(hwnd, TRUE); break;
case IDCANCEL: case IDNO:
EndDialog(hwnd, FALSE); break; }
return TRUE; } }
return FALSE; }
DWORD ShowClientAuthCerts( IN HWND hWndParent )
/*++
Routine Description:
Shows the Client Authentication Certificates found in the system.
Arguments:
hWndParent - Parent Window Handle
Return Value:
DWORD Win32 or WININET error code.
--*/
{ // With the NT5 crypto UI we don't need to display client-auth certs anymore.
// I left this in code in the source file in case we switch back to the old
// crypto dlls for some reason. Once we decide to move on to the new crypto dlls
// this code can be removed. - sgs
#ifndef USE_NT5_CRYPTOUI
DWORD error; ERRORINFODLGTYPE ErrorInfoDlgInfo;
ErrorInfoDlgInfo.hInternetMapped = NULL; ErrorInfoDlgInfo.dwDlgId = IDD_CERTVIEWER; ErrorInfoDlgInfo.lpVoid = NULL; ErrorInfoDlgInfo.dwDlgFlags = 0;
CliAuthAquireCertChains( NULL, NULL, (CERT_CHAIN_ARRAY **) &ErrorInfoDlgInfo.lpVoid );
//
// Don't Care about error code, from function.
//
error = LaunchDlg( hWndParent, (LPVOID) &ErrorInfoDlgInfo, ErrorInfoDlgInfo.dwDlgId, CertPickDialogProc );
if ( ErrorInfoDlgInfo.lpVoid ) delete ErrorInfoDlgInfo.lpVoid;
return error; #else
INET_ASSERT(FALSE); return ERROR_CALL_NOT_IMPLEMENTED; #endif
}
DWORD ParseX509EncodedCertificateForListBoxEntry( IN LPBYTE lpCert, IN DWORD cbCert, OUT LPSTR lpszListBoxEntry, IN LPDWORD lpdwListBoxEntry ) /*++
Routine Description:
Parses an X509 certificate, into a single text entry that can be displayed on a line in a listbox.
Arguments:
lpCert - Certificte bytes to parse
cbCert - Size of certificate to parse
lpszListBoxEntry - Formated text to use in List Box.
lpdwListBoxEntry - IN: size of lpszListBoxEntry, OUT: actual size of string.
Return Value:
DWORD Win32 or WININET error code.
--*/
{ BOOL fSuccess; DWORD error = ERROR_SUCCESS; PCCERT_CONTEXT pCert; PCERT_NAME_INFO pName = NULL; PCERT_RDN pIdentRDN; PCERT_RDN_ATTR pIdentifier; DWORD cbIdentifier; DWORD cbName, cbName2;
INET_ASSERT(lpdwListBoxEntry);
if (lpszListBoxEntry == NULL) *lpdwListBoxEntry = 0;
//
// 30-Aug-1997 pberkman:
// we need to do this to be backwards compatible with this function.
// however, becuase the create context function does not get us properties
// when we are creating it from a already existing context, we need the
// ability to just pass in the pre-existing context. To do this, just
// pass "-1" in for the cbCert and we'll do the "right thing".
//
if (cbCert == (-1)) { pCert = (PCCERT_CONTEXT)lpCert; } else { pCert = CertCreateCertificateContext(X509_ASN_ENCODING, lpCert, cbCert); }
//
// 30-Aug-1997 pberkman:
// look at the "Friendly Name" property first.
//
cbName = 0; CertGetCertificateContextProperty(pCert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cbName);
if (cbName > 0) { WCHAR *pbFName;
if (pbFName = (WCHAR *)new BYTE[cbName]) { if (CertGetCertificateContextProperty(pCert, CERT_FRIENDLY_NAME_PROP_ID, pbFName, &cbName)) { cbName2 = WideCharToMultiByte(0, 0, (WCHAR *)pbFName, wcslen((WCHAR *)pbFName) + 1, lpszListBoxEntry, *lpdwListBoxEntry, NULL, NULL);
if (cbName2 > *lpdwListBoxEntry) { error = ERROR_INSUFFICIENT_BUFFER; *lpdwListBoxEntry = cbName2; }
delete pbFName;
if ((pCert) && (cbCert != (-1))) { CertFreeCertificateContext(pCert); }
return(error); }
delete pbFName; } }
if(CryptDecodeObject(pCert->dwCertEncodingType, X509_NAME, pCert->pCertInfo->Subject.pbData, pCert->pCertInfo->Subject.cbData, 0, NULL, &cbName)) { pName = (PCERT_NAME_INFO)new BYTE[cbName]; if(pName == NULL) { error = ERROR_NOT_ENOUGH_MEMORY; } else if(!CryptDecodeObject(pCert->dwCertEncodingType, X509_NAME, pCert->pCertInfo->Subject.pbData, pCert->pCertInfo->Subject.cbData, 0, pName, &cbName)) { delete pName; pName = NULL; error = GetLastError();
} } else { error = GetLastError(); }
if((NULL != pName) && (pName->cRDN > 0)) { pIdentifier = CertFindRDNAttr(szOID_COMMON_NAME, pName);
if(pIdentifier == NULL) { pIdentifier = CertFindRDNAttr(szOID_ORGANIZATIONAL_UNIT_NAME, pName); if(pIdentifier == NULL) { pIdentifier = CertFindRDNAttr(szOID_ORGANIZATION_NAME, pName); if(pIdentifier == NULL) { pIdentRDN = &pName->rgRDN[pName->cRDN-1]; pIdentifier = &pIdentRDN->rgRDNAttr[pIdentRDN->cRDNAttr-1]; } } }
if(pIdentifier != NULL) { cbIdentifier = CertRDNValueToStr(pIdentifier->dwValueType, &pIdentifier->Value, NULL, 0);
if(cbIdentifier == 0) { error = GetLastError(); } else if ( (lpszListBoxEntry != NULL) && (cbIdentifier > (*lpdwListBoxEntry)) ) { error = ERROR_INSUFFICIENT_BUFFER; *lpdwListBoxEntry = cbIdentifier; } else {
*lpdwListBoxEntry = CertRDNValueToStr(pIdentifier->dwValueType, &pIdentifier->Value, lpszListBoxEntry, cbIdentifier); error = ERROR_SUCCESS; } } else { *lpdwListBoxEntry = 0;
error = ERROR_INTERNET_INVALID_OPERATION; }
delete pName; }
//
// 30-Aug-1997 pberkman:
// we have to free this thing!
//
if ((pCert) && (cbCert != (-1))) { CertFreeCertificateContext(pCert); }
return error; }
DWORD ShowX509EncodedCertificate( IN HWND hWndParent, IN LPBYTE lpCert, IN DWORD cbCert ) /*++
Routine Description:
Shows an encoded set of bytes which represent a certificate, in a dialog box.
Arguments:
hWndParent
lpCert
cbCert
Return Value:
DWORD ERROR_SUCCESS
--*/
{
DWORD error;
#ifdef USE_NT5_CRYPTOUI
//
// For now, we use the new UI only if we can load the DLL. Otherwise we
// resort to the old UI. Eventually, we may nuke the old UI.
//
if (UseCryptoUI()) { CRYPTUI_VIEWCERTIFICATE_STRUCT cert;
ZeroMemory(&cert, sizeof(cert)); cert.dwSize = sizeof(cert); cert.hwndParent = hWndParent; cert.pCertContext = (PCCERT_CONTEXT)lpCert; cert.cStores = 1; cert.rghStores = (HCERTSTORE *) & (cert.pCertContext->hCertStore);
return _CryptUIDlgViewCertificate(&cert, NULL); } else #endif
{ X509Certificate *pCertData = NULL; INTERNET_SECURITY_INFO ciInfo;
ZeroMemory(&ciInfo, sizeof(ciInfo));
ciInfo.dwSize = sizeof(ciInfo);
ciInfo.pCertificate = CertCreateCertificateContext(X509_ASN_ENCODING, lpCert, cbCert); error = ShowSecurityInfo( hWndParent, &ciInfo ); }
return error; }
BOOL _GetSelectedCertContext(HWND hwnd, PERRORINFODLGTYPE pDlgInfo, PCCERT_CONTEXT *ppCertContext) { CERT_CONTEXT_ARRAY* pCertContextArray;
if (ppCertContext == NULL) return FALSE;
*ppCertContext = NULL;
pCertContextArray = ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
PCERT_CHAIN pcCertChain; LRESULT index;
INET_ASSERT(pCertContextArray); if (!pCertContextArray) return FALSE;
//
// Retrieve the Cert from List box
//
index = SendDlgItemMessage(hwnd, IDC_CERTPICKLIST, LB_GETCURSEL, 0, 0);
if ( index == LB_ERR ) index = 0;
if ( index >= (INT) pCertContextArray->GetArraySize()) { INET_ASSERT(FALSE); return FALSE; }
*ppCertContext = pCertContextArray->GetCertContext((INT)index);
if (!*ppCertContext) return FALSE; else return TRUE; }
INT_PTR CALLBACK CertPickDialogProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
/*++
Routine Description:
Supports Ok/Cancel decisions for the Client Authentication UI. Allows the User to select a specific Certificate that he wishes to use for Client Auth.
Arguments:
hwnd - standard dialog params
msg - "
wparam - "
lparam - "
Return Value:
BOOL TRUE - we handled message
FALSE - Windows should handle message
--*/
{ PERRORINFODLGTYPE pDlgInfo; CERT_CONTEXT_ARRAY* pCertContextArray; LRESULT index;
const static DWORD mapIDCsToIDHs[] = { IDC_CERTPICKLIST, IDH_CLIENT_AUTHENTICATION_LIST, ID_SHOW_CERTIFICATE, IDH_CLIENT_AUTHENTICATION_CERT_PROPS, IDCLOSE, IDH_ORG_FAVORITES_CLOSE, IDC_BUTTON_IMPORT, IDH_CLIENTAUTH_IMPORT, IDC_BUTTON_EXPORT, IDH_CLIENTAUTH_EXPORT, 0,0 };
switch (msg) {
case WM_INITDIALOG:
{ INET_ASSERT(lparam);
pDlgInfo = (PERRORINFODLGTYPE)lparam;
(void)SetWindowLongPtr(hwnd, DWLP_USER, lparam);
// We used to have other dialogs use the same dialog proc, but this
// shouldn't happen with the removal of the personal certs dialog.
INET_ASSERT(pDlgInfo->dwDlgId == IDD_CERTPICKER); pCertContextArray = ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
PlaceCertContextsInListBox( GetDlgItem(hwnd, IDC_CERTPICKLIST), GetDlgItem(hwnd, ID_SHOW_CERTIFICATE), GetDlgItem(hwnd, IDC_BUTTON_EXPORT), pCertContextArray );
return TRUE;
}
case WM_HELP: // F1
WinHelp( (HWND)((LPHELPINFO)lparam)->hItemHandle, szHelpFile, HELP_WM_HELP, (ULONG_PTR)(LPSTR)mapIDCsToIDHs ); break;
case WM_CONTEXTMENU: // right mouse click
WinHelp( (HWND) wparam, szHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)(LPSTR)mapIDCsToIDHs ); break;
case WM_COMMAND: { WORD wID = LOWORD(wparam); WORD wNotificationCode = HIWORD(wparam); HWND hWndCtrl = (HWND) lparam;
pDlgInfo = (PERRORINFODLGTYPE) GetWindowLongPtr(hwnd,DWLP_USER);
switch (wID) { case ID_TELL_ME_ABOUT_SECURITY:
//
// Launches help for this button.
//
WinHelp( hwnd, szHelpFile, HELP_CONTEXT, (ULONG_PTR)HELP_TOPIC_SECURITY ); break;
case ID_SHOW_CERTIFICATE: { //
// If this dialog supports this behavior, then launch
// a show certficate dlg.
//
PCCERT_CONTEXT pCertContext;
if ( wNotificationCode == BN_CLICKED && _GetSelectedCertContext(hwnd, pDlgInfo, &pCertContext )) { ShowX509EncodedCertificate( hwnd, (LPBYTE)pCertContext, sizeof(pCertContext) ); }
break; }
case ID_CERT_MORE_INFO: HtmlHelp(hwnd, TEXT("iexplore.chm > iedefault"), HH_DISPLAY_TOPIC, (DWORD_PTR)TEXT("cert_ovr.htm")); break;
case IDCANCEL:
index = -1; goto lskip_getcursel;
case IDOK:
//
// Get the selected Cert.
//
index = SendDlgItemMessage(hwnd, IDC_CERTPICKLIST, LB_GETCURSEL, 0, 0);
if ( index == LB_ERR ) index = -1;
lskip_getcursel:
INET_ASSERT(pDlgInfo); INET_ASSERT(pDlgInfo->dwDlgId != 0);
//
// Select the Client Auth Cert to use,
// but only if we've got the cert picker dialog.
//
pCertContextArray = ((HTTP_REQUEST_HANDLE_OBJECT *)pDlgInfo->hInternetMapped)->GetCertContextArray();
if (pCertContextArray) { pCertContextArray->SelectCertContext((INT)index); }
EndDialog(hwnd, TRUE); break;
case IDCLOSE:
//
// We're done, so return FALSE.
//
EndDialog(hwnd, FALSE); break;
}
return TRUE; } }
return FALSE; }
//
// private functions
//
PRIVATE BOOL PlaceCertContextsInListBox( IN HWND hWndListBox, IN HWND hWndViewCertButton, IN HWND hWndExportButton, IN CERT_CONTEXT_ARRAY* pCertContextArray )
/*++
Routine Description:
Takes an array of CertContext's and puts them into a listbox, by cracking their contents one at a time.
Arguments:
hWndListBox - Window Handle to ListBox to add items to.
pCertContext's - Pointer to array of cert chains.
hWndViewCertButton - Window handle to ViewCert Button, NULL if no button is around
Return Value:
BOOL TRUE - success.
FALSE - failure.
--*/
{ DWORD i = 0;
if ( !pCertContextArray) { goto quit; }
SendMessage(hWndListBox, LB_RESETCONTENT, 0, 0 );
for ( i = 0; i < pCertContextArray->GetArraySize(); i++ ) { PCCERT_CONTEXT pCert; // PCERT_NAME_INFO pName = NULL;
// PCERT_RDN_ATTR pCommonName;
DWORD cbName; DWORD dwRet;
pCert = pCertContextArray->GetCertContext(i);
INET_ASSERT(pCert);
LPSTR lpszSubject;
cbName = 0; ParseX509EncodedCertificateForListBoxEntry(pCert->pbCertEncoded, pCert->cbCertEncoded, NULL, &cbName); if (cbName > 0) { if (lpszSubject = new TCHAR[cbName]) { if (ParseX509EncodedCertificateForListBoxEntry(pCert->pbCertEncoded, pCert->cbCertEncoded, lpszSubject, &cbName) == ERROR_SUCCESS) { SendMessage(hWndListBox, LB_INSERTSTRING, (WPARAM)-1, (LPARAM) lpszSubject); }
FREE_MEMORY(lpszSubject); } } }
quit:
// Select the first item in the list box
// TODO: move selection to current default item.
SendMessage(hWndListBox, LB_SETCURSEL, 0, 0 );
// If nothing was added, disable the windows, otherwise enable them
EnableWindow(hWndListBox, (i != 0)); if ( hWndViewCertButton ) EnableWindow(hWndViewCertButton, (i != 0)); if ( hWndExportButton ) EnableWindow(hWndExportButton, (i != 0));
return TRUE; }
PRIVATE BOOL PlaceCertificateDataIntoListBox( IN HWND hWndDlg, IN HWND hWndListBox, IN ShowCertMapping *pMapCertFields ) {
DWORD i;
INET_ASSERT(pMapCertFields); INET_ASSERT(IsWindow(hWndListBox));
for ( i = 0; pMapCertFields[i].lpszListBoxText != NULL; i++ ) { if ( pMapCertFields[i].dwSpcCtlId != 0 ) { SetDlgItemTextWrapW(hWndDlg,pMapCertFields[i].dwSpcCtlId, pMapCertFields[i].lpszEditBoxText );
SetWindowLong(GetDlgItem(hWndDlg,pMapCertFields[i].dwSpcCtlId), GWL_STYLE, ES_READONLY | GetWindowLong(GetDlgItem(hWndDlg,pMapCertFields[i].dwSpcCtlId), GWL_STYLE));
}
SendMessage(hWndListBox, LB_ADDSTRING, 0, (LPARAM)pMapCertFields[i].lpszListBoxText); }
INET_ASSERT(i>0);
SendMessage(hWndListBox, LB_SETCURSEL, 0, 0 );
return TRUE; }
PRIVATE DWORD OnSelectionOfACertField( IN HWND hWndListBox, IN HWND hWndEditBox, IN ShowCertMapping *pMapCertFields ) { LRESULT index;
index = SendMessage(hWndListBox, LB_GETCURSEL, 0, 0);
if (index == LB_ERR ) index = 0;
if ( pMapCertFields[index].lpszListBoxText != NULL ) { SetWindowTextWrapW(hWndEditBox, pMapCertFields[index].lpszEditBoxText );
SetWindowLong(hWndEditBox, GWL_STYLE, ES_READONLY | GetWindowLong(hWndEditBox, GWL_STYLE)); }
return ERROR_SUCCESS; }
#ifndef CERT_E_WRONG_USAGE
# define CERT_E_WRONG_USAGE _HRESULT_TYPEDEF_(0x800B0110L)
#endif
#ifndef SECURITY_FLAG_IGNORE_WRONG_USAGE
# define SECURITY_FLAG_IGNORE_WRONG_USAGE 0x00010000
#endif
/* get a string representing the status of a certificate */ LPWSTR GetCertStatus(LPINTERNET_SECURITY_INFO pciCert) {
// We've done our handshake, now update the security info
DWORD dwCertFlags; PLOCAL_STRINGS plszStrings; GUID gHTTPS = HTTPSPROV_ACTION; WINTRUST_DATA sWTD; WINTRUST_CERT_INFO sWTCI; HTTPSPolicyCallbackData polHttps; DWORD cbServerName; DWORD error;
plszStrings = FetchLocalStrings(); if(plszStrings == NULL) { return NULL; }
if((pciCert == NULL) || (pciCert->pCertificate == NULL)) { return NULL; }
//
// initialize the structures for forward/backward support of wintrust.dll!!!
//
memset(&sWTD, 0x00, sizeof(WINTRUST_DATA)); sWTD.cbStruct = sizeof(WINTRUST_DATA); sWTD.dwUIChoice = WTD_UI_NONE; sWTD.pPolicyCallbackData = (LPVOID)&polHttps; sWTD.dwUnionChoice = WTD_CHOICE_CERT; sWTD.pCert = &sWTCI; sWTD.pwszURLReference = NULL;
memset(&sWTCI, 0x00, sizeof(WINTRUST_CERT_INFO)); sWTCI.cbStruct = sizeof(WINTRUST_CERT_INFO); sWTCI.psCertContext = (CERT_CONTEXT *)pciCert->pCertificate; sWTCI.chStores = 1; sWTCI.pahStores = (HCERTSTORE *)&pciCert->pCertificate->hCertStore;
memset(&polHttps, 0x00, sizeof(HTTPSPolicyCallbackData)); polHttps.cbStruct = sizeof(HTTPSPolicyCallbackData); polHttps.dwAuthType = AUTHTYPE_SERVER; polHttps.fdwChecks = INTERNET_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_WRONG_USAGE;
polHttps.pwszServerName = NULL;
sWTCI.pcwszDisplayName = NULL;
error = LoadWinTrust();
if(ERROR_SUCCESS == error) {
error = WinVerifySecureChannel(NULL, &sWTD); }
// If we are unable to verify revocation, then ignore.
if(error == CERT_E_REVOCATION_FAILURE) { error = ERROR_SUCCESS; }
switch(error) { case CERT_E_EXPIRED: case CERT_E_VALIDITYPERIODNESTING: return plszStrings->szCommentExpires;
case CERT_E_UNTRUSTEDROOT: return plszStrings->szCommentBadCA;
case CERT_E_CN_NO_MATCH: return plszStrings->szCommentBadCN;
case CRYPT_E_REVOKED: return plszStrings->szCommentRevoked;
case CERT_E_WRONG_USAGE: return plszStrings->szCertUsage;
case CERT_E_ROLE: case CERT_E_PATHLENCONST: case CERT_E_CRITICAL: case CERT_E_PURPOSE: case CERT_E_ISSUERCHAINING: case CERT_E_MALFORMED: case CERT_E_CHAINING: return plszStrings->szCommentNotValid;
case ERROR_SUCCESS: return NULL;
default: return plszStrings->szCommentNotValid; }
}
|