841 lines
21 KiB
C++
841 lines
21 KiB
C++
|
#include <stdio.h>
|
||
|
#include <tchar.h>
|
||
|
#include <malloc.h>
|
||
|
|
||
|
// iis metabase includes
|
||
|
#define INITGUID // must be before iadmw.h
|
||
|
#include <iadmw.h> // Interface header
|
||
|
#include <iiscnfg.h> // MD_ & IIS_MD_ defines
|
||
|
|
||
|
// other includes
|
||
|
#include <wincrypt.h>
|
||
|
#include <xenroll.h>
|
||
|
#include <cryptui.h>
|
||
|
#include "utils.h"
|
||
|
|
||
|
const CLSID CLSID_CEnroll =
|
||
|
{0x43F8F289, 0x7A20, 0x11D0, {0x8F, 0x06, 0x00, 0xC0, 0x4F, 0xC2, 0x95, 0xE1}};
|
||
|
|
||
|
const IID IID_IEnroll =
|
||
|
{0xacaa7838, 0x4585, 0x11d1, {0xab, 0x57, 0x00, 0xc0, 0x4f, 0xc2, 0x95, 0xe1}};
|
||
|
|
||
|
#define ARRAYSIZE(x)\
|
||
|
(sizeof(x)/sizeof(x[0]))
|
||
|
|
||
|
int g_iDo_A = FALSE;
|
||
|
int g_iDo_B = FALSE;
|
||
|
int g_iDo_C = FALSE;
|
||
|
|
||
|
|
||
|
// prototypes
|
||
|
void ShowHelp(void);
|
||
|
int DoStuff(void);
|
||
|
int PrintCertDescList(void);
|
||
|
DWORD CheckCertConstraints(PCCERT_CONTEXT pCC);
|
||
|
|
||
|
// begin
|
||
|
void ShowHelp(void)
|
||
|
{
|
||
|
_tprintf(_T("Certificate Looker test program\n\n"));
|
||
|
_tprintf(_T("Usage:Certlook.exe [-b] [-c]\n\n"));
|
||
|
_tprintf(_T("no parameters opens the 'MY' store\n"));
|
||
|
_tprintf(_T(" -b opens the 'CA' store\n"));
|
||
|
_tprintf(_T(" -c opens the 'ROOT' store\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
int __cdecl main(int argc,char *argv[])
|
||
|
{
|
||
|
int iRet = 0;
|
||
|
int argno;
|
||
|
char * pArg = NULL;
|
||
|
char * pCmdStart = NULL;
|
||
|
TCHAR szFilePath1[_MAX_PATH];
|
||
|
TCHAR szFilePath2[_MAX_PATH];
|
||
|
TCHAR szParamString_Z[_MAX_PATH];
|
||
|
|
||
|
int iDoVersion = FALSE;
|
||
|
int iGotParamZ = FALSE;
|
||
|
|
||
|
*szFilePath1 = '\0';
|
||
|
*szFilePath2 = '\0';
|
||
|
*szParamString_Z = '\0';
|
||
|
_tcscpy(szFilePath1,_T(""));
|
||
|
_tcscpy(szFilePath2,_T(""));
|
||
|
_tcscpy(szParamString_Z,_T(""));
|
||
|
|
||
|
for(argno=1; argno<argc; argno++)
|
||
|
{
|
||
|
if ( argv[argno][0] == '-' || argv[argno][0] == '/' )
|
||
|
{
|
||
|
switch (argv[argno][1])
|
||
|
{
|
||
|
case 'a':
|
||
|
case 'A':
|
||
|
g_iDo_A = TRUE;
|
||
|
break;
|
||
|
case 'b':
|
||
|
case 'B':
|
||
|
g_iDo_B = TRUE;
|
||
|
break;
|
||
|
case 'c':
|
||
|
case 'C':
|
||
|
g_iDo_C = TRUE;
|
||
|
break;
|
||
|
case 'v':
|
||
|
case 'V':
|
||
|
iDoVersion = TRUE;
|
||
|
break;
|
||
|
case 'z':
|
||
|
case 'Z':
|
||
|
// Get the string for this flag
|
||
|
pArg = CharNextA(argv[argno]);
|
||
|
pArg = CharNextA(pArg);
|
||
|
if (*pArg == ':')
|
||
|
{
|
||
|
char szTempString[_MAX_PATH];
|
||
|
|
||
|
pArg = CharNextA(pArg);
|
||
|
|
||
|
// Check if it's quoted
|
||
|
if (*pArg == '\"')
|
||
|
{
|
||
|
pArg = CharNextA(pArg);
|
||
|
pCmdStart = pArg;
|
||
|
while ((*pArg) && (*pArg != '\"')){pArg = CharNextA(pArg);}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pCmdStart = pArg;
|
||
|
while (*pArg){pArg = CharNextA(pArg);}
|
||
|
}
|
||
|
*pArg = '\0';
|
||
|
lstrcpyA(szTempString, StripWhitespace(pCmdStart));
|
||
|
|
||
|
// Convert to unicode
|
||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||
|
MultiByteToWideChar(CP_ACP, 0, szTempString, -1, (LPWSTR) szParamString_Z, _MAX_PATH);
|
||
|
#else
|
||
|
_tcscpy(szParamString_Z,szTempString);
|
||
|
#endif
|
||
|
|
||
|
iGotParamZ = TRUE;
|
||
|
}
|
||
|
break;
|
||
|
case '?':
|
||
|
goto main_exit_with_help;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_tcsicmp(szFilePath1, _T("")) == 0)
|
||
|
{
|
||
|
// if no arguments, then get the filename portion
|
||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||
|
MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath1, _MAX_PATH);
|
||
|
#else
|
||
|
_tcscpy(szFilePath1,argv[argno]);
|
||
|
#endif
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (_tcsicmp(szFilePath2, _T("")) == 0)
|
||
|
{
|
||
|
// if no arguments, then get the filename portion
|
||
|
#if defined(UNICODE) || defined(_UNICODE)
|
||
|
MultiByteToWideChar(CP_ACP, 0, argv[argno], -1, (LPTSTR) szFilePath2, _MAX_PATH);
|
||
|
#else
|
||
|
_tcscpy(szFilePath2,argv[argno]);
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
iRet = DoStuff();
|
||
|
|
||
|
if (TRUE == iDoVersion)
|
||
|
{
|
||
|
// output the version
|
||
|
_tprintf(_T("1\n\n"));
|
||
|
|
||
|
iRet = 10;
|
||
|
goto main_exit_gracefully;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if (_tcsicmp(szFilePath1, _T("")) == 0)
|
||
|
{
|
||
|
goto main_exit_with_help;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
goto main_exit_gracefully;
|
||
|
|
||
|
main_exit_gracefully:
|
||
|
exit(iRet);
|
||
|
|
||
|
main_exit_with_help:
|
||
|
ShowHelp();
|
||
|
exit(iRet);
|
||
|
}
|
||
|
|
||
|
int DoStuff(void)
|
||
|
{
|
||
|
int iReturn = FALSE;
|
||
|
|
||
|
PrintCertDescList();
|
||
|
|
||
|
goto DoStuff_Exit;
|
||
|
|
||
|
DoStuff_Exit:
|
||
|
return iReturn;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL ViewCertificateDialog(CRYPT_HASH_BLOB* pcrypt_hash, HWND hWnd)
|
||
|
{
|
||
|
BOOL bReturn = FALSE;
|
||
|
HCERTSTORE hStore = NULL;
|
||
|
PCCERT_CONTEXT pCert = NULL;
|
||
|
|
||
|
hStore = CertOpenStore(
|
||
|
CERT_STORE_PROV_SYSTEM,
|
||
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||
|
NULL,
|
||
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
||
|
_T("MY")
|
||
|
);
|
||
|
if (hStore != NULL)
|
||
|
{
|
||
|
// Now we need to find cert by hash
|
||
|
//CRYPT_HASH_BLOB crypt_hash;
|
||
|
//crypt_hash.cbData = hash.GetSize();
|
||
|
//crypt_hash.pbData = hash.GetData();
|
||
|
pCert = CertFindCertificateInStore(hStore,
|
||
|
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||
|
0, CERT_FIND_HASH, (LPVOID)pcrypt_hash, NULL);
|
||
|
}
|
||
|
|
||
|
if (pCert)
|
||
|
{
|
||
|
BOOL fPropertiesChanged;
|
||
|
CRYPTUI_VIEWCERTIFICATE_STRUCT vcs;
|
||
|
HCERTSTORE hCertStore = ::CertDuplicateStore(hStore);
|
||
|
::ZeroMemory (&vcs, sizeof (vcs));
|
||
|
vcs.dwSize = sizeof (vcs);
|
||
|
vcs.hwndParent = hWnd;
|
||
|
vcs.dwFlags = 0;
|
||
|
vcs.cStores = 1;
|
||
|
vcs.rghStores = &hCertStore;
|
||
|
vcs.pCertContext = pCert;
|
||
|
::CryptUIDlgViewCertificate(&vcs, &fPropertiesChanged);
|
||
|
::CertCloseStore (hCertStore, 0);
|
||
|
bReturn = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// it failed
|
||
|
}
|
||
|
if (pCert != NULL)
|
||
|
::CertFreeCertificateContext(pCert);
|
||
|
if (hStore != NULL)
|
||
|
::CertCloseStore(hStore, 0);
|
||
|
|
||
|
return bReturn;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
GetKeyUsageProperty(PCCERT_CONTEXT pCertContext,
|
||
|
CERT_ENHKEY_USAGE ** pKeyUsage,
|
||
|
BOOL fPropertiesOnly,
|
||
|
HRESULT * phRes)
|
||
|
{
|
||
|
DWORD cb = 0;
|
||
|
BOOL bRes = FALSE;
|
||
|
if (!CertGetEnhancedKeyUsage(pCertContext,
|
||
|
fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
|
||
|
NULL,
|
||
|
&cb))
|
||
|
{
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
if (NULL == (*pKeyUsage = (CERT_ENHKEY_USAGE *)malloc(cb)))
|
||
|
{
|
||
|
*phRes = E_OUTOFMEMORY;
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
if (!CertGetEnhancedKeyUsage (pCertContext,
|
||
|
fPropertiesOnly ? CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG : 0,
|
||
|
*pKeyUsage,
|
||
|
&cb))
|
||
|
{
|
||
|
free(*pKeyUsage);
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
*phRes = S_OK;
|
||
|
bRes = TRUE;
|
||
|
ErrExit:
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ContainsKeyUsageProperty(PCCERT_CONTEXT pCertContext,
|
||
|
HRESULT * phRes
|
||
|
)
|
||
|
{
|
||
|
BOOL bRes = FALSE;
|
||
|
CERT_ENHKEY_USAGE * pKeyUsage = NULL;
|
||
|
if (GetKeyUsageProperty(pCertContext, &pKeyUsage, FALSE, phRes))
|
||
|
{
|
||
|
if (pKeyUsage->cUsageIdentifier == 0)
|
||
|
{
|
||
|
_tprintf(_T("cUsageIdentifier=0 <---\n"));
|
||
|
bRes = TRUE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
|
||
|
{
|
||
|
// Our friends from CAPI made this property ASCII even for
|
||
|
// UNICODE program
|
||
|
if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_PKIX_KP_SERVER_AUTH) != NULL)
|
||
|
{
|
||
|
_tprintf(_T("cUsageIdentifier=szOID_PKIX_KP_SERVER_AUTH\n"));
|
||
|
bRes = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_SERVER_GATED_CRYPTO) != NULL)
|
||
|
{
|
||
|
_tprintf(_T("cUsageIdentifier=szOID_SERVER_GATED_CRYPTO\n"));
|
||
|
bRes = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
if (strstr(pKeyUsage->rgpszUsageIdentifier[i], szOID_SGC_NETSCAPE) != NULL)
|
||
|
{
|
||
|
_tprintf(_T("cUsageIdentifier=szOID_SGC_NETSCAPE\n"));
|
||
|
bRes = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (pKeyUsage){free(pKeyUsage);}
|
||
|
}
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
GetNameString(PCCERT_CONTEXT pCertContext,
|
||
|
DWORD type,
|
||
|
DWORD flag,
|
||
|
WCHAR * TheName,
|
||
|
HRESULT * phRes)
|
||
|
{
|
||
|
BOOL bRes = FALSE;
|
||
|
LPTSTR pName = NULL;
|
||
|
DWORD cchName = CertGetNameString(pCertContext, type, flag, NULL, NULL, 0);
|
||
|
if (cchName > 1)
|
||
|
{
|
||
|
pName = (LPTSTR) malloc(cchName);
|
||
|
if (pName)
|
||
|
{
|
||
|
bRes = (1 != CertGetNameString(pCertContext, type, flag, NULL, pName, cchName));
|
||
|
ZeroMemory(TheName,sizeof(TheName));
|
||
|
memcpy(TheName,pName,cchName);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
GetFriendlyName(PCCERT_CONTEXT pCertContext,
|
||
|
WCHAR * TheName,
|
||
|
HRESULT * phRes)
|
||
|
{
|
||
|
BOOL bRes = FALSE;
|
||
|
DWORD cb;
|
||
|
TCHAR * pName = NULL;
|
||
|
if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, NULL, &cb))
|
||
|
{
|
||
|
pName = (LPTSTR) malloc(cb);
|
||
|
if (pName)
|
||
|
{
|
||
|
if (CertGetCertificateContextProperty(pCertContext, CERT_FRIENDLY_NAME_PROP_ID, pName, &cb))
|
||
|
{
|
||
|
pName[cb] = 0;
|
||
|
bRes = TRUE;
|
||
|
|
||
|
ZeroMemory(TheName,sizeof(TheName));
|
||
|
memcpy(TheName,pName,cb);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*phRes = HRESULT_FROM_WIN32(GetLastError());
|
||
|
}
|
||
|
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL MyGetOIDInfo(LPWSTR string, DWORD stringSize, LPSTR pszObjId)
|
||
|
{
|
||
|
PCCRYPT_OID_INFO pOIDInfo;
|
||
|
|
||
|
if (NULL != (pOIDInfo = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pszObjId, 0)))
|
||
|
{
|
||
|
if ((DWORD)wcslen(pOIDInfo->pwszName)+1 <= stringSize)
|
||
|
{
|
||
|
wcscpy(string, pOIDInfo->pwszName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return (MultiByteToWideChar(CP_ACP, 0, pszObjId, -1, string, stringSize) != 0);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
FormatEnhancedKeyUsageString(PCCERT_CONTEXT pCertContext,
|
||
|
BOOL fPropertiesOnly,
|
||
|
BOOL fMultiline,
|
||
|
HRESULT * phRes)
|
||
|
{
|
||
|
CERT_ENHKEY_USAGE * pKeyUsage = NULL;
|
||
|
WCHAR szText[255];
|
||
|
BOOL bRes = FALSE;
|
||
|
|
||
|
if (GetKeyUsageProperty(pCertContext, &pKeyUsage, fPropertiesOnly, phRes))
|
||
|
{
|
||
|
_tprintf(_T("EnhancedKeyUsage="));
|
||
|
|
||
|
// loop for each usage and add it to the display string
|
||
|
for (DWORD i = 0; i < pKeyUsage->cUsageIdentifier; i++)
|
||
|
{
|
||
|
if (!(bRes = MyGetOIDInfo(szText, ARRAYSIZE(szText), pKeyUsage->rgpszUsageIdentifier[i])))
|
||
|
break;
|
||
|
// add delimeter if not first iteration
|
||
|
wprintf(szText);
|
||
|
wprintf(L",");
|
||
|
}
|
||
|
wprintf(L"\n");
|
||
|
free (pKeyUsage);
|
||
|
}
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL PrintCertDescription(PCCERT_CONTEXT pCert)
|
||
|
{
|
||
|
BOOL bRes = FALSE;
|
||
|
HRESULT hRes = 0;
|
||
|
DWORD cb;
|
||
|
UINT i, j;
|
||
|
CERT_NAME_INFO * pNameInfo;
|
||
|
WCHAR wCA_Name[255];
|
||
|
|
||
|
if (pCert == NULL)
|
||
|
goto ErrExit;
|
||
|
|
||
|
if (!CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
|
||
|
pCert->pCertInfo->Subject.pbData,
|
||
|
pCert->pCertInfo->Subject.cbData,
|
||
|
0, NULL, &cb)
|
||
|
|| NULL == (pNameInfo = (CERT_NAME_INFO *)_alloca(cb))
|
||
|
|| !CryptDecodeObject(X509_ASN_ENCODING, X509_UNICODE_NAME,
|
||
|
pCert->pCertInfo->Subject.pbData,
|
||
|
pCert->pCertInfo->Subject.cbData,
|
||
|
0,
|
||
|
pNameInfo, &cb)
|
||
|
)
|
||
|
{
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < pNameInfo->cRDN; i++)
|
||
|
{
|
||
|
CERT_RDN_VALUE_BLOB Blobber;
|
||
|
CERT_RDN rdn = pNameInfo->rgRDN[i];
|
||
|
for (j = 0; j < rdn.cRDNAttr; j++)
|
||
|
{
|
||
|
CERT_RDN_ATTR attr = rdn.rgRDNAttr[j];
|
||
|
Blobber = (CERT_RDN_VALUE_BLOB) attr.Value;
|
||
|
WCHAR TempString[255];
|
||
|
ZeroMemory(TempString,sizeof(TempString));
|
||
|
memcpy(TempString, Blobber.pbData,Blobber.cbData);
|
||
|
|
||
|
if (strcmp(attr.pszObjId, szOID_COMMON_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_COMMON_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
else if (strcmp(attr.pszObjId, szOID_COUNTRY_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_COUNTRY_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
else if (strcmp(attr.pszObjId, szOID_LOCALITY_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_LOCALITY_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
else if (strcmp(attr.pszObjId, szOID_STATE_OR_PROVINCE_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_STATE_OR_PROVINCE_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
else if (strcmp(attr.pszObjId, szOID_ORGANIZATION_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_ORGANIZATION_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
else if (strcmp(attr.pszObjId, szOID_ORGANIZATIONAL_UNIT_NAME) == 0)
|
||
|
{
|
||
|
_tprintf(_T("szOID_ORGANIZATIONAL_UNIT_NAME="));wprintf(TempString);_tprintf(_T("\n"));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// issued to
|
||
|
if (!GetNameString(pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, wCA_Name, &hRes))
|
||
|
{
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
_tprintf(_T("Name="));wprintf(wCA_Name);_tprintf(_T("\n"));
|
||
|
if (wCA_Name){free(wCA_Name);}
|
||
|
|
||
|
/*
|
||
|
// expiration date
|
||
|
if (!FormatDateString(desc.m_ExpirationDate, pCert->pCertInfo->NotAfter, FALSE, FALSE))
|
||
|
{
|
||
|
goto ErrExit;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// purpose
|
||
|
if (!FormatEnhancedKeyUsageString(pCert, FALSE, FALSE, &hRes))
|
||
|
{
|
||
|
// According to local experts, we should also use certs without this property set
|
||
|
_tprintf(_T("There is no EnhancedKeyUsage on this one.\n"));
|
||
|
//goto ErrExit;
|
||
|
}
|
||
|
|
||
|
// friendly name
|
||
|
if (GetFriendlyName(pCert, wCA_Name, &hRes))
|
||
|
{
|
||
|
_tprintf(_T("FriendlyName="));wprintf(wCA_Name);_tprintf(_T("\n"));
|
||
|
if (wCA_Name){free(wCA_Name);}
|
||
|
}
|
||
|
|
||
|
bRes = TRUE;
|
||
|
|
||
|
ErrExit:
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
HCERTSTORE OpenMyStore(IEnroll * pEnroll, HRESULT * phResult)
|
||
|
{
|
||
|
HCERTSTORE hStore = NULL;
|
||
|
BSTR bstrStoreName = NULL;
|
||
|
BSTR bstrStoreType = NULL;
|
||
|
long dwStoreFlags;
|
||
|
|
||
|
if(SUCCEEDED(pEnroll->get_MyStoreNameWStr(&bstrStoreName)))
|
||
|
{
|
||
|
if(SUCCEEDED(pEnroll->get_MyStoreTypeWStr(&bstrStoreType)))
|
||
|
{
|
||
|
if(SUCCEEDED(pEnroll->get_MyStoreFlags(&dwStoreFlags)))
|
||
|
{
|
||
|
size_t store_type_len = wcslen(bstrStoreType);
|
||
|
char * szStoreProvider = (char *)_alloca(store_type_len + 1);
|
||
|
//ASSERT(szStoreProvider != NULL);
|
||
|
size_t n = wcstombs(szStoreProvider, bstrStoreType, store_type_len);
|
||
|
//ASSERT(n != -1);
|
||
|
// this converter doesn't set zero byte!!!
|
||
|
szStoreProvider[n] = '\0';
|
||
|
|
||
|
if (g_iDo_B)
|
||
|
{
|
||
|
_tprintf(_T("CertOpenStore:CA\n"));
|
||
|
hStore = CertOpenStore(
|
||
|
CERT_STORE_PROV_SYSTEM,
|
||
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||
|
NULL,
|
||
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
||
|
L"CA");
|
||
|
}
|
||
|
else if (g_iDo_C)
|
||
|
{
|
||
|
_tprintf(_T("CertOpenStore:ROOT\n"));
|
||
|
hStore = CertOpenStore(
|
||
|
CERT_STORE_PROV_SYSTEM,
|
||
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||
|
NULL,
|
||
|
CERT_SYSTEM_STORE_LOCAL_MACHINE,
|
||
|
L"ROOT");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wprintf(L"CertOpenStore:%s\n",bstrStoreName);
|
||
|
hStore = CertOpenStore(
|
||
|
szStoreProvider,
|
||
|
PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
|
||
|
NULL,
|
||
|
dwStoreFlags,
|
||
|
bstrStoreName
|
||
|
);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bstrStoreName) {CoTaskMemFree(bstrStoreName);}
|
||
|
if (bstrStoreType) {CoTaskMemFree(bstrStoreType);}
|
||
|
if (hStore == NULL){*phResult = HRESULT_FROM_WIN32(GetLastError());}
|
||
|
return hStore;
|
||
|
}
|
||
|
|
||
|
IEnroll * GetEnrollObject(void)
|
||
|
{
|
||
|
HRESULT hRes = 0;
|
||
|
IEnroll * pEnroll;
|
||
|
BOOL bPleaseDoCoUninit = FALSE;
|
||
|
|
||
|
hRes = CoInitialize(NULL);
|
||
|
if(FAILED(hRes))
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
bPleaseDoCoUninit = TRUE;
|
||
|
|
||
|
hRes = CoCreateInstance(CLSID_CEnroll,NULL,CLSCTX_INPROC_SERVER,IID_IEnroll,(void **)&pEnroll);
|
||
|
|
||
|
// now we need to change defaults for this
|
||
|
// object to LOCAL_MACHINE
|
||
|
if (pEnroll != NULL)
|
||
|
{
|
||
|
long dwFlags;
|
||
|
pEnroll->get_MyStoreFlags(&dwFlags);
|
||
|
dwFlags &= ~CERT_SYSTEM_STORE_LOCATION_MASK;
|
||
|
dwFlags |= CERT_SYSTEM_STORE_LOCAL_MACHINE;
|
||
|
// following call will change Request store flags also
|
||
|
pEnroll->put_MyStoreFlags(dwFlags);
|
||
|
pEnroll->get_GenKeyFlags(&dwFlags);
|
||
|
dwFlags |= CRYPT_EXPORTABLE;
|
||
|
pEnroll->put_GenKeyFlags(dwFlags);
|
||
|
pEnroll->put_KeySpec(AT_KEYEXCHANGE);
|
||
|
pEnroll->put_ProviderType(PROV_RSA_SCHANNEL);
|
||
|
pEnroll->put_DeleteRequestCert(TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_tprintf(_T("GetEnrollObject failed!\n"));
|
||
|
}
|
||
|
|
||
|
if (bPleaseDoCoUninit)
|
||
|
{
|
||
|
CoUninitialize();
|
||
|
}
|
||
|
|
||
|
return pEnroll;
|
||
|
}
|
||
|
|
||
|
|
||
|
int PrintCertDescList(void)
|
||
|
{
|
||
|
BOOL bRes = FALSE;
|
||
|
HRESULT hRes = 0;
|
||
|
HCERTSTORE hStore = NULL;
|
||
|
int iCount = 0;
|
||
|
|
||
|
// we are looking to MY store only
|
||
|
IEnroll * pXEnroll = GetEnrollObject();
|
||
|
if (!pXEnroll){goto PrintCertDescList_Exit;}
|
||
|
|
||
|
hStore = OpenMyStore(GetEnrollObject(), &hRes);
|
||
|
if (hStore != NULL)
|
||
|
{
|
||
|
PCCERT_CONTEXT pCert = NULL;
|
||
|
|
||
|
// do not include certs with improper usage
|
||
|
while (NULL != (pCert = CertEnumCertificatesInStore(hStore, pCert)))
|
||
|
{
|
||
|
_tprintf(_T("========================================\n"));
|
||
|
if (TRUE == g_iDo_A)
|
||
|
{
|
||
|
AttachFriendlyName(pCert);
|
||
|
}
|
||
|
CheckCertConstraints(pCert);
|
||
|
|
||
|
if (!ContainsKeyUsageProperty(pCert, &hRes))
|
||
|
{
|
||
|
_tprintf(_T("There is a key missing KeyUsage Property. skipping.\n"));
|
||
|
if (SUCCEEDED(hRes) || hRes == CRYPT_E_NOT_FOUND)
|
||
|
continue;
|
||
|
else
|
||
|
goto PrintCertDescList_ExitErr;
|
||
|
}
|
||
|
if (!PrintCertDescription(pCert))
|
||
|
{
|
||
|
if (hRes == CRYPT_E_NOT_FOUND)
|
||
|
continue;
|
||
|
goto PrintCertDescList_ExitErr;
|
||
|
}
|
||
|
}
|
||
|
_tprintf(_T("========================================\n"));
|
||
|
bRes = TRUE;
|
||
|
PrintCertDescList_ExitErr:
|
||
|
if (pCert != NULL){CertFreeCertificateContext(pCert);}
|
||
|
CertCloseStore(hStore, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_tprintf(_T("CertOpenStore failed\n"));
|
||
|
}
|
||
|
|
||
|
PrintCertDescList_Exit:
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD CheckCertConstraints(PCCERT_CONTEXT pCC)
|
||
|
{
|
||
|
PCERT_EXTENSION pCExt; // returned ext
|
||
|
LPCSTR pszObjId; // Object identifier
|
||
|
DWORD i;
|
||
|
|
||
|
CERT_BASIC_CONSTRAINTS_INFO *pConstraints=NULL;
|
||
|
CERT_BASIC_CONSTRAINTS2_INFO *p2Constraints=NULL;
|
||
|
DWORD ConstraintSize=0;
|
||
|
DWORD RV=ERROR_IPSEC_IKE_GENERAL_PROCESSING_ERROR;
|
||
|
BOOL Using2=FALSE;
|
||
|
|
||
|
void* ConstraintBlob=NULL;
|
||
|
|
||
|
pszObjId = szOID_BASIC_CONSTRAINTS;
|
||
|
|
||
|
pCExt = CertFindExtension(
|
||
|
pszObjId, // in, Pointer to object identifier
|
||
|
pCC->pCertInfo->cExtension, // in, # of extensions in the array
|
||
|
pCC->pCertInfo->rgExtension); // in, The array of attributes
|
||
|
|
||
|
if (pCExt == NULL) {
|
||
|
pszObjId = szOID_BASIC_CONSTRAINTS2;
|
||
|
|
||
|
pCExt = CertFindExtension(
|
||
|
pszObjId, // in, Pointer to object identifier
|
||
|
pCC->pCertInfo->cExtension, // in, # of extensions in the array
|
||
|
pCC->pCertInfo->rgExtension); // in, The array of attributes
|
||
|
Using2=TRUE;
|
||
|
}
|
||
|
|
||
|
if (pCExt == NULL) {
|
||
|
_tprintf(_T("No BasicConstraints in cert\n"));
|
||
|
goto ret;
|
||
|
}
|
||
|
|
||
|
// Decode extension
|
||
|
if (!CryptDecodeObject(
|
||
|
X509_ASN_ENCODING,
|
||
|
pCExt->pszObjId,
|
||
|
pCExt->Value.pbData,
|
||
|
pCExt->Value.cbData,
|
||
|
0,
|
||
|
NULL,
|
||
|
&ConstraintSize)) {
|
||
|
|
||
|
_tprintf(_T("Error %d when Decoding extension\n"),GetLastError());
|
||
|
goto ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
ConstraintBlob=malloc(ConstraintSize);
|
||
|
if (ConstraintBlob == NULL)
|
||
|
{
|
||
|
_tprintf(_T("out of memory!!!!...\n"));
|
||
|
goto ret;
|
||
|
}
|
||
|
|
||
|
if (!CryptDecodeObject(
|
||
|
X509_ASN_ENCODING,
|
||
|
pCExt->pszObjId,
|
||
|
pCExt->Value.pbData,
|
||
|
pCExt->Value.cbData,
|
||
|
0,
|
||
|
(void*)ConstraintBlob,
|
||
|
&ConstraintSize))
|
||
|
{
|
||
|
_tprintf(_T("Error %d when Decoding extension\n"),GetLastError());
|
||
|
goto ret;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (Using2)
|
||
|
{
|
||
|
_tprintf(_T("Using2....\n"));
|
||
|
|
||
|
p2Constraints=(CERT_BASIC_CONSTRAINTS2_INFO*)ConstraintBlob;
|
||
|
if (!p2Constraints->fCA)
|
||
|
{
|
||
|
_tprintf(_T("Yes, there is constraints in here! it's not a CA!\n"));
|
||
|
RV=ERROR_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_tprintf(_T("Yes, there is constraints in here! it's a CA!\n"));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_tprintf(_T("!Using2....\n"));
|
||
|
pConstraints=(CERT_BASIC_CONSTRAINTS_INFO*)ConstraintBlob;
|
||
|
if (((pConstraints->SubjectType.cbData * 8) - pConstraints->SubjectType.cUnusedBits) >= 2)
|
||
|
{
|
||
|
if ((*pConstraints->SubjectType.pbData) & CERT_END_ENTITY_SUBJECT_FLAG)
|
||
|
{
|
||
|
_tprintf(_T("Yes, there is constraints in here! CERT_END_ENTITY_SUBJECT_FLAG = true!\n"));
|
||
|
|
||
|
RV=ERROR_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
_tprintf(_T("Yes, there is constraints in here but CERT_END_ENTITY_SUBJECT_FLAG = false!\n"));
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ret:
|
||
|
|
||
|
free(ConstraintBlob);
|
||
|
return (RV);
|
||
|
|
||
|
}
|