Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

991 lines
30 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1995 - 1996
//
// File: tx500str.cpp
//
// Contents: X500 Certificate Name String API Tests
//
// See Usage() for list of test options.
//
//
// Functions: main
//
// History: 18-Feb-97 philh created
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <assert.h>
#include "wincrypt.h"
#include "certtest.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <memory.h>
#include <time.h>
#define ALL_STR_TYPES 0xFFFFFFFF
static BOOL fVerbose = FALSE;
static void FormatAndParseCertNames(
IN LPCSTR pszCertFilename,
IN DWORD dwStrType,
IN BOOL fSubject
);
static void GetCertNameFromFile(
IN LPCSTR pszCertFilename,
IN DWORD dwGetNameStringType,
IN LPSTR pszAttrOID,
IN DWORD dwStrType,
IN BOOL fSubject,
IN DWORD dwExpectedErr
);
static void ParseX500Name(
IN LPCSTR pszName,
IN DWORD dwStrType,
IN DWORD dwExpectedErr,
IN int iExpectedErrOffset
);
static void ParsePredefinedX500Names();
#define CROW 8
void PrintWords(LPCSTR pszHdr, WORD *pw, DWORD cwSize)
{
ULONG cw, i;
while (cwSize > 0)
{
printf("%s", pszHdr);
cw = min(CROW, cwSize);
cwSize -= cw;
for (i = 0; i<cw; i++)
printf(" %04X", pw[i]);
for (i = cw; i<CROW; i++)
printf(" ");
printf(" '");
for (i = 0; i<cw; i++)
if (pw[i] >= 0x20 && pw[i] <= 0x7f)
printf("%C", pw[i]);
else
printf(".");
pw += cw;
printf("'\n");
}
}
static void Usage(void)
{
int i;
printf("Usage: tx500str [options]\n");
printf("Options are:\n");
printf(" -h - This message\n");
printf(" -n<X500 Name> - For example \"CN=Joe Cool, O=Microsoft\"\n");
printf(" -e<number> - Expected Error\n");
printf(" -o<number> - Expected Error Offset\n");
printf(" -c<Cert Filename> - Read encoded cert file for names\n");
printf(" -S - Format cert's Subject (default)\n");
printf(" -I - Format cert's Issuer\n");
printf(" -f<number> - Name string formatting type\n");
printf(" -fAll - Name string formatting (All types)\n");
printf(" -v - Verbose\n");
printf(" -g - CertGetNameString(SIMPLE_DISPLAY)\n");
printf(" -g<number> - CertGetNameString type\n");
printf(" -a<OID> - Attribute OID, for example, -a2.5.4.3\n");
printf("\n");
printf("Default: Cycle through predefined list of X500 test names\n");
}
int _cdecl main(int argc, char * argv[])
{
LPSTR pszName = NULL;
LPSTR pszCertFilename = NULL;
DWORD dwStrType = 0;
DWORD dwExpectedErr = 0;
int iExpectedErrOffset = -1;
BOOL fSubject = TRUE;
BOOL fGetCertName = FALSE;
DWORD dwGetNameStringType = CERT_NAME_SIMPLE_DISPLAY_TYPE;
LPSTR pszAttrOID = NULL;
while (--argc>0)
{
if (**++argv == '-')
{
switch(argv[0][1])
{
case 'c':
pszCertFilename = argv[0]+2;
if (*pszCertFilename == '\0') {
printf("Need to specify filename\n");
goto BadUsage;
}
break;
case 'n':
pszName = argv[0]+2;
if (*pszName == '\0') {
printf("Need to specify X500 name\n");
goto BadUsage;
}
break;
case 'f':
if (argv[0][2]) {
if (0 == _stricmp(argv[0]+2, "ALL"))
dwStrType = ALL_STR_TYPES;
else
dwStrType = (DWORD) strtoul(argv[0]+2, NULL, 0);
} else {
printf("Need to specify -fALL or -f<number>\n");
goto BadUsage;
}
break;
case 'e':
if (argv[0][2])
dwExpectedErr = (DWORD) strtoul(argv[0]+2, NULL, 0);
else {
printf("Need to specify -e<number>\n");
goto BadUsage;
}
break;
case 'o':
if (argv[0][2])
iExpectedErrOffset = strtol(argv[0]+2, NULL, 0);
else {
printf("Need to specify -o<number>\n");
goto BadUsage;
}
break;
case 'v':
fVerbose = TRUE;
break;
case 'S':
fSubject = TRUE;
break;
case 'I':
fSubject = FALSE;
break;
case 'g':
fGetCertName = TRUE;
if (argv[0][2])
dwGetNameStringType = (DWORD) strtoul(argv[0]+2, NULL, 0);
break;
case 'a':
pszAttrOID = argv[0]+2;
break;
case 'h':
default:
goto BadUsage;
}
} else
goto BadUsage;
}
printf("command line: %s\n", GetCommandLine());
if (pszName) {
printf("Parsing ");
ParseX500Name(
pszName,
dwStrType,
dwExpectedErr,
iExpectedErrOffset
);
} else if (pszCertFilename) {
printf("Reading encoded certificate file: %s\n", pszCertFilename);
if (fGetCertName)
GetCertNameFromFile(
pszCertFilename,
dwGetNameStringType,
pszAttrOID,
dwStrType,
fSubject,
dwExpectedErr
);
else
FormatAndParseCertNames(
pszCertFilename,
dwStrType,
fSubject
);
} else {
printf("Parsing predefined X500 test names\n", pszName);
ParsePredefinedX500Names();
}
CommonReturn:
return 0;
BadUsage:
Usage();
goto CommonReturn;
}
static void *TestDecodeObject(
IN LPCSTR lpszStructType,
IN const BYTE *pbEncoded,
IN DWORD cbEncoded
)
{
DWORD cbInfo;
void *pvInfo;
// Set to bogus value. pvInfo == NULL, should cause it to be ignored.
cbInfo = 0x12345678;
CryptDecodeObject(
dwCertEncodingType,
lpszStructType,
pbEncoded,
cbEncoded,
0, // dwFlags
NULL, // pvInfo
&cbInfo
);
if (cbInfo == 0) {
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptDecodeObject(StructType: %d, pvInfo == NULL)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptDecodeObject(StructType: %s, pvInfo == NULL)",
lpszStructType);
PrintLastError("");
return NULL;
}
if (NULL == (pvInfo = TestAlloc(cbInfo)))
return NULL;
if (!CryptDecodeObject(
dwCertEncodingType,
lpszStructType,
pbEncoded,
cbEncoded,
0, // dwFlags
pvInfo,
&cbInfo
)) {
if ((DWORD_PTR) lpszStructType <= 0xFFFF)
printf("CryptDecodeObject(StructType: %d)",
(DWORD)(DWORD_PTR) lpszStructType);
else
printf("CryptDecodeObject(StructType: %s)",
lpszStructType);
PrintLastError("");
TestFree(pvInfo);
return NULL;
}
return pvInfo;
}
static BOOL DecodeName(BYTE *pbEncoded, DWORD cbEncoded, DWORD dwStrType)
{
BOOL fResult;
PCERT_NAME_INFO pInfo = NULL;
DWORD i,j;
PCERT_RDN pRDN;
PCERT_RDN_ATTR pAttr;
CERT_NAME_BLOB Name;
DWORD cwsz;
LPWSTR pwsz;
if (NULL == (pInfo = (PCERT_NAME_INFO) TestDecodeObject(
X509_NAME,
pbEncoded,
cbEncoded
))) goto ErrorReturn;
for (i = 0, pRDN = pInfo->rgRDN; i < pInfo->cRDN; i++, pRDN++) {
for (j = 0, pAttr = pRDN->rgRDNAttr; j < pRDN->cRDNAttr; j++, pAttr++) {
LPSTR pszObjId = pAttr->pszObjId;
if (pszObjId == NULL)
pszObjId = "<NULL OBJID>";
printf(" [%d,%d] %s ValueType: %d\n",
i, j, pszObjId, pAttr->dwValueType);
if (pAttr->Value.cbData)
PrintBytes(" ", pAttr->Value.pbData, pAttr->Value.cbData);
else
printf(" NO Value Bytes\n");
}
}
if (dwStrType == 0xFFFFFFFF)
goto GoodReturn;
Name.pbData = pbEncoded;
Name.cbData = cbEncoded;
if (0 == (dwStrType & 0xFFFF))
dwStrType |= CERT_X500_NAME_STR;
cwsz = CertNameToStrW(
dwCertEncodingType,
&Name,
dwStrType,
NULL, // pwsz
0); // cwsz
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
CertNameToStrW(
dwCertEncodingType,
&Name,
dwStrType,
pwsz,
cwsz);
printf(" %S\n", pwsz);
TestFree(pwsz);
}
GoodReturn:
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
fResult = FALSE;
CommonReturn:
if (pInfo)
TestFree(pInfo);
return fResult;
}
static void ParseUnicodeX500Name(
IN LPCWSTR pwszName,
IN DWORD dwStrFlags
)
{
BOOL fResult;
DWORD i;
BYTE *pbEncoded;
DWORD cbEncoded;
CERT_NAME_BLOB Name;
DWORD cwsz;
LPWSTR pwsz;
printf("Unicode name::\n");
PrintWords(" ", (WORD *) pwszName, wcslen(pwszName));
fResult = CertStrToNameW(
dwCertEncodingType,
pwszName,
dwStrFlags | 0, // dwStrType
NULL, // pvReserved
NULL, // pbEncoded
&cbEncoded,
NULL // pwszError
);
if (!fResult) {
PrintLastError("CertStrToNameW");
return;
}
if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbEncoded)))
return;
if (!CertStrToNameW(
dwCertEncodingType,
pwszName,
dwStrFlags | 0, // dwStrType
NULL, // pvReserved
pbEncoded,
&cbEncoded,
NULL // pwszError
))
PrintLastError("CertStrToNameW");
else if (fVerbose)
DecodeName(pbEncoded, cbEncoded, 0xFFFFFFFF);
// Decode name to see if we come up with what was passed in
Name.pbData = pbEncoded;
Name.cbData = cbEncoded;
cwsz = CertNameToStrW(
dwCertEncodingType,
&Name,
dwStrFlags | CERT_X500_NAME_STR,
NULL, // pwsz
0); // cwsz
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
cwsz = CertNameToStrW(
dwCertEncodingType,
&Name,
dwStrFlags | CERT_X500_NAME_STR,
pwsz,
cwsz);
cwsz--;
if (cwsz != wcslen(pwszName)) {
printf(" failed => CertNameToStrW length of %d != %d\n",
cwsz, wcslen(pwszName));
PrintWords(" ", (WORD *) pwsz, cwsz);
} else if (0 != memcmp(pwsz, pwszName, cwsz * sizeof(WCHAR))) {
printf(" failed => CertNameToStrW didn't match input\n");
PrintWords(" ", (WORD *) pwsz, cwsz);
}
TestFree(pwsz);
}
TestFree(pbEncoded);
}
typedef struct _X500_NAMES {
LPCSTR pszName;
DWORD dwStrType;
DWORD dwErr; // 0 => expect success
int iErrOffset; // -1 => expect NULL pszError
} X500_NAMES, *PX500_NAMES;
// 1 2 3 4 5 6
// 0123456789012345678901234567890123456789012345678901234567890
static const X500_NAMES rgX500Names[] = {
"CN=Joe Cool", 0, 0, -1,
"CN=Joe Cool;", 0, 0, -1,
"CN=Joe Cool,", 0, 0, -1,
"CN=Joe Cool+ ", 0, 0, -1,
"Cn=Joe Cool+T= + ", 0, 0, -1,
"cn=Joe Cool+t= , ", 0, 0, -1,
"cn=\"Joe Cool ,;+\"\"-#\t<>=\"", 0, 0, -1,
"cN=Joe Cool + T = Programmer; OU= Micro , OiD.1.2.3.4=#01 02", 0, 0, -1,
" 1.2.3.4 = # 0123456789abcdef 13 + SN = wow", 0, 0, -1,
"1.2.3.4=\"# 0123456789abcdef 13 string not octet\" + oid.1.2.3.4.1=#0123456789abcdef13 + SN = wow", 0, 0, -1,
"oiD.1.2.3.4.5=#12\t34 \t45 \t 78;1.2.3=#45; 1.2.3.1=#87", 0, 0, -1,
"C=US; L=Internet; St=Washington + Street=Microsoft Way", 0, 0, -1,
"C=U#; L=Internet; Street=Microsoft Way", 0,
(DWORD) CRYPT_E_INVALID_PRINTABLE_STRING, 3,
"[email protected]", 0, 0, -1,
"Email=joe\xB0[email protected]", 0,
(DWORD) CRYPT_E_INVALID_IA5_STRING, 9,
"C=US; OU=Microsoft; St=Way + L= Internet + Email=joe\xB0[email protected]",
0, (DWORD) CRYPT_E_INVALID_IA5_STRING, 53,
"C=US; OU=Microsoft; St=Way + L= Internet + [email protected]",
0, 0, -1,
"Email=\"\"\"Cool\"\" Guy\xB0@microsoft.com\"",
0, (DWORD) CRYPT_E_INVALID_IA5_STRING, 19,
"C=US; OU=Microsoft; St=Way + L= Internet + Email=\"\"\"Cool\"\" Guy\xB0@microsoft.com\"",
0, (DWORD) CRYPT_E_INVALID_IA5_STRING, 64,
"C=US; OU=Microsoft; St=Way + L= Internet + Email=\"\"\"Cool\"\" [email protected]\"",
0, 0, -1,
"T = Numeric ; 2.5.4.24=0123456789 0123456789", 0, 0, -1,
"T = Bad Numeric ; 2.5.4.24=0123456789abcdef 0123456789",
0, (DWORD) CRYPT_E_INVALID_NUMERIC_STRING, 37,
" CN = \" Joe \"\"Cool\"\"\" ", 0, 0, -1,
" CN = \" Joe \"\"Cool\"\" \" ;T=quoted lead and trail spaces ",
0, 0, -1,
"CN = Joe \"Cool\" ", (DWORD) CERT_NAME_STR_NO_QUOTING_FLAG, 0, -1,
"CN=Joe \"\"Cool\"\" ", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 7,
" CN = \"Joe \"\"Cool\"\" ", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 9,
"CM=Joe Cool", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 0,
"Cn=Joe Cool, Ox=wrong",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 13,
"OID.1.2=#01 02 g", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 8,
"1.2=# ; T= empty ascii hex", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 4,
"OID.1.2=#00; OID.1..3.1=#01; T=Consecutive dots",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 13,
"1.2=#f; T= Odd ascii hex", 0, 0, -1,
"1.2=#12e; T= Odd ascii hex", 0, 0, -1,
"CN = Joe, Cool ; OU = Microsoft, xyz; T=CERT_NAME_STR_SEMICOLON_FLAG",
CERT_NAME_STR_SEMICOLON_FLAG, 0, -1,
"CN = Joe, Cool ; OU = Microsoft, xyz",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 10,
"CN = Joe; Cool , OU = Microsoft; xyz, T=CERT_NAME_STR_COMMA_FLAG",
CERT_NAME_STR_COMMA_FLAG, 0, -1,
"CN = Joe; Cool , OU = Microsoft; xyz",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 10,
"CN = Joe, Cool ; More stuff \n OU = Microsoft; xyz \nT=CERT_NAME_STR_CRLF_FLAG",
CERT_NAME_STR_CRLF_FLAG, 0, -1,
"CN = Joe, Cool ; More stuff \n OU = Microsoft; xyz",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 10,
"CN = Joe Cool + more cool ; L= Wa + more local; T=CERT_NAME_STR_NO_PLUS_FLAG",
CERT_NAME_STR_NO_PLUS_FLAG, 0, -1,
"CN = Joe Cool + more cool ; L= Wa + more local;",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 16,
"CN = Joe Cool , OU = Microsoft xyz T=IgnoredEqualDelimiter",
0, 0, -1,
"CN = Joe Cool; T=CERT_SIMPLE_NAME_STR",
CERT_SIMPLE_NAME_STR, (DWORD) E_INVALIDARG, -1,
"CN=xyz; =; T=EmptyX500Key",
0, (DWORD) CRYPT_E_INVALID_X500_STRING, 8,
"O", 0, (DWORD) CRYPT_E_INVALID_X500_STRING, 0,
"", 0, 0, -1
};
#define NX500NAMES (sizeof(rgX500Names) / sizeof(rgX500Names[0]))
static void ParsePredefinedX500Names()
{
// Note, fffe and ffff aren't valid UTF8 characters
LPWSTR pwszUnicodeName =
L"DC=microsoft, "
L"DC=com, "
L"DC=\x0001 \x0002 \x007e \x007f, "
L"DC=\x0080 \x0081 \x07fe \x07ff, "
L"DC=\x0800 \x0801 \xfffc \xfffd, "
L"CN=UNICODE, "
L"OID.1.2.3.1=\x0001 \x0002 \x007e \x007f, "
L"OID.1.2.3.2=\x0080 \x0081 \x07fe \x07ff, "
L"OID.1.2.3.3=\x0800 \x0801 \xfffc \xfffd"
;
WCHAR rgwszUnicode[3 + 1 + 0xFFFC + 1 + 1 + 1];
DWORD i;
DWORD j;
wcscpy(rgwszUnicode, L"CN=\"");
j = 4;
for (i = 1; i <= 0xFF; i++) {
rgwszUnicode[j++] = (WCHAR) i;
if ((WCHAR) i == L'\"')
rgwszUnicode[j++] = L'\"';
}
for (i = 0x7E0; i <= 0x820; i++)
rgwszUnicode[j++] = (WCHAR) i;
for (i = 0xFFE0; i <= 0xFFFD; i++)
rgwszUnicode[j++] = (WCHAR) i;
rgwszUnicode[j] = L'\0';
wcscat(rgwszUnicode, L"\"");
for (i = 0; i < NX500NAMES; i++)
ParseX500Name(
rgX500Names[i].pszName,
rgX500Names[i].dwStrType,
rgX500Names[i].dwErr,
rgX500Names[i].iErrOffset
);
for (i = 0; i < NX500NAMES; i++)
ParseX500Name(
rgX500Names[i].pszName,
rgX500Names[i].dwStrType | CERT_NAME_STR_REVERSE_FLAG,
rgX500Names[i].dwErr,
rgX500Names[i].iErrOffset
);
ParseUnicodeX500Name(pwszUnicodeName, 0);
ParseUnicodeX500Name(pwszUnicodeName,
CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG);
ParseUnicodeX500Name(pwszUnicodeName,
CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG |
CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG);
ParseUnicodeX500Name(pwszUnicodeName,
CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG);
ParseUnicodeX500Name(pwszUnicodeName,
CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG |
CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG);
ParseUnicodeX500Name(rgwszUnicode, 0);
ParseUnicodeX500Name(rgwszUnicode,
CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG);
ParseUnicodeX500Name(rgwszUnicode,
CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG |
CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG);
}
static void ParseX500Name(
IN LPCSTR pszName,
IN DWORD dwStrType,
IN DWORD dwExpectedErr,
IN int iExpectedErrOffset
)
{
BOOL fResult;
DWORD i;
BYTE *pbEncoded;
DWORD cbEncoded;
LPCSTR pszError;
printf("<%s>\n", pszName);
fResult = CertStrToNameA(
dwCertEncodingType,
pszName,
dwStrType,
NULL, // pvReserved
NULL, // pbEncoded
&cbEncoded,
&pszError
);
if (!fResult) {
DWORD dwErr = GetLastError();
if (0 == dwExpectedErr)
printf(" failed => unexpected error %d 0x%x\n", dwErr, dwErr);
else if (dwErr != dwExpectedErr)
printf(" failed => expected error %d 0x%x got %d 0x%x\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
if (pszError) {
int iErrOffset = (int)(INT_PTR) (pszError - pszName);
LPSTR pszNameErr = (LPSTR) _alloca(iErrOffset + 1 + 1);
memcpy(pszNameErr, pszName, iErrOffset + 1);
pszNameErr[iErrOffset + 1] = '\0';
printf(" Error at offset %d <%s\n", iErrOffset, pszNameErr);
if (iExpectedErrOffset < 0)
printf(" failed => unexpected error offset\n");
else if (iExpectedErrOffset != iErrOffset)
printf(" failed => expected error offset %d\n",
iExpectedErrOffset);
} else if (iExpectedErrOffset >= 0)
printf(" failed => expected error offset %d\n",
iExpectedErrOffset);
} else if (dwExpectedErr)
printf(" failed => expected error %d 0x%x\n",
dwExpectedErr, dwExpectedErr);
else {
if (NULL == (pbEncoded = (BYTE *) TestAlloc(cbEncoded)))
return;
if (!CertStrToNameA(
dwCertEncodingType,
pszName,
dwStrType,
NULL, // pvReserved
pbEncoded,
&cbEncoded,
&pszError
))
PrintLastError("CertStrToName");
else {
if (pszError != NULL)
printf(" failed => expected NULL pszError\n");
if (fVerbose)
DecodeName(pbEncoded, cbEncoded, dwStrType);
}
TestFree(pbEncoded);
}
}
static LPWSTR NameToStr(
IN PCERT_NAME_BLOB pName,
IN DWORD dwStrType
)
{
DWORD cwsz;
LPWSTR pwsz;
cwsz = CertNameToStrW(
dwCertEncodingType,
pName,
dwStrType,
NULL, // pwsz
0); // cwsz
if (cwsz <= 1) {
PrintLastError("CertNameToStr");
return NULL;
}
if (pwsz = (LPWSTR) TestAlloc(cwsz * sizeof(WCHAR))) {
cwsz = CertNameToStrW(
dwCertEncodingType,
pName,
dwStrType,
pwsz,
cwsz);
}
return pwsz;
}
static BOOL StrToName(
IN LPCWSTR pwszName,
IN DWORD dwStrType,
OUT PCERT_NAME_BLOB pName
)
{
BOOL fResult;
LPCWSTR pwszError;
memset(pName, 0, sizeof(*pName));
fResult = CertStrToNameW(
dwCertEncodingType,
pwszName,
dwStrType,
NULL, // pvReserved
NULL, // pbEncoded
&pName->cbData,
&pwszError
);
if (!fResult) {
PrintLastError("CertStrToNameW");
if (pwszError) {
int iErrOffset = (int)(INT_PTR) (pwszError - pwszName);
LPWSTR pwszNameErr = (LPWSTR) _alloca((iErrOffset + 1 + 1) * 2);
memcpy(pwszNameErr, pwszName, (iErrOffset + 1) * 2);
pwszNameErr[iErrOffset + 1] = L'\0';
printf("Error at <%S\n", pwszNameErr);
}
return FALSE;
}
if (NULL == (pName->pbData = (BYTE *) TestAlloc(pName->cbData)))
return FALSE;
fResult = CertStrToNameW(
dwCertEncodingType,
pwszName,
dwStrType,
NULL, // pvReserved
pName->pbData,
&pName->cbData,
NULL // pwszError
);
if (!fResult) {
PrintLastError("CertStrToNameW");
TestFree(pName->pbData);
pName->pbData = NULL;
return FALSE;
}
return TRUE;
}
static void FormatAndParseName(
IN PCERT_NAME_BLOB pName,
IN DWORD dwStrType
)
{
LPWSTR pwszName = NULL;
CERT_NAME_BLOB Name2;
memset(&Name2, 0, sizeof(Name2));
LPWSTR pwszName2 = NULL;
pwszName = NameToStr(pName, dwStrType);
if (NULL == pwszName)
goto ErrorReturn;
printf("<%S>\n", pwszName);
if (!StrToName(pwszName, dwStrType, &Name2))
goto ErrorReturn;
pwszName2 = NameToStr(&Name2, dwStrType);
if (NULL == pwszName2)
goto ErrorReturn;
if (wcslen(pwszName) != wcslen(pwszName2) ||
0 != wcscmp(pwszName, pwszName2)) {
printf("failed => re-formatted name mismatch\n");
printf("Re-formatted::\n");
printf("<%S>\n", pwszName2);
}
if (pName->cbData != Name2.cbData ||
0 != memcmp(pName->pbData, Name2.pbData, Name2.cbData)) {
printf("failed => re-encoded name mismatch\n");
printf("Input::\n");
PrintBytes(" ", pName->pbData, pName->cbData);
DecodeName(pName->pbData, pName->cbData, 0xFFFFFFFF);
printf("Re-encoded::\n");
PrintBytes(" ", Name2.pbData, Name2.cbData);
DecodeName(Name2.pbData, Name2.cbData, 0xFFFFFFFF);
}
ErrorReturn:
if (pwszName)
TestFree(pwszName);
if (pwszName2)
TestFree(pwszName2);
if (Name2.pbData)
TestFree(Name2.pbData);
}
static void FormatAndParseCertNames(
IN LPCSTR pszCertFilename,
IN DWORD dwStrType,
IN BOOL fSubject
)
{
CERT_BLOB Cert;
PCCERT_CONTEXT pCertContext = NULL;
PCERT_NAME_BLOB pName;
static DWORD rgdwStrType[] = {
CERT_OID_NAME_STR,
CERT_X500_NAME_STR,
CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG |
CERT_NAME_STR_NO_QUOTING_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_NO_QUOTING_FLAG |
CERT_NAME_STR_CRLF_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG |
CERT_NAME_STR_DISABLE_IE4_UTF8_FLAG,
CERT_X500_NAME_STR | CERT_NAME_STR_ENABLE_UTF8_UNICODE_FLAG,
0
};
DWORD *pdwStrType;
if (!ReadDERFromFile(pszCertFilename, &Cert.pbData, &Cert.cbData))
return;
if (NULL == (pCertContext = CertCreateCertificateContext(
dwCertEncodingType, Cert.pbData, Cert.cbData))) {
PrintLastError("CertCreateCertificateContext");
goto ErrorReturn;
}
if (fSubject) {
printf("Subject::\n");
pName = &pCertContext->pCertInfo->Subject;
} else {
printf("Issuer::\n");
pName = &pCertContext->pCertInfo->Issuer;
}
if (fVerbose)
DecodeName(pName->pbData, pName->cbData, 0xFFFFFFFF);
if (dwStrType != 0xFFFFFFFF) {
if (dwStrType == 0)
dwStrType = CERT_X500_NAME_STR;
FormatAndParseName(pName, dwStrType);
} else {
pdwStrType = rgdwStrType;
while (dwStrType = *pdwStrType++) {
FormatAndParseName(pName, dwStrType);
printf("\n");
}
}
ErrorReturn:
CertFreeCertificateContext(pCertContext);
TestFree(Cert.pbData);
}
static void GetCertNameFromFile(
IN LPCSTR pszCertFilename,
IN DWORD dwGetNameStringType,
IN LPSTR pszAttrOID,
IN DWORD dwStrType,
IN BOOL fSubject,
IN DWORD dwExpectedErr
)
{
CERT_BLOB Cert;
PCCERT_CONTEXT pCertContext = NULL;
LPWSTR pwsz = NULL;
LPSTR psz = NULL;
DWORD cch;
DWORD dwFlags;
void *pvTypePara;
dwFlags = dwGetNameStringType & 0xFFFF0000;
dwGetNameStringType &= 0x0000FFFF;
switch (dwGetNameStringType) {
case CERT_NAME_RDN_TYPE:
pvTypePara = &dwStrType;
break;
case CERT_NAME_ATTR_TYPE:
pvTypePara = pszAttrOID;
break;
default:
pvTypePara = NULL;
}
if (!ReadDERFromFile(pszCertFilename, &Cert.pbData, &Cert.cbData))
return;
if (NULL == (pCertContext = CertCreateCertificateContext(
dwCertEncodingType, Cert.pbData, Cert.cbData))) {
PrintLastError("CertCreateCertificateContext");
goto ErrorReturn;
}
if (fSubject) {
printf("Unicode Subject::\n");
dwFlags |= 0;
} else {
printf("Unicode Issuer::\n");
dwFlags |= CERT_NAME_ISSUER_FLAG;
}
cch = CertGetNameStringW(
pCertContext,
dwGetNameStringType,
dwFlags,
pvTypePara,
NULL, // pwsz
0); // cch
if (cch <= 1) {
DWORD dwErr = GetLastError();
printf(" CertGetNameStringW returned empty string\n");
if (0 == dwExpectedErr)
printf(" failed => unexpected error %d 0x%x\n", dwErr, dwErr);
else if (dwErr != dwExpectedErr)
printf(" failed => expected error %d 0x%x got %d 0x%x\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
} else if (dwExpectedErr)
printf(" failed => expected error %d 0x%x\n",
dwExpectedErr, dwExpectedErr);
else if (pwsz = (LPWSTR) TestAlloc(cch * sizeof(WCHAR))) {
cch = CertGetNameStringW(
pCertContext,
dwGetNameStringType,
dwFlags,
pvTypePara,
pwsz,
cch);
printf(" <%S>\n", pwsz);
}
if (!fVerbose)
goto CommonReturn;
if (fSubject) {
printf("ASCII Subject::\n");
dwFlags = 0;
} else {
printf("ASCII Issuer::\n");
dwFlags = CERT_NAME_ISSUER_FLAG;
}
cch = CertGetNameStringA(
pCertContext,
dwGetNameStringType,
dwFlags,
pvTypePara,
NULL, // psz
0); // cch
if (cch <= 1) {
DWORD dwErr = GetLastError();
printf(" CertGetNameStringA returned empty string\n");
if (0 == dwExpectedErr)
printf(" failed => unexpected error %d 0x%x\n", dwErr, dwErr);
else if (dwErr != dwExpectedErr)
printf(" failed => expected error %d 0x%x got %d 0x%x\n",
dwExpectedErr, dwExpectedErr, dwErr, dwErr);
} else if (dwExpectedErr)
printf(" failed => expected error %d 0x%x\n",
dwExpectedErr, dwExpectedErr);
else if (psz = (LPSTR) TestAlloc(cch)) {
cch = CertGetNameStringA(
pCertContext,
dwGetNameStringType,
dwFlags,
pvTypePara,
psz,
cch);
printf(" <%s>\n", psz);
}
CommonReturn:
ErrorReturn:
CertFreeCertificateContext(pCertContext);
TestFree(Cert.pbData);
TestFree(pwsz);
TestFree(psz);
}