windows-nt/Source/XPSP1/NT/ds/security/services/ca/certlib/check7f.cpp
2020-09-26 16:20:57 +08:00

908 lines
20 KiB
C++

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: check7f.cpp
//
// Contents: Cert Server test for ASN-encoded 7f length
//
//---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <stdlib.h>
#include <assert.h>
#include "csdisp.h"
typedef struct _ASNTABLE {
WORD State;
WORD Flags;
WCHAR const *pwszElement;
} ASNTABLE;
#define BOOLEAN_TAG 0x01
#define INTEGER_TAG 0x02
#define BIT_STRING_TAG 0x03
#define OCTET_STRING_TAG 0x04
#define NULL_TAG 0x05
#define OBJECT_ID_TAG 0x06
#define SET_OF_TAG 0x11
#define PRINTABLE_STRING_TAG 0x13
#define TELETEX_STRING_TAG 0x14
#define CHAR_STRING_TAG 0x16
#define UTCTIME_TAG 0x17
#define SEQUENCE_TAG 0x30
#define RDN_TAG 0x31
#define PRIMITIVE_TAG 0x80
#define ATTRIBUTE_TAG 0xa0
#define BEG_REPEAT1 0x00000100 // begin repeat section
#define BEG_REPEAT2 0x00000200 // begin nested repeat section
#define END_REPEAT1 0x00000400 // 'or' in back step count
#define END_REPEAT2 0x00000800 // 'or' in back step count
#define OPTIONAL_FIELD 0x00001000 // begin optional field
#define ANY_TAG 0x00002000 // match any tag
const ASNTABLE asnCert[] = {
{ CHECK7F_OTHER, SEQUENCE_TAG, L"Certificate" },
{ CHECK7F_OTHER, SEQUENCE_TAG, L".ToBeSigned" },
{ CHECK7F_OTHER, ATTRIBUTE_TAG | OPTIONAL_FIELD, L"..Version" },
{ CHECK7F_OTHER, INTEGER_TAG , L"...Version.Integer" },
{ CHECK7F_OTHER, INTEGER_TAG, L"..SerialNumber" },
{ CHECK7F_OTHER, SEQUENCE_TAG, L"..SignatureAlgorithm" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L"...SignatureAlgorithm.ObjectId" },
{ CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"...SignatureAlgorithm.Parameters" },
{ CHECK7F_ISSUER, SEQUENCE_TAG, L"..Issuer Name" },
{ CHECK7F_ISSUER_RDN,
BEG_REPEAT1 | RDN_TAG | OPTIONAL_FIELD, L"...Issuer.RDN" },
{ CHECK7F_ISSUER_RDN_ATTRIBUTE,
BEG_REPEAT2 | SEQUENCE_TAG, L"....Issuer.RDN.Attribute" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L".....Issuer.RDN.Attribute.ObjectId" },
{ CHECK7F_ISSUER_RDN_STRING, ANY_TAG, L".....Issuer.RDN.Attribute.Value" },
{ 0, END_REPEAT2 | 3, L"...." },
{ 0, END_REPEAT1 | 5, L"..." },
{ CHECK7F_OTHER, SEQUENCE_TAG, L"..Dates" },
{ CHECK7F_OTHER, UTCTIME_TAG, L"...Dates.NotBefore" },
{ CHECK7F_OTHER, UTCTIME_TAG, L"...Dates.NotAfter" },
{ CHECK7F_SUBJECT, SEQUENCE_TAG, L"..Subject Name" },
{ CHECK7F_SUBJECT_RDN,
BEG_REPEAT1 | RDN_TAG | OPTIONAL_FIELD, L"...Subject.RDN" },
{ CHECK7F_SUBJECT_RDN_ATTRIBUTE,
BEG_REPEAT2 | SEQUENCE_TAG, L"....Subject.RDN.Attribute" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L".....Subject.RDN.Attribute.ObjectId" },
{ CHECK7F_SUBJECT_RDN_STRING, ANY_TAG, L".....Subject.RDN.Attribute.Value" },
{ 0, END_REPEAT2 | 3, L"...." },
{ 0, END_REPEAT1 | 5, L"..." },
{ CHECK7F_OTHER, SEQUENCE_TAG, L"..PublicKey" },
{ CHECK7F_OTHER, SEQUENCE_TAG, L"...PublicKey.Algorithm" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L"....PublicKey.Algorithm.ObjectId" },
{ CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"....PublicKey.Algorithm.Parameters" },
{ CHECK7F_OTHER, BIT_STRING_TAG, L"...PublicKey.Key" },
{ CHECK7F_OTHER,
PRIMITIVE_TAG | 1 | OPTIONAL_FIELD, L"..IssuerUniqueId" },
{ CHECK7F_OTHER,
PRIMITIVE_TAG | 2 | OPTIONAL_FIELD, L"..SubjectUniqueId" },
{ CHECK7F_EXTENSIONS,
ATTRIBUTE_TAG | 3 | OPTIONAL_FIELD, L"..Extensions" },
{ CHECK7F_EXTENSION_ARRAY, SEQUENCE_TAG, L"...Extensions.Array" },
{ CHECK7F_EXTENSION,
BEG_REPEAT1 | SEQUENCE_TAG, L"....Extensions.Array.Extension" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L".....Extensions.Array.Extension.ObjectId" },
{ CHECK7F_OTHER, BOOLEAN_TAG | OPTIONAL_FIELD, L".....Extensions.Array.Extension.Critical" },
{ CHECK7F_EXTENSION_VALUE, OCTET_STRING_TAG, L".....Extensions.Array.Extension.Value" },
//{ CHECK7F_EXTENSION_VALUE_RAW, ANY_TAG, L"......Extensions.Array.Extension.Value.Bits" },
{ 0, END_REPEAT1 | 4, L"...." },
{ CHECK7F_OTHER, SEQUENCE_TAG, L".SignatureAlogorithm" },
{ CHECK7F_OTHER, OBJECT_ID_TAG, L"..SignatureAlgorithm.ObjectId" },
{ CHECK7F_OTHER, ANY_TAG | OPTIONAL_FIELD, L"..SignatureAlgorithm.Parameters" },
{ CHECK7F_OTHER, BIT_STRING_TAG, L".Signature" },
{ 0, 0, NULL }
};
#define cbOLDCERTENROLLCHOKESLENGTH 0x7f
// DecodeLength decodes an ASN1 encoded length field. The pbEncoded parameter
// is the encoded length. pdwLen is used to return the length. The function
// returns a -1 if it fails and otherwise returns the number of total bytes in
// the encoded length.
long
DecodeLength(
BOOL fVerbose,
DWORD *pdwLen,
DWORD iLevel,
BYTE const *pbBase,
BYTE const *pbEncoded,
DWORD cbEncoded,
WCHAR const *pwsz)
{
long index = 0;
BYTE count;
assert(NULL != pdwLen);
assert(NULL != pbEncoded);
if (1 > cbEncoded)
{
DBGPRINT((DBG_SS_CERTLIB, "cbEncoded overflow %d\n", cbEncoded));
return(-1);
}
// determine the length of the length field
count = pbEncoded[0];
if (0x80 < count)
{
// If there is more than one byte in the length field, then the lower
// seven bits tells us the number of bytes.
count &= 0x7f;
// This function only allows the length field to be 2 bytes. If the
// field is longer, then the function fails.
if (2 < count)
{
DBGPRINT((DBG_SS_CERTLIB, "Length field reported to be over 2 bytes\n"));
return(-1);
}
if (count > cbEncoded)
{
DBGPRINT((DBG_SS_CERTLIB, "cbEncoded overflow %d\n", cbEncoded));
return(-1);
}
*pdwLen = 0;
// go through the bytes of the length field
for (index = 1; index <= count; index++)
{
*pdwLen = (*pdwLen << 8) + pbEncoded[index];
}
}
else // the length field is just one byte long
{
*pdwLen = pbEncoded[0];
index = 1;
}
// return how many bytes there were in the length field.
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT7((
DBG_SS_CERTLIB,
"asn %u:@%x: %02x, len %x, cbEncoded %x, end @%x, %ws\n",
iLevel,
&pbEncoded[-1] - pbBase,
pbEncoded[-1],
*pdwLen,
cbEncoded + 1,
&pbEncoded[-1] - pbBase + cbEncoded + 1,
pwsz));
}
#endif // DBG_CERTSRV
return(index);
}
WCHAR const *
GetLevel(
OPTIONAL IN WCHAR const *pwszField,
OUT DWORD *piLevel)
{
DWORD iLevel = 0;
iLevel = 0;
if (NULL != pwszField)
{
while ('.' == *pwszField)
{
iLevel++;
pwszField++;
}
}
*piLevel = iLevel;
return(pwszField);
}
BOOL
RestoreLevel(
IN DWORD *acbLevel,
IN DWORD iLevelNext,
IN DWORD *piLevel,
IN BOOL fVerbose)
{
BOOL fOk = FALSE;
DWORD iLevel;
DWORD i = *piLevel;
#if DBG_CERTSRV
if (1 < fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIBI,
"RestoreLevel(%x, %x)\n",
iLevelNext,
*piLevel));
}
#endif
iLevel = *piLevel;
while (0 < iLevel && 0 == acbLevel[iLevel] && iLevelNext < iLevel)
{
iLevel--;
if (1 < fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIBI,
"Restoring length(%u) ==> %x\n",
iLevel,
acbLevel[iLevel]));
}
}
if (iLevelNext < iLevel)
{
CONSOLEPRINT2((
MAXDWORD,
"BAD RESTORED LENGTH[%u]: 0 < %x\n",
iLevel,
acbLevel[iLevel]));
goto error;
}
*piLevel = iLevel;
fOk = TRUE;
error:
if (1 < fVerbose)
{
CONSOLEPRINT4((
DBG_SS_CERTLIBI,
"RestoreLevel(%x, %x --> %x) --> %x\n",
iLevelNext,
i,
*piLevel,
fOk));
}
return(fOk);
}
VOID
ReturnString(
IN WCHAR const *pwszReturn,
OPTIONAL IN OUT DWORD *pcwcBuf,
OPTIONAL OUT WCHAR *pwcBuf)
{
DWORD cwcNeeded = wcslen(pwszReturn) + 1;
DWORD cwcBuf;
if (NULL != pcwcBuf)
{
cwcBuf = *pcwcBuf;
if (NULL != pwcBuf && 0 < cwcBuf)
{
CopyMemory(pwcBuf, pwszReturn, sizeof(WCHAR) * min(cwcBuf, cwcNeeded));
pwcBuf[cwcBuf - 1] = L'\0';
}
*pcwcBuf = cwcNeeded;
}
}
#define MATCHTAG(b, flags) ((ANY_TAG & (flags)) || (b) == (BYTE) (flags))
HRESULT
myCheck7f(
IN const BYTE *pbCert,
IN DWORD cbCert,
IN BOOL fVerbose,
OUT DWORD *pState,
OPTIONAL OUT DWORD *pIndex1,
OPTIONAL OUT DWORD *pIndex2,
OPTIONAL IN OUT DWORD *pcwcField,
OPTIONAL OUT WCHAR *pwszField,
OPTIONAL IN OUT DWORD *pcwcObjectId,
OPTIONAL OUT WCHAR *pwszObjectId,
OPTIONAL OUT WCHAR const **ppwszObjectIdDescription)
{
ASNTABLE const *pasn;
HRESULT hr = S_OK;
BOOL fSaveCert = TRUE;
BYTE const *pb = pbCert;
long index;
DWORD length;
DWORD acbLevel[20];
DWORD iLevel;
DWORD iLevelNext;
WCHAR const *pwszfieldname;
DWORD cbdiff;
DWORD aiElement[20];
DWORD aiElement7f[2];
DWORD iElementLevel;
DWORD State;
BOOL fSetField = FALSE;
BOOL fSetObjectId = FALSE;
CERT_INFO *pCertInfo = NULL;
DWORD cbCertInfo;
CERT_NAME_INFO *pNameInfo = NULL;
DWORD cbNameInfo;
WCHAR *pwszObjId = NULL;
State = CHECK7F_NONE;
if (NULL != ppwszObjectIdDescription)
{
*ppwszObjectIdDescription = NULL;
}
#if DBG_CERTSRV
if (!fVerbose && DbgIsSSActive(DBG_SS_CERTLIBI))
{
fVerbose = TRUE;
}
#endif // DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT1((MAXDWORD, "myCheck7f: %x bytes\n", cbCert));
}
pasn = asnCert;
iLevel = 0;
ZeroMemory(aiElement7f, sizeof(aiElement7f));
acbLevel[iLevel] = cbCert;
iElementLevel = 0;
while (0 != iLevel || (0 != acbLevel[iLevel] && NULL != pasn->pwszElement))
{
DWORD i;
if (1 < fVerbose)
{
if (2 < fVerbose)
{
CONSOLEPRINT3((
DBG_SS_CERTLIBI,
"ASN:0: *pb=%x %u: %ws\n",
*pb,
pasn - asnCert,
pasn->pwszElement));
}
CONSOLEPRINT0((MAXDWORD, "LENGTHS:0:"));
for (i = 0; i <= iLevel; i++)
{
CONSOLEPRINT1((MAXDWORD, " %3x", acbLevel[i]));
}
CONSOLEPRINT0((MAXDWORD, "\n"));
}
while (OPTIONAL_FIELD & pasn->Flags)
{
DWORD f;
if (0 < acbLevel[iLevel] && MATCHTAG(*pb, pasn->Flags))
{
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIB,
"Optional field MATCH cb=%x %ws\n",
acbLevel[iLevel],
pasn->pwszElement));
}
#endif // DBG_CERTSRV
break;
}
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIB,
"Optional field NO match cb=%x %ws\n",
acbLevel[iLevel],
pasn->pwszElement));
}
#endif // DBG_CERTSRV
f = 0;
switch ((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags)
{
case BEG_REPEAT1:
f = END_REPEAT1;
break;
case BEG_REPEAT2:
f = END_REPEAT2;
break;
}
if (f)
{
while (!(f & pasn->Flags))
{
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIB,
"Skipping[%x] %ws\n",
f,
pasn->pwszElement));
}
#endif // DBG_CERTSRV
pasn++;
}
}
else
{
DWORD iLevelCurrent;
GetLevel(pasn->pwszElement, &iLevelCurrent);
while (TRUE)
{
GetLevel(pasn[1].pwszElement, &iLevelNext);
if (iLevelNext <= iLevelCurrent)
{
break;
}
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT1((
DBG_SS_CERTLIB,
"Skipping nested optional field %ws\n",
pasn->pwszElement));
}
#endif // DBG_CERTSRV
pasn++;
}
}
#if DBG_CERTSRV
if (fVerbose)
{
CONSOLEPRINT1((
DBG_SS_CERTLIB,
"Skipping optional field %ws\n",
pasn->pwszElement));
}
#endif // DBG_CERTSRV
pasn++;
if (0 == acbLevel[iLevel])
{
GetLevel(pasn->pwszElement, &iLevelNext);
if (iLevelNext < iLevel)
{
iLevel = iLevelNext;
}
}
}
while ((END_REPEAT1 | END_REPEAT2) & pasn->Flags)
{
// Make sure only one END_REPEAT bit is on.
assert(
(END_REPEAT1 | END_REPEAT2) !=
((END_REPEAT1 | END_REPEAT2) & pasn->Flags));
pwszfieldname = GetLevel(pasn->pwszElement, &iLevelNext);
if (!RestoreLevel(acbLevel, iLevelNext, &iLevel, fVerbose))
{
goto error;
}
i = (BYTE) pasn->Flags;
assert((DWORD) (pasn - asnCert) > i);
if (0 != acbLevel[iLevel])
{
if (!MATCHTAG(*pb, (pasn - i)->Flags))
{
CONSOLEPRINT5((
MAXDWORD,
"Check7f: Unexpected tag at %x: at level %u: (%x/%x) %ws\n",
cbCert - acbLevel[0],
iLevel,
*pb,
pasn->Flags,
pasn->pwszElement));
goto error;
}
// Some data remain at this level, and the type tag matches
// the expected repeat tag, loop back to the start of the
// section to be repeated.
pasn -= i;
// Make sure only one BEG_REPEAT bit is on.
assert(
(BEG_REPEAT1 | BEG_REPEAT2) !=
((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags));
// Make sure the BEG_REPEAT bit in the begin record matches
// the END_REPEAT bit in the end record.
assert(
((BEG_REPEAT1 & pasn->Flags) &&
(END_REPEAT1 & pasn[i].Flags)) ||
((BEG_REPEAT2 & pasn->Flags) &&
(END_REPEAT2 & pasn[i].Flags)));
}
else
{
pasn++;
iElementLevel--;
}
}
if (2 < fVerbose)
{
CONSOLEPRINT3((
DBG_SS_CERTLIBI,
"ASN:1: *pb=%x %u: %ws\n",
*pb,
pasn - asnCert,
pasn->pwszElement));
}
if ((BEG_REPEAT1 | BEG_REPEAT2) & pasn->Flags)
{
if ((BEG_REPEAT1 & pasn->Flags) && 0 == iElementLevel ||
(BEG_REPEAT2 & pasn->Flags) && 1 == iElementLevel)
{
iElementLevel++;
aiElement[iElementLevel] = 0;
}
aiElement[iElementLevel]++;
}
pwszfieldname = GetLevel(pasn->pwszElement, &iLevelNext);
if (!RestoreLevel(acbLevel, iLevelNext, &iLevel, fVerbose))
{
goto error;
}
if (1 < fVerbose)
{
CONSOLEPRINT0((MAXDWORD, "LENGTHS:1:"));
for (i = 0; i <= iLevel; i++)
{
CONSOLEPRINT1((MAXDWORD, " %3x", acbLevel[i]));
}
CONSOLEPRINT0((MAXDWORD, "\n"));
}
if (0 == iLevel && 0 == acbLevel[0])
{
break; // all done!
}
if (!MATCHTAG(*pb, pasn->Flags))
{
CONSOLEPRINT5((
MAXDWORD,
"Check7f: Unexpected tag at %x: at level %u: (%x/%x) %ws\n",
cbCert - acbLevel[0],
iLevel,
*pb,
pasn->Flags,
pasn->pwszElement));
goto error;
}
GetLevel(pasn[1].pwszElement, &iLevelNext);
index = DecodeLength(
fVerbose,
&length,
iLevel,
pbCert,
&pb[1],
acbLevel[iLevel] - 1,
pasn->pwszElement);
if (fVerbose)
{
DWORD ccol;
char achdbg[128];
char *pchdbg;
//char achbuf[10];
pchdbg = achdbg;
pchdbg += sprintf(pchdbg, "%04x:", pb - pbCert);
for (i = 0; i <= iLevel; i++)
{
pchdbg += sprintf(pchdbg, " %3x", acbLevel[i]);
}
pchdbg += sprintf(pchdbg, " (%x)", length);
ccol = SAFE_SUBTRACT_POINTERS(pchdbg, achdbg);
if (ccol > 34)
{
ccol = 34;
}
pchdbg += sprintf(pchdbg, " %*hs -- ", 34 - ccol, "");
assert(2 >= iElementLevel);
if (1 == iElementLevel)
{
pchdbg += sprintf(pchdbg, "[%u]:", aiElement[1] - 1);
}
else if (2 == iElementLevel)
{
pchdbg += sprintf(
pchdbg,
"[%u,%u]:",
aiElement[1] - 1,
aiElement[2] - 1);
}
CONSOLEPRINT2((DBG_SS_CERTLIBI, "%hs%ws\n", achdbg, pwszfieldname));
}
if (length == cbOLDCERTENROLLCHOKESLENGTH)
{
CONSOLEPRINT2((
MAXDWORD,
"Check7f: Length of %ws is %u bytes\n",
pwszfieldname,
length));
if (CHECK7F_NONE == State)
{
ReturnString(pwszfieldname, pcwcField, pwszField);
if (1 <= iElementLevel)
{
aiElement7f[0] = aiElement[1];
}
if (2 <= iElementLevel)
{
aiElement7f[1] = aiElement[2];
}
State = pasn->State;
fSetField = TRUE;
}
}
if (1 < fVerbose)
{
CONSOLEPRINT6((
DBG_SS_CERTLIBI,
"index=%x len=%x level=%x->%x acb[%x]=%x\n",
index,
length,
iLevel,
iLevelNext,
iLevel,
acbLevel[iLevel]));
}
if (0 > index || index + length > acbLevel[iLevel])
{
CONSOLEPRINT2((
MAXDWORD,
"Check7f: BAD LENGTH: i=%x l=%x\n",
index,
length));
goto error;
}
cbdiff = index + 1;
if (iLevelNext > iLevel)
{
assert(iLevel + 1 == iLevelNext);
}
else
{
cbdiff += length;
}
for (i = 0; i <= iLevel; i++)
{
if (acbLevel[i] < cbdiff)
{
CONSOLEPRINT3((
MAXDWORD,
"Check7f: BAD NESTED LENGTH[%u]: %x < %x\n",
i,
acbLevel[i],
cbdiff));
goto error;
}
acbLevel[i] -= cbdiff;
}
if (iLevelNext > iLevel)
{
iLevel++;
if (1 < fVerbose)
{
CONSOLEPRINT2((
DBG_SS_CERTLIBI,
"Saving length(%u) <== %x\n",
iLevel,
length));
}
acbLevel[iLevel] = length;
}
pb += cbdiff;
pasn++;
}
*pIndex1 = 0;
if (0 != iLevel || 0 != acbLevel[iLevel] || NULL != pasn->pwszElement)
{
CONSOLEPRINT3((
MAXDWORD,
"Check7f: Mismatch: %x bytes left at: %x: %ws\n",
acbLevel[iLevel],
cbCert - acbLevel[0],
pasn->pwszElement));
}
else if (!fSetField)
{
fSaveCert = FALSE;
}
if (fSetField && NULL != pcwcObjectId)
{
char const *pszObjId;
CERT_NAME_BLOB const *pNameBlob;
// Decode certificate
cbCertInfo = 0;
if (!myDecodeObject(
X509_ASN_ENCODING,
X509_CERT_TO_BE_SIGNED,
pbCert,
cbCert,
CERTLIB_USE_LOCALALLOC,
(VOID **) &pCertInfo,
&cbCertInfo))
{
hr = GetLastError();
goto error;
}
pszObjId = NULL;
pNameBlob = NULL;
switch (State)
{
case CHECK7F_ISSUER_RDN:
case CHECK7F_ISSUER_RDN_ATTRIBUTE:
case CHECK7F_ISSUER_RDN_STRING:
pNameBlob = &pCertInfo->Issuer;
break;
case CHECK7F_SUBJECT_RDN:
case CHECK7F_SUBJECT_RDN_ATTRIBUTE:
case CHECK7F_SUBJECT_RDN_STRING:
pNameBlob = &pCertInfo->Subject;
break;
case CHECK7F_EXTENSION:
case CHECK7F_EXTENSION_VALUE:
case CHECK7F_EXTENSION_VALUE_RAW:
if (0 != aiElement7f[0] &&
aiElement7f[0] <= pCertInfo->cExtension)
{
pszObjId =
pCertInfo->rgExtension[aiElement7f[0] - 1].pszObjId;
}
break;
default:
break;
}
if (NULL != pNameBlob)
{
if (!myDecodeName(
X509_ASN_ENCODING,
X509_UNICODE_NAME,
pNameBlob->pbData,
pNameBlob->cbData,
CERTLIB_USE_LOCALALLOC,
&pNameInfo,
&cbNameInfo))
{
hr = GetLastError();
goto error;
}
if (0 != aiElement7f[0] && aiElement7f[0] <= pNameInfo->cRDN)
{
CERT_RDN *pRDN;
pRDN = &pNameInfo->rgRDN[aiElement7f[0] - 1];
if (0 != aiElement7f[1] && aiElement7f[1] <= pRDN->cRDNAttr)
{
pszObjId = pRDN->rgRDNAttr[aiElement7f[1] - 1].pszObjId;
}
}
}
if (NULL != pszObjId)
{
if (!ConvertSzToWsz(&pwszObjId, pszObjId, -1))
{
hr = E_OUTOFMEMORY;
goto error;
}
ReturnString(pwszObjId, pcwcObjectId, pwszObjectId);
fSetObjectId = TRUE;
if (NULL != ppwszObjectIdDescription)
{
WCHAR const *pwszDesc;
pwszDesc = myGetOIDNameA(pszObjId);
if (NULL != pwszDesc && L'\0' != *pwszDesc)
{
*ppwszObjectIdDescription = pwszDesc;
}
}
}
}
error:
if (fSaveCert)
{
EncodeToFileW(
fSetField? L"c:\\7flen.crt" : L"c:\\7fasn.crt",
pbCert,
cbCert,
DECF_FORCEOVERWRITE | CRYPT_STRING_BINARY);
}
if (NULL != pCertInfo)
{
LocalFree(pCertInfo);
}
if (NULL != pNameInfo)
{
LocalFree(pNameInfo);
}
if (NULL != pwszObjId)
{
LocalFree(pwszObjId);
}
*pState = State;
if (NULL != pIndex1)
{
*pIndex1 = aiElement7f[0];
}
if (NULL != pIndex2)
{
*pIndex2 = aiElement7f[1];
}
if (!fSetField && NULL != pcwcField)
{
if (NULL != pwszField && 0 < *pcwcField)
{
pwszField[0] = L'\0';
}
*pcwcField = 0;
}
if (!fSetObjectId && NULL != pcwcObjectId)
{
if (NULL != pwszObjectId && 0 < *pcwcObjectId)
{
pwszObjectId[0] = L'\0';
}
*pcwcObjectId = 0;
}
if (fVerbose)
{
CONSOLEPRINT1((MAXDWORD, "myCheck7f: --> %x\n", hr));
}
return(hr);
}