Reputation: 788
I want to be able to get all the issuer data that you can get from Windows Explorer like here:
I've been able to get CN from https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetnamestringw, but I don't know what it is about that call that targets the CN (if I did, I might be able to figure how to get everything else). I've tried Googling things like "api wintrust issuer CommonName Organization" and "wincrypt organization commonname" but it's like the API washes its hands of all the other issuer data.
Upvotes: 0
Views: 1797
Reputation: 63
I'm doing it using CertGetNameStringW
std::wstring subjectString(PCCERT_CONTEXT pCertContext) const
{
DWORD dwStrType = CERT_X500_NAME_STR;
// Ensure we have a valid certificate context
if (!pCertContext) {
return L"";
}
// Get the size needed for the subject's name
DWORD dwSubjectNameStrSize = CertGetNameStringW(
pCertContext,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
NULL,
0
);
if (dwSubjectNameStrSize > 0) {
// Allocate memory for the subject's name
std::wstring subjectName(dwSubjectNameStrSize-1, L'\0');
// Get the subject's name
if (CertGetNameStringW(
pCertContext,
CERT_NAME_RDN_TYPE,
0,
&dwStrType,
subjectName.data(),
dwSubjectNameStrSize
) <= 0) {
throw win32error("Extracting subject from certificate");
}
return subjectName;
}
return L"";
}
Upvotes: 0
Reputation: 3880
You only need to use CertNameToStr
and set the &(pCertContext->pCertInfo->Issuer)
parameter:
CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Issuer),
CERT_X500_NAME_STR,
pszString,
cbSize);
I modified the official sample for your reference:
#pragma comment(lib, "crypt32.lib")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <Wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define MY_STRING_TYPE (CERT_OID_NAME_STR)
void MyHandleError(LPTSTR);
void main(void)
{
HCERTSTORE hCertStore;
PCCERT_CONTEXT pCertContext;
if (!(hCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
MY_ENCODING_TYPE,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
L"MY")))
{
MyHandleError(TEXT("The MY system store did not open."));
}
pCertContext = NULL;
while (pCertContext = CertEnumCertificatesInStore(
hCertStore,
pCertContext))
{
LPTSTR pszString;
LPTSTR pszName;
DWORD cbSize;
CERT_BLOB blobEncodedName;
if (!(cbSize = CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
NULL,
0)))
{
MyHandleError(TEXT("CertGetName 1 failed."));
}
if (!(pszName = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
if (CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
0,
NULL,
pszName,
cbSize))
{
_tprintf(TEXT("\nSubject -> %s.\n"), pszName);
free(pszName);
}
else
{
MyHandleError(TEXT("CertGetName failed."));
}
if (!(cbSize = CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
NULL,
0)))
{
MyHandleError(TEXT("CertGetName 1 failed."));
}
if (!(pszName = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
if (CertGetNameString(
pCertContext,
CERT_NAME_SIMPLE_DISPLAY_TYPE,
CERT_NAME_ISSUER_FLAG,
NULL,
pszName,
cbSize))
{
_tprintf(TEXT("Issuer -> %s.\n"), pszName);
free(pszName);
}
else
{
MyHandleError(TEXT("CertGetName failed."));
}
cbSize = CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Subject),
MY_STRING_TYPE,
NULL,
0);
if (1 == cbSize)
{
MyHandleError(TEXT("Subject name is an empty string."));
}
if (!(pszString = (LPTSTR)malloc(cbSize * sizeof(TCHAR))))
{
MyHandleError(TEXT("Memory allocation failed."));
}
cbSize = CertNameToStr(
pCertContext->dwCertEncodingType,
&(pCertContext->pCertInfo->Issuer),
CERT_X500_NAME_STR,
pszString,
cbSize);
if (1 == cbSize)
{
MyHandleError(TEXT("Issuer name is an empty string."));
}
else
{
printf("Issuer String = %ls\n", pszString); //what you want
}
if (!(CertStrToName(
MY_ENCODING_TYPE,
pszString,
MY_STRING_TYPE,
NULL,
NULL, // NULL to get the number of bytes
// needed for the buffer.
&cbSize, // Pointer to a DWORD to hold the
// number of bytes needed for the
// buffer
NULL))) // Optional address of a pointer to
// old the location for an error in the
// input string.
{
MyHandleError(
TEXT("Could not get the length of the BLOB."));
}
if (!(blobEncodedName.pbData = (LPBYTE)malloc(cbSize)))
{
MyHandleError(
TEXT("Memory Allocation for the BLOB failed."));
}
blobEncodedName.cbData = cbSize;
if (CertStrToName(
MY_ENCODING_TYPE,
pszString,
MY_STRING_TYPE,
NULL,
blobEncodedName.pbData,
&blobEncodedName.cbData,
NULL))
{
_tprintf(TEXT("CertStrToName created the BLOB.\n"));
}
else
{
MyHandleError(TEXT("Could not create the BLOB."));
}
free(blobEncodedName.pbData);
free(pszString);
}
_tprintf(
TEXT("\nThere are no more certificates in the store. \n"));
if (CertCloseStore(
hCertStore,
CERT_CLOSE_STORE_CHECK_FLAG))
{
_tprintf(TEXT("The store is closed. ")
TEXT("All certificates are released.\n"));
}
else
{
_tprintf(TEXT("The store was closed, ")
TEXT("but certificates still in use.\n"));
}
_tprintf(TEXT("This demonstration program ran to completion ")
TEXT("without error.\n"));
}
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr,
TEXT("An error occurred in running the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
}
Upvotes: 1