|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: cps.cpp
//
//--------------------------------------------------------------------------
//
// File: select.cpp
//
// Description: This file contains the implmentation code for the
// "Certificate Select" dialog.
//
#pragma warning (disable: 4201) // nameless struct/union
#pragma warning (disable: 4514) // remove inline functions
#pragma warning (disable: 4127) // conditional expression is constant
#include "global.hxx"
#include <dbgdef.h>
extern HINSTANCE HinstDll; extern HMODULE HmodRichEdit;
typedef struct _CPS_STATE_STRUCT { LPWSTR pwszURL; LPWSTR pwszDisplayText; DWORD dwChainError; BOOL fNoCOM; } CPS_STATE_STRUCT, *PCPS_STATE_STRUCT;
INT_PTR CALLBACK CPSDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
BOOL f; CPS_STATE_STRUCT *pcpsStateStruct;
switch (msg) { case WM_INITDIALOG:
pcpsStateStruct = (CPS_STATE_STRUCT *) lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR) pcpsStateStruct);
// set the text for the CPS
CryptUISetRicheditTextW(hwndDlg, IDC_CPS_TEXT, pcpsStateStruct->pwszDisplayText);
// if there is no URL then hide the more info button,
//
// DSIE: Bug 364742, also hide if the URL is not safe to be execute.
if (!pcpsStateStruct->pwszURL || !IsOKToFormatAsLinkW(pcpsStateStruct->pwszURL, pcpsStateStruct->dwChainError)) { EnableWindow(GetDlgItem(hwndDlg, ID_MORE_INFO), FALSE); } break;
case WM_NOTIFY: //if (((NMHDR FAR *) lParam)->code == EN_LINK)
break;
case WM_COMMAND: switch (LOWORD(wParam)) { case ID_MORE_INFO:
if (HIWORD(wParam) == BN_CLICKED) { DWORD numBytes = 0; LPSTR pszURL = NULL;
pcpsStateStruct = (CPS_STATE_STRUCT *) GetWindowLongPtr(hwndDlg, DWLP_USER);
pszURL = CertUIMkMBStr(pcpsStateStruct->pwszURL);
if (pszURL == NULL) { return TRUE; }
CryptuiGoLink(hwndDlg, pszURL, pcpsStateStruct->fNoCOM); free(pszURL); return TRUE; } break;
case IDOK: case IDCANCEL: case IDOK_CPS: case IDCANCEL_CPS: EndDialog(hwndDlg, IDOK); return TRUE; } break;
//
// Use the default handler -- we don't do anything for it
//
default: return FALSE; }
return FALSE; }
DWORD GetCPSInfo(PCCERT_CONTEXT pCertContext, LPWSTR * ppwszUrlString, LPWSTR * ppwszDisplayText) { DWORD dwRetCode = 0; PCERT_EXTENSION pExt = NULL; DWORD i,j,k; DWORD cbCertPolicyInfo = 0; CERT_POLICIES_INFO * pCertPolicyInfo = NULL; CERT_NAME_VALUE * pCertName = NULL; DWORD cbCertName = 0; CERT_POLICY_QUALIFIER_USER_NOTICE * pUserNotice = NULL; DWORD cbUserNotice = 0; PSPC_SP_AGENCY_INFO pInfo = NULL; DWORD cbInfo = 0; CERT_POLICY95_QUALIFIER1 * pCertPolicy95Qualifier = NULL; DWORD cbCertPolicy95Qualifier = 0;
//
// Check parameters and intialize return values.
//
if (NULL == pCertContext || NULL == ppwszUrlString || NULL == ppwszDisplayText) { return ERROR_INVALID_PARAMETER; }
*ppwszUrlString = *ppwszDisplayText = NULL;
//
// first look for the PKIX policy extension and see if it has an URL
//
if ((pExt = CertFindExtension(szOID_CERT_POLICIES, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension))) { //
// decode the policy extension
//
CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbCertPolicyInfo);
if (!(pCertPolicyInfo = (CERT_POLICIES_INFO *) malloc(cbCertPolicyInfo))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES, pExt->Value.pbData, pExt->Value.cbData, 0, pCertPolicyInfo, &cbCertPolicyInfo))) { dwRetCode = GetLastError(); goto ErrorExit; }
//
// look for display text and/or and URL in the extension
//
for (i = 0; i < pCertPolicyInfo->cPolicyInfo ; i++) { for (j = 0; j < pCertPolicyInfo->rgPolicyInfo[i].cPolicyQualifier; j++) { // check to see what type of qualifier it is
if (0 == strcmp(szOID_PKIX_POLICY_QUALIFIER_CPS, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId)) { // decode as an anystring
CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, NULL, &cbCertName);
if (!(pCertName = (CERT_NAME_VALUE *) malloc(cbCertName))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_ANY_STRING, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, pCertName, &cbCertName))) { dwRetCode = GetLastError(); goto ErrorExit; }
if (pCertName->Value.cbData && NULL == *ppwszUrlString) { if (!(*ppwszUrlString = (LPWSTR) malloc(pCertName->Value.cbData + sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszUrlString, (LPWSTR) pCertName->Value.pbData); }
free(pCertName); pCertName = NULL; } else if (0 == strcmp(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId)) { // decode as user notice
CryptDecodeObject(X509_ASN_ENCODING, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, NULL, &cbUserNotice);
if (!(pUserNotice = (CERT_POLICY_QUALIFIER_USER_NOTICE *) malloc(cbUserNotice))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, pUserNotice, &cbUserNotice))) { dwRetCode = GetLastError(); goto ErrorExit; }
// NOTE: pUserNotice->pszDisplayText may be NULL
if (pUserNotice->pszDisplayText && NULL == *ppwszDisplayText) { if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pUserNotice->pszDisplayText) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszDisplayText, pUserNotice->pszDisplayText); }
free(pUserNotice); pUserNotice = NULL; } } } } //
// next look for display information in the SPC Agency Info
//
else if ((pExt = CertFindExtension(SPC_SP_AGENCY_INFO_OBJID, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension))) { CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbInfo);
if (!(pInfo = (PSPC_SP_AGENCY_INFO) malloc(cbInfo))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, SPC_SP_AGENCY_INFO_STRUCT, pExt->Value.pbData, pExt->Value.cbData, 0, pInfo, &cbInfo))) { dwRetCode = GetLastError(); goto ErrorExit; }
if (!(pInfo->pPolicyInformation)) { dwRetCode = CRYPT_E_NOT_FOUND; goto ErrorExit; }
if (pInfo->pwszPolicyDisplayText) { if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pInfo->pwszPolicyDisplayText) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszDisplayText, pInfo->pwszPolicyDisplayText); }
switch (pInfo->pPolicyInformation->dwLinkChoice) { case SPC_URL_LINK_CHOICE: { if (pInfo->pPolicyInformation->pwszUrl) { if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pInfo->pPolicyInformation->pwszUrl) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszUrlString, pInfo->pPolicyInformation->pwszUrl); }
break; }
case SPC_FILE_LINK_CHOICE: { if (pInfo->pPolicyInformation->pwszFile) { if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pInfo->pPolicyInformation->pwszFile) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszUrlString, pInfo->pPolicyInformation->pwszFile); }
break; } } }
//
// finally, look for info in the 2.5.29.3 extension
//
else if ((pExt = CertFindExtension(szOID_CERT_POLICIES_95, pCertContext->pCertInfo->cExtension, pCertContext->pCertInfo->rgExtension))) { CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES_95, pExt->Value.pbData, pExt->Value.cbData, 0, NULL, &cbCertPolicyInfo);
if (!(pCertPolicyInfo = (CERT_POLICIES_INFO *) malloc(cbCertPolicyInfo))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES_95, pExt->Value.pbData, pExt->Value.cbData, 0, pCertPolicyInfo, &cbCertPolicyInfo))) { dwRetCode = GetLastError(); goto ErrorExit; }
// now decode the qualifiers
for (i = 0; i < pCertPolicyInfo->cPolicyInfo; i++) { for (j = 0; j < pCertPolicyInfo->rgPolicyInfo[i].cPolicyQualifier; j++) { if (0 == strcmp(szOID_CERT_POLICIES_95_QUALIFIER1, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].pszPolicyQualifierId)) { CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES_95_QUALIFIER1, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, NULL, &cbCertPolicy95Qualifier);
if (!(pCertPolicy95Qualifier = (CERT_POLICY95_QUALIFIER1 *) malloc(cbCertPolicy95Qualifier))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
if (!(CryptDecodeObject(X509_ASN_ENCODING, szOID_CERT_POLICIES_95_QUALIFIER1, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.pbData, pCertPolicyInfo->rgPolicyInfo[i].rgPolicyQualifier[j].Qualifier.cbData, 0, pCertPolicy95Qualifier, &cbCertPolicy95Qualifier))) { dwRetCode = GetLastError(); goto ErrorExit; }
// check to see what is available
if ((NULL != pCertPolicy95Qualifier->pszPracticesReference) && (NULL == *ppwszDisplayText)) { if (!(*ppwszDisplayText = (LPWSTR) malloc((wcslen(pCertPolicy95Qualifier->pszPracticesReference) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszDisplayText, pCertPolicy95Qualifier->pszPracticesReference); }
for (k = 0; k < pCertPolicy95Qualifier->cCPSURLs; k++) { if ((NULL != pCertPolicy95Qualifier->rgCPSURLs[k].pszURL) && (NULL == *ppwszUrlString)) { if (!(*ppwszUrlString = (LPWSTR) malloc((wcslen(pCertPolicy95Qualifier->rgCPSURLs[k].pszURL) + 1) * sizeof(WCHAR)))) { dwRetCode = ERROR_OUTOFMEMORY; goto ErrorExit; }
wcscpy(*ppwszUrlString, pCertPolicy95Qualifier->rgCPSURLs[k].pszURL); } }
free(pCertPolicy95Qualifier); pCertPolicy95Qualifier = NULL; } } } }
//
// If there is neither display text nor an URL, then return CRYPT_E_NOT_FOUND.
//
if ((NULL == *ppwszUrlString) && (NULL == *ppwszDisplayText)) { dwRetCode = CRYPT_E_NOT_FOUND; }
CommonExit:
if (pInfo) free(pInfo);
if (pCertPolicyInfo) free(pCertPolicyInfo);
if (pUserNotice) free(pUserNotice);
if (pCertName) free(pCertName);
if (pCertPolicy95Qualifier) free(pCertPolicy95Qualifier);
return dwRetCode;
ErrorExit: if (*ppwszUrlString) { free(*ppwszUrlString); *ppwszUrlString = NULL; }
if (*ppwszDisplayText) { free(*ppwszDisplayText); *ppwszDisplayText = NULL; }
goto CommonExit; }
BOOL IsOKToDisplayCPS(PCCERT_CONTEXT pCertContext, DWORD dwChainError) { BOOL fResult = FALSE; LPWSTR pwszUrlString = NULL; LPWSTR pwszDisplayText = NULL;
//
// Check parameters and initialize.
//
if (NULL == pCertContext) { goto CommonExit; }
//
// Get CPS info.
//
if ((0 == GetCPSInfo(pCertContext, &pwszUrlString, &pwszDisplayText)) && (pwszDisplayText || IsOKToFormatAsLinkW(pwszUrlString, dwChainError))) { fResult = TRUE; }
CommonExit:
if (pwszUrlString) { free(pwszUrlString); }
if (pwszDisplayText) { free(pwszDisplayText); }
return fResult; }
BOOL DisplayCPS(HWND hwnd, PCCERT_CONTEXT pCertContext, DWORD dwChainError, BOOL fNoCOM) { BOOL fRet = FALSE; DWORD dwRetCode = 0; CPS_STATE_STRUCT cpsStateStruct;
//
// Initialize and check parameters.
//
memset(&cpsStateStruct, 0, sizeof(cpsStateStruct));
if (NULL == pCertContext) { goto Return; }
//
// Get CPS info.
//
if (0 != (dwRetCode = GetCPSInfo(pCertContext, &cpsStateStruct.pwszURL, &cpsStateStruct.pwszDisplayText))) { goto Return; }
// NOW, set up for, and launch that dialog
if ((HmodRichEdit == NULL) && (NULL == (HmodRichEdit = LoadLibraryA("RichEd20.dll")))) { goto Return; }
//
// If there is an URL but no text then just invoke the browser and don't bring
// up the dialog
//
if ((cpsStateStruct.pwszDisplayText == NULL) && (cpsStateStruct.pwszURL != NULL)) { DWORD numBytes = 0; LPSTR pszURL = NULL;
pszURL = CertUIMkMBStr(cpsStateStruct.pwszURL); if (pszURL == NULL) { goto Return; }
CryptuiGoLink(hwnd, pszURL, fNoCOM); free(pszURL); } else { cpsStateStruct.fNoCOM = fNoCOM; cpsStateStruct.dwChainError = dwChainError; DialogBoxParamU(HinstDll, (LPWSTR) MAKEINTRESOURCE(IDD_CPS_DIALOG), hwnd, CPSDlgProc, (LPARAM) &cpsStateStruct); }
fRet = TRUE;
Return:
if (cpsStateStruct.pwszURL) free(cpsStateStruct.pwszURL);
if (cpsStateStruct.pwszDisplayText) free(cpsStateStruct.pwszDisplayText);
return fRet; }
|