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.
2634 lines
88 KiB
2634 lines
88 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
|
//
|
|
// File: oidinfo.cpp
|
|
//
|
|
// Contents: Cryptographic Object ID (OID) Info Functions
|
|
//
|
|
// Functions: I_CryptOIDInfoDllMain
|
|
// CryptFindOIDInfo
|
|
// CryptRegisterOIDInfo
|
|
// CryptUnregisterOIDInfo
|
|
// CryptEnumOIDInfo
|
|
// CryptFindLocalizedName
|
|
//
|
|
// Comments:
|
|
//
|
|
// History: 24-May-97 philh created
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "global.hxx"
|
|
#include <dbgdef.h>
|
|
#include "wintrust.h" // wintrust.h is needed for SPC_ oids
|
|
#include "chain.h" // chain.h is needed for ChainRetrieveObjectByUrlW()
|
|
// and ChainIsConnected()
|
|
#include "certca.h" // certca.h is needed for CAOIDGetLdapURL()
|
|
|
|
// Initialized in I_CryptOIDInfoDllMain at ProcessAttach
|
|
static HMODULE hOIDInfoInst;
|
|
|
|
#define MAX_RESOURCE_OID_NAME_LENGTH 256
|
|
static LPCWSTR pwszNullName = L"";
|
|
|
|
#define LEN_ALIGN(Len) ((Len + 7) & ~7)
|
|
|
|
#define CONST_OID_GROUP_PREFIX_CHAR '!'
|
|
#define OID_INFO_ENCODING_TYPE 0
|
|
#define OID_INFO_NAME_VALUE_NAME L"Name"
|
|
#define OID_INFO_ALGID_VALUE_NAME L"Algid"
|
|
#define OID_INFO_EXTRA_INFO_VALUE_NAME L"ExtraInfo"
|
|
#define OID_INFO_FLAGS_VALUE_NAME L"Flags"
|
|
|
|
|
|
|
|
//+=========================================================================
|
|
// OID Information Tables (by GROUP_ID)
|
|
//==========================================================================
|
|
|
|
#define OID_INFO_LEN sizeof(CRYPT_OID_INFO)
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Hash Algorithm Table
|
|
//--------------------------------------------------------------------------
|
|
#define HASH_ALG_ENTRY(pszOID, pwszName, Algid) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_HASH_ALG_OID_GROUP_ID, Algid, 0, NULL
|
|
|
|
static CCRYPT_OID_INFO HashAlgTable[] = {
|
|
HASH_ALG_ENTRY(szOID_OIWSEC_sha1, L"sha1", CALG_SHA1),
|
|
HASH_ALG_ENTRY(szOID_OIWSEC_sha1, L"sha", CALG_SHA1),
|
|
HASH_ALG_ENTRY(szOID_OIWSEC_sha, L"sha", CALG_SHA),
|
|
HASH_ALG_ENTRY(szOID_RSA_MD5, L"md5", CALG_MD5),
|
|
HASH_ALG_ENTRY(szOID_RSA_MD4, L"md4", CALG_MD4),
|
|
HASH_ALG_ENTRY(szOID_RSA_MD2, L"md2", CALG_MD2)
|
|
};
|
|
#define HASH_ALG_CNT (sizeof(HashAlgTable) / sizeof(HashAlgTable[0]))
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Encryption Algorithm Table
|
|
//--------------------------------------------------------------------------
|
|
#define ENCRYPT_ALG_ENTRY(pszOID, pwszName, Algid) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID, \
|
|
Algid, 0, NULL
|
|
|
|
static CCRYPT_OID_INFO EncryptAlgTable[] = {
|
|
ENCRYPT_ALG_ENTRY(szOID_OIWSEC_desCBC, L"des", CALG_DES),
|
|
ENCRYPT_ALG_ENTRY(szOID_RSA_DES_EDE3_CBC, L"3des", CALG_3DES),
|
|
ENCRYPT_ALG_ENTRY(szOID_RSA_RC2CBC, L"rc2", CALG_RC2),
|
|
ENCRYPT_ALG_ENTRY(szOID_RSA_RC4, L"rc4", CALG_RC4),
|
|
#ifdef CMS_PKCS7
|
|
ENCRYPT_ALG_ENTRY(szOID_RSA_SMIMEalgCMS3DESwrap, L"CMS3DESwrap", CALG_3DES),
|
|
ENCRYPT_ALG_ENTRY(szOID_RSA_SMIMEalgCMSRC2wrap, L"CMSRC2wrap", CALG_RC2),
|
|
#endif // CMS_PKCS7
|
|
};
|
|
#define ENCRYPT_ALG_CNT (sizeof(EncryptAlgTable) / sizeof(EncryptAlgTable[0]))
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Public Key Algorithm Table
|
|
//--------------------------------------------------------------------------
|
|
static const DWORD dwMosaicFlags = CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
|
|
CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
|
|
|
|
static const DWORD dwNoNullParaFlag = CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
|
|
|
|
#define PUBKEY_ALG_ENTRY(pszOID, pwszName, Algid) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
|
|
Algid, 0, NULL
|
|
|
|
#define PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, Algid, dwFlags) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
|
|
Algid, sizeof(dwFlags), (BYTE *) &dwFlags
|
|
|
|
#define DSA_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
|
|
PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DSS_SIGN, dwNoNullParaFlag)
|
|
|
|
#define DH_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
|
|
PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DH_SF, dwNoNullParaFlag)
|
|
|
|
#ifdef CMS_PKCS7
|
|
#define ESDH_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
|
|
PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DH_EPHEM, dwNoNullParaFlag)
|
|
#endif // CMS_PKCS7
|
|
|
|
static CCRYPT_OID_INFO PubKeyAlgTable[] = {
|
|
PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA", CALG_RSA_KEYX),
|
|
DSA_PUBKEY_ALG_ENTRY(szOID_X957_DSA, L"DSA"),
|
|
DH_PUBKEY_ALG_ENTRY(szOID_ANSI_X942_DH, L"DH"),
|
|
PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA_KEYX", CALG_RSA_KEYX),
|
|
PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA", CALG_RSA_SIGN),
|
|
PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA_SIGN", CALG_RSA_SIGN),
|
|
DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSA"),
|
|
DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSS"),
|
|
DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSA_SIGN"),
|
|
DH_PUBKEY_ALG_ENTRY(szOID_RSA_DH, L"DH"),
|
|
PUBKEY_ALG_ENTRY(szOID_OIWSEC_rsaXchg, L"RSA_KEYX", CALG_RSA_KEYX),
|
|
PUBKEY_EXTRA_ALG_ENTRY(szOID_INFOSEC_mosaicKMandUpdSig,
|
|
L"mosaicKMandUpdSig", CALG_DSS_SIGN, dwMosaicFlags),
|
|
#ifdef CMS_PKCS7
|
|
ESDH_PUBKEY_ALG_ENTRY(szOID_RSA_SMIMEalgESDH, L"ESDH"),
|
|
#endif // CMS_PKCS7
|
|
PUBKEY_ALG_ENTRY(szOID_PKIX_NO_SIGNATURE, L"NO_SIGN", CALG_NO_SIGN),
|
|
};
|
|
#define PUBKEY_ALG_CNT (sizeof(PubKeyAlgTable) / sizeof(PubKeyAlgTable[0]))
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Signature Algorithm Table
|
|
//--------------------------------------------------------------------------
|
|
static const ALG_ID aiRsaPubKey = CALG_RSA_SIGN;
|
|
static const DWORD rgdwMosaicSign[] = {
|
|
CALG_DSS_SIGN,
|
|
CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
|
|
CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG
|
|
};
|
|
static const DWORD rgdwDssSign[] = {
|
|
CALG_DSS_SIGN,
|
|
CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG
|
|
};
|
|
|
|
#define SIGN_ALG_ENTRY(pszOID, pwszName, aiHash, aiPubKey) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_SIGN_ALG_OID_GROUP_ID, aiHash, \
|
|
sizeof(aiPubKey), (BYTE *) &aiPubKey
|
|
#define RSA_SIGN_ALG_ENTRY(pszOID, pwszName, aiHash) \
|
|
SIGN_ALG_ENTRY(pszOID, pwszName, aiHash, aiRsaPubKey)
|
|
|
|
#define SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, aiHash, rgdwExtra) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_SIGN_ALG_OID_GROUP_ID, aiHash, \
|
|
sizeof(rgdwExtra), (BYTE *) rgdwExtra
|
|
|
|
#define DSS_SIGN_ALG_ENTRY(pszOID, pwszName) \
|
|
SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_SHA1, rgdwDssSign)
|
|
|
|
static CCRYPT_OID_INFO SignAlgTable[] = {
|
|
RSA_SIGN_ALG_ENTRY(szOID_RSA_SHA1RSA, L"sha1RSA", CALG_SHA1),
|
|
RSA_SIGN_ALG_ENTRY(szOID_RSA_MD5RSA, L"md5RSA", CALG_MD5),
|
|
DSS_SIGN_ALG_ENTRY(szOID_X957_SHA1DSA, L"sha1DSA"),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_sha1RSASign, L"sha1RSA", CALG_SHA1),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_sha1RSASign, L"shaRSA", CALG_SHA1),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_shaRSA, L"shaRSA", CALG_SHA),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md5RSA, L"md5RSA", CALG_MD5),
|
|
RSA_SIGN_ALG_ENTRY(szOID_RSA_MD2RSA, L"md2RSA", CALG_MD2),
|
|
RSA_SIGN_ALG_ENTRY(szOID_RSA_MD4RSA, L"md4RSA", CALG_MD4),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md4RSA, L"md4RSA", CALG_MD4),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md4RSA2, L"md4RSA", CALG_MD4),
|
|
RSA_SIGN_ALG_ENTRY(szOID_OIWDIR_md2RSA, L"md2RSA", CALG_MD2),
|
|
DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_shaDSA, L"sha1DSA"),
|
|
DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_shaDSA, L"shaDSA"),
|
|
DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_dsaSHA1,L"dsaSHA1"),
|
|
SIGN_EXTRA_ALG_ENTRY(szOID_INFOSEC_mosaicUpdatedSig, L"mosaicUpdatedSig",
|
|
CALG_SHA, rgdwMosaicSign),
|
|
};
|
|
#define SIGN_ALG_CNT (sizeof(SignAlgTable) / sizeof(SignAlgTable[0]))
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// RDN Attribute Table
|
|
//--------------------------------------------------------------------------
|
|
|
|
// PLEASE UPDATE the following define in certstr.cpp if you add a new entry
|
|
// with a longer pwszName
|
|
// #define MAX_X500_KEY_LEN 64
|
|
|
|
// Ordered lists of acceptable RDN attribute value types. 0 terminates.
|
|
static const DWORD rgdwPrintableValueType[] = { CERT_RDN_PRINTABLE_STRING, 0 };
|
|
static const DWORD rgdwIA5ValueType[] = { CERT_RDN_IA5_STRING, 0 };
|
|
static const DWORD rgdwNumericValueType[] = { CERT_RDN_NUMERIC_STRING, 0 };
|
|
static const DWORD rgdwIA5orUTF8ValueType[] = { CERT_RDN_IA5_STRING,
|
|
CERT_RDN_UTF8_STRING, 0 };
|
|
|
|
#define RDN_ATTR_ENTRY(pszOID, pwszName, rgdwValueType) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 0, \
|
|
sizeof(rgdwValueType), (BYTE *) rgdwValueType
|
|
#define DEFAULT_RDN_ATTR_ENTRY(pszOID, pwszName) \
|
|
OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 0, 0, NULL
|
|
|
|
static CCRYPT_OID_INFO RDNAttrTable[] = {
|
|
// Ordered with most commonly used key names at the beginning
|
|
|
|
// Labeling attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_COMMON_NAME, L"CN"),
|
|
// Geographic attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_LOCALITY_NAME, L"L"),
|
|
// Organizational attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_ORGANIZATION_NAME, L"O"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_ORGANIZATIONAL_UNIT_NAME, L"OU"),
|
|
|
|
// Verisign sticks the following in their cert names. Netscape uses the
|
|
// "E" instead of the "Email". Will let "E" take precedence
|
|
RDN_ATTR_ENTRY(szOID_RSA_emailAddr, L"E", rgdwIA5ValueType),
|
|
RDN_ATTR_ENTRY(szOID_RSA_emailAddr, L"Email", rgdwIA5ValueType),
|
|
|
|
// The following aren't used in Verisign's certs
|
|
|
|
// Geographic attribute types:
|
|
RDN_ATTR_ENTRY(szOID_COUNTRY_NAME, L"C", rgdwPrintableValueType),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME, L"S"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME, L"ST"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_STREET_ADDRESS, L"STREET"),
|
|
|
|
// Organizational attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_TITLE, L"T"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_TITLE, L"Title"),
|
|
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"G"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"GN"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"GivenName"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_INITIALS, L"I"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_INITIALS, L"Initials"),
|
|
|
|
// Labeling attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_SUR_NAME, L"SN"),
|
|
// RDN_ATTR_ENTRY(szOID_DEVICE_SERIAL_NUMBER, L"", rgdwPrintableValueType),
|
|
|
|
// Pilot user attribute types:
|
|
RDN_ATTR_ENTRY(szOID_DOMAIN_COMPONENT, L"DC", rgdwIA5orUTF8ValueType),
|
|
|
|
// Explanatory attribute types:
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_DESCRIPTION, L"Description"),
|
|
// szOID_SEARCH_GUIDE "2.5.4.14"
|
|
// DEFAULT_RDN_ATTR_ENTRY(szOID_BUSINESS_CATEGORY, L""),
|
|
|
|
// Postal addressing attribute types:
|
|
// szOID_POSTAL_ADDRESS "2.5.4.16"
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_POSTAL_CODE, L"PostalCode"),
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_POST_OFFICE_BOX, L"POBox"),
|
|
// DEFAULT_RDN_ATTR_ENTRY(szOID_PHYSICAL_DELIVERY_OFFICE_NAME, L""),
|
|
|
|
// Telecommunications addressing attribute types:
|
|
RDN_ATTR_ENTRY(szOID_TELEPHONE_NUMBER, L"Phone", rgdwPrintableValueType),
|
|
// szOID_TELEX_NUMBER "2.5.4.21"
|
|
// szOID_TELETEXT_TERMINAL_IDENTIFIER "2.5.4.22"
|
|
// szOID_FACSIMILE_TELEPHONE_NUMBER "2.5.4.23"
|
|
|
|
// Following is used as a test case for a Numeric value
|
|
RDN_ATTR_ENTRY(szOID_X21_ADDRESS, L"X21Address", rgdwNumericValueType),
|
|
// RDN_ATTR_ENTRY(szOID_INTERNATIONAL_ISDN_NUMBER, L"", rgdwNumericValueType),
|
|
// szOID_REGISTERED_ADDRESS "2.5.4.26"
|
|
// RDN_ATTR_ENTRY(szOID_DESTINATION_INDICATOR, L"", rgdwPrintableValueType)
|
|
|
|
// Preference attribute types:
|
|
// szOID_PREFERRED_DELIVERY_METHOD "2.5.4.28"
|
|
|
|
// OSI application attribute types:
|
|
// szOID_PRESENTATION_ADDRESS "2.5.4.29"
|
|
// szOID_SUPPORTED_APPLICATION_CONTEXT "2.5.4.30"
|
|
|
|
// Relational application attribute types:
|
|
// szOID_MEMBER "2.5.4.31"
|
|
// szOID_OWNER "2.5.4.32"
|
|
// szOID_ROLE_OCCUPANT "2.5.4.33"
|
|
// szOID_SEE_ALSO "2.5.4.34"
|
|
|
|
// Security attribute types:
|
|
// szOID_USER_PASSWORD "2.5.4.35"
|
|
// szOID_USER_CERTIFICATE "2.5.4.36"
|
|
// szOID_CA_CERTIFICATE "2.5.4.37"
|
|
// szOID_AUTHORITY_REVOCATION_LIST "2.5.4.38"
|
|
// szOID_CERTIFICATE_REVOCATION_LIST "2.5.4.39"
|
|
// szOID_CROSS_CERTIFICATE_PAIR "2.5.4.40"
|
|
|
|
// Undocumented attribute types???
|
|
//#define szOID_??? "2.5.4.41"
|
|
|
|
DEFAULT_RDN_ATTR_ENTRY(szOID_DN_QUALIFIER, L"dnQualifier"),
|
|
};
|
|
#define RDN_ATTR_CNT (sizeof(RDNAttrTable) / sizeof(RDNAttrTable[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Extension or Attribute Table (Localized via resource strings)
|
|
//--------------------------------------------------------------------------
|
|
#define EXT_ATTR_ENTRY(pszOID, ResourceIdORpwszName) \
|
|
OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
|
|
CRYPT_EXT_OR_ATTR_OID_GROUP_ID, 0, 0, NULL
|
|
|
|
static CRYPT_OID_INFO ExtAttrTable[] = {
|
|
EXT_ATTR_ENTRY(szOID_AUTHORITY_KEY_IDENTIFIER2,
|
|
IDS_EXT_AUTHORITY_KEY_IDENTIFIER),
|
|
EXT_ATTR_ENTRY(szOID_AUTHORITY_KEY_IDENTIFIER,
|
|
IDS_EXT_AUTHORITY_KEY_IDENTIFIER),
|
|
EXT_ATTR_ENTRY(szOID_KEY_ATTRIBUTES,
|
|
IDS_EXT_KEY_ATTRIBUTES),
|
|
EXT_ATTR_ENTRY(szOID_KEY_USAGE_RESTRICTION,
|
|
IDS_EXT_KEY_USAGE_RESTRICTION),
|
|
EXT_ATTR_ENTRY(szOID_SUBJECT_ALT_NAME2,
|
|
IDS_EXT_SUBJECT_ALT_NAME),
|
|
EXT_ATTR_ENTRY(szOID_SUBJECT_ALT_NAME,
|
|
IDS_EXT_SUBJECT_ALT_NAME),
|
|
EXT_ATTR_ENTRY(szOID_ISSUER_ALT_NAME2,
|
|
IDS_EXT_ISSUER_ALT_NAME),
|
|
EXT_ATTR_ENTRY(szOID_ISSUER_ALT_NAME,
|
|
IDS_EXT_ISSUER_ALT_NAME),
|
|
EXT_ATTR_ENTRY(szOID_BASIC_CONSTRAINTS2,
|
|
IDS_EXT_BASIC_CONSTRAINTS),
|
|
EXT_ATTR_ENTRY(szOID_BASIC_CONSTRAINTS,
|
|
IDS_EXT_BASIC_CONSTRAINTS),
|
|
EXT_ATTR_ENTRY(szOID_KEY_USAGE,
|
|
IDS_EXT_KEY_USAGE),
|
|
EXT_ATTR_ENTRY(szOID_CERT_POLICIES,
|
|
IDS_EXT_CERT_POLICIES),
|
|
EXT_ATTR_ENTRY(szOID_SUBJECT_KEY_IDENTIFIER,
|
|
IDS_EXT_SUBJECT_KEY_IDENTIFIER),
|
|
EXT_ATTR_ENTRY(szOID_CRL_REASON_CODE,
|
|
IDS_EXT_CRL_REASON_CODE),
|
|
EXT_ATTR_ENTRY(szOID_CRL_DIST_POINTS,
|
|
IDS_EXT_CRL_DIST_POINTS),
|
|
EXT_ATTR_ENTRY(szOID_ENHANCED_KEY_USAGE,
|
|
IDS_EXT_ENHANCED_KEY_USAGE),
|
|
EXT_ATTR_ENTRY(szOID_AUTHORITY_INFO_ACCESS,
|
|
IDS_EXT_AUTHORITY_INFO_ACCESS),
|
|
EXT_ATTR_ENTRY(szOID_CERT_EXTENSIONS,
|
|
IDS_EXT_CERT_EXTENSIONS),
|
|
EXT_ATTR_ENTRY(szOID_RSA_certExtensions,
|
|
IDS_EXT_CERT_EXTENSIONS),
|
|
EXT_ATTR_ENTRY(szOID_NEXT_UPDATE_LOCATION,
|
|
IDS_EXT_NEXT_UPDATE_LOCATION),
|
|
EXT_ATTR_ENTRY(szOID_YESNO_TRUST_ATTR,
|
|
IDS_EXT_YESNO_TRUST_ATTR),
|
|
EXT_ATTR_ENTRY(szOID_RSA_emailAddr,
|
|
IDS_EXT_RSA_emailAddr),
|
|
EXT_ATTR_ENTRY(szOID_RSA_unstructName,
|
|
IDS_EXT_RSA_unstructName),
|
|
EXT_ATTR_ENTRY(szOID_RSA_contentType,
|
|
IDS_EXT_RSA_contentType),
|
|
EXT_ATTR_ENTRY(szOID_RSA_messageDigest,
|
|
IDS_EXT_RSA_messageDigest),
|
|
EXT_ATTR_ENTRY(szOID_RSA_signingTime,
|
|
IDS_EXT_RSA_signingTime),
|
|
EXT_ATTR_ENTRY(szOID_RSA_counterSign,
|
|
IDS_EXT_RSA_counterSign),
|
|
EXT_ATTR_ENTRY(szOID_RSA_challengePwd,
|
|
IDS_EXT_RSA_challengePwd),
|
|
EXT_ATTR_ENTRY(szOID_RSA_unstructAddr,
|
|
IDS_EXT_RSA_unstructAddr),
|
|
EXT_ATTR_ENTRY(szOID_RSA_extCertAttrs, L""),
|
|
EXT_ATTR_ENTRY(szOID_RSA_SMIMECapabilities,
|
|
IDS_EXT_RSA_SMIMECapabilities),
|
|
EXT_ATTR_ENTRY(szOID_RSA_preferSignedData,
|
|
IDS_EXT_RSA_preferSignedData),
|
|
EXT_ATTR_ENTRY(szOID_PKIX_POLICY_QUALIFIER_CPS,
|
|
IDS_EXT_PKIX_POLICY_QUALIFIER_CPS),
|
|
EXT_ATTR_ENTRY(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
|
|
IDS_EXT_PKIX_POLICY_QUALIFIER_USERNOTICE),
|
|
EXT_ATTR_ENTRY(szOID_PKIX_OCSP,
|
|
IDS_EXT_PKIX_OCSP),
|
|
EXT_ATTR_ENTRY(szOID_PKIX_CA_ISSUERS,
|
|
IDS_EXT_PKIX_CA_ISSUERS),
|
|
EXT_ATTR_ENTRY(szOID_ENROLL_CERTTYPE_EXTENSION,
|
|
IDS_EXT_MS_CERTIFICATE_TEMPLATE),
|
|
EXT_ATTR_ENTRY(szOID_ENROLL_CERTTYPE_EXTENSION,
|
|
IDS_EXT_ENROLL_CERTTYPE),
|
|
EXT_ATTR_ENTRY(szOID_CERT_MANIFOLD,
|
|
IDS_EXT_CERT_MANIFOLD),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_CERT_TYPE,
|
|
IDS_EXT_NETSCAPE_CERT_TYPE),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_BASE_URL,
|
|
IDS_EXT_NETSCAPE_BASE_URL),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_REVOCATION_URL,
|
|
IDS_EXT_NETSCAPE_REVOCATION_URL),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_CA_REVOCATION_URL,
|
|
IDS_EXT_NETSCAPE_CA_REVOCATION_URL),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_CERT_RENEWAL_URL,
|
|
IDS_EXT_NETSCAPE_CERT_RENEWAL_URL),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_CA_POLICY_URL,
|
|
IDS_EXT_NETSCAPE_CA_POLICY_URL),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_SSL_SERVER_NAME,
|
|
IDS_EXT_NETSCAPE_SSL_SERVER_NAME),
|
|
EXT_ATTR_ENTRY(szOID_NETSCAPE_COMMENT,
|
|
IDS_EXT_NETSCAPE_COMMENT),
|
|
EXT_ATTR_ENTRY(SPC_SP_AGENCY_INFO_OBJID,
|
|
IDS_EXT_SPC_SP_AGENCY_INFO_OBJID),
|
|
EXT_ATTR_ENTRY(SPC_FINANCIAL_CRITERIA_OBJID,
|
|
IDS_EXT_SPC_FINANCIAL_CRITERIA_OBJID),
|
|
EXT_ATTR_ENTRY(SPC_MINIMAL_CRITERIA_OBJID,
|
|
IDS_EXT_SPC_MINIMAL_CRITERIA_OBJID),
|
|
EXT_ATTR_ENTRY(szOID_COUNTRY_NAME,
|
|
IDS_EXT_COUNTRY_NAME),
|
|
EXT_ATTR_ENTRY(szOID_ORGANIZATION_NAME,
|
|
IDS_EXT_ORGANIZATION_NAME),
|
|
EXT_ATTR_ENTRY(szOID_ORGANIZATIONAL_UNIT_NAME,
|
|
IDS_EXT_ORGANIZATIONAL_UNIT_NAME),
|
|
EXT_ATTR_ENTRY(szOID_COMMON_NAME,
|
|
IDS_EXT_COMMON_NAME),
|
|
EXT_ATTR_ENTRY(szOID_LOCALITY_NAME,
|
|
IDS_EXT_LOCALITY_NAME),
|
|
EXT_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME,
|
|
IDS_EXT_STATE_OR_PROVINCE_NAME),
|
|
EXT_ATTR_ENTRY(szOID_TITLE,
|
|
IDS_EXT_TITLE),
|
|
EXT_ATTR_ENTRY(szOID_GIVEN_NAME,
|
|
IDS_EXT_GIVEN_NAME),
|
|
EXT_ATTR_ENTRY(szOID_INITIALS,
|
|
IDS_EXT_INITIALS),
|
|
EXT_ATTR_ENTRY(szOID_SUR_NAME,
|
|
IDS_EXT_SUR_NAME),
|
|
EXT_ATTR_ENTRY(szOID_DOMAIN_COMPONENT,
|
|
IDS_EXT_DOMAIN_COMPONENT),
|
|
EXT_ATTR_ENTRY(szOID_STREET_ADDRESS,
|
|
IDS_EXT_STREET_ADDRESS),
|
|
EXT_ATTR_ENTRY(szOID_DEVICE_SERIAL_NUMBER,
|
|
IDS_EXT_DEVICE_SERIAL_NUMBER),
|
|
EXT_ATTR_ENTRY(szOID_CERTSRV_CA_VERSION,
|
|
IDS_EXT_CA_VERSION),
|
|
EXT_ATTR_ENTRY(szOID_CERTSRV_CROSSCA_VERSION,
|
|
IDS_EXT_CROSSCA_VERSION),
|
|
EXT_ATTR_ENTRY(szOID_SERIALIZED,
|
|
IDS_EXT_SERIALIZED),
|
|
EXT_ATTR_ENTRY(szOID_NT_PRINCIPAL_NAME,
|
|
IDS_EXT_NT_PRINCIPAL_NAME),
|
|
EXT_ATTR_ENTRY(szOID_PRODUCT_UPDATE,
|
|
IDS_EXT_PRODUCT_UPDATE),
|
|
EXT_ATTR_ENTRY(szOID_ENROLLMENT_NAME_VALUE_PAIR,
|
|
IDS_EXT_ENROLLMENT_NAME_VALUE_PAIR),
|
|
EXT_ATTR_ENTRY(szOID_OS_VERSION,
|
|
IDS_EXT_OS_VERSION),
|
|
EXT_ATTR_ENTRY(szOID_ENROLLMENT_CSP_PROVIDER,
|
|
IDS_EXT_ENROLLMENT_CSP_PROVIDER),
|
|
EXT_ATTR_ENTRY(szOID_CRL_NUMBER,
|
|
IDS_EXT_CRL_NUMBER),
|
|
EXT_ATTR_ENTRY(szOID_DELTA_CRL_INDICATOR,
|
|
IDS_EXT_DELTA_CRL_INDICATOR),
|
|
EXT_ATTR_ENTRY(szOID_ISSUING_DIST_POINT,
|
|
IDS_EXT_ISSUING_DIST_POINT),
|
|
EXT_ATTR_ENTRY(szOID_FRESHEST_CRL,
|
|
IDS_EXT_FRESHEST_CRL),
|
|
EXT_ATTR_ENTRY(szOID_NAME_CONSTRAINTS,
|
|
IDS_EXT_NAME_CONSTRAINTS),
|
|
EXT_ATTR_ENTRY(szOID_POLICY_MAPPINGS,
|
|
IDS_EXT_POLICY_MAPPINGS),
|
|
EXT_ATTR_ENTRY(szOID_LEGACY_POLICY_MAPPINGS,
|
|
IDS_EXT_POLICY_MAPPINGS),
|
|
EXT_ATTR_ENTRY(szOID_POLICY_CONSTRAINTS,
|
|
IDS_EXT_POLICY_CONSTRAINTS),
|
|
EXT_ATTR_ENTRY(szOID_CROSS_CERT_DIST_POINTS,
|
|
IDS_EXT_CROSS_CERT_DIST_POINTS),
|
|
EXT_ATTR_ENTRY(szOID_APPLICATION_CERT_POLICIES,
|
|
IDS_EXT_APP_POLICIES),
|
|
EXT_ATTR_ENTRY(szOID_APPLICATION_POLICY_MAPPINGS,
|
|
IDS_EXT_APP_POLICY_MAPPINGS),
|
|
EXT_ATTR_ENTRY(szOID_APPLICATION_POLICY_CONSTRAINTS,
|
|
IDS_EXT_APP_POLICY_CONSTRAINTS),
|
|
|
|
|
|
// DSIE: Post Win2K, 8/2/2000.
|
|
EXT_ATTR_ENTRY(szOID_CT_PKI_DATA,
|
|
IDS_EXT_CT_PKI_DATA),
|
|
EXT_ATTR_ENTRY(szOID_CT_PKI_RESPONSE,
|
|
IDS_EXT_CT_PKI_RESPONSE),
|
|
EXT_ATTR_ENTRY(szOID_CMC,
|
|
IDS_EXT_CMC),
|
|
EXT_ATTR_ENTRY(szOID_CMC_STATUS_INFO,
|
|
IDS_EXT_CMC_STATUS_INFO),
|
|
EXT_ATTR_ENTRY(szOID_CMC_ADD_EXTENSIONS,
|
|
IDS_EXT_CMC_ADD_EXTENSIONS),
|
|
EXT_ATTR_ENTRY(szOID_CMC_ADD_ATTRIBUTES,
|
|
IDS_EXT_CMC_ADD_ATTRIBUTES),
|
|
EXT_ATTR_ENTRY(szOID_CMC_ADD_ATTRIBUTES,
|
|
IDS_EXT_CMC_ADD_ATTRIBUTES),
|
|
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_DATA,
|
|
IDS_EXT_PKCS_7_DATA),
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_SIGNED,
|
|
IDS_EXT_PKCS_7_SIGNED),
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_ENVELOPED,
|
|
IDS_EXT_PKCS_7_ENVELOPED),
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_SIGNEDANDENVELOPED,
|
|
IDS_EXT_PKCS_7_SIGNEDANDENVELOPED),
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_DIGESTED,
|
|
IDS_EXT_PKCS_7_DIGESTED),
|
|
EXT_ATTR_ENTRY(szOID_PKCS_7_ENCRYPTED,
|
|
IDS_EXT_PKCS_7_ENCRYPTED),
|
|
|
|
EXT_ATTR_ENTRY(szOID_CERTSRV_PREVIOUS_CERT_HASH,
|
|
IDS_EXT_CERTSRV_PREVIOUS_CERT_HASH),
|
|
EXT_ATTR_ENTRY(szOID_CRL_VIRTUAL_BASE,
|
|
IDS_EXT_CRL_VIRTUAL_BASE),
|
|
EXT_ATTR_ENTRY(szOID_CRL_NEXT_PUBLISH,
|
|
IDS_EXT_CRL_NEXT_PUBLISH),
|
|
EXT_ATTR_ENTRY(szOID_KP_CA_EXCHANGE,
|
|
IDS_EXT_KP_CA_EXCHANGE),
|
|
EXT_ATTR_ENTRY(szOID_KP_KEY_RECOVERY_AGENT,
|
|
IDS_EXT_KP_KEY_RECOVERY_AGENT),
|
|
EXT_ATTR_ENTRY(szOID_CERTIFICATE_TEMPLATE,
|
|
IDS_EXT_CERTIFICATE_TEMPLATE),
|
|
EXT_ATTR_ENTRY(szOID_ENTERPRISE_OID_ROOT,
|
|
IDS_EXT_ENTERPRISE_OID_ROOT),
|
|
EXT_ATTR_ENTRY(szOID_RDN_DUMMY_SIGNER,
|
|
IDS_EXT_RDN_DUMMY_SIGNER),
|
|
|
|
EXT_ATTR_ENTRY(szOID_ARCHIVED_KEY_ATTR,
|
|
IDS_EXT_ARCHIVED_KEY_ATTR),
|
|
EXT_ATTR_ENTRY(szOID_CRL_SELF_CDP,
|
|
IDS_EXT_CRL_SELF_CDP),
|
|
EXT_ATTR_ENTRY(szOID_REQUIRE_CERT_CHAIN_POLICY,
|
|
IDS_EXT_REQUIRE_CERT_CHAIN_POLICY),
|
|
|
|
EXT_ATTR_ENTRY(szOID_CMC_TRANSACTION_ID,
|
|
IDS_EXT_CMC_TRANSACTION_ID),
|
|
EXT_ATTR_ENTRY(szOID_CMC_SENDER_NONCE,
|
|
IDS_EXT_CMC_SENDER_NONCE),
|
|
EXT_ATTR_ENTRY(szOID_CMC_RECIPIENT_NONCE,
|
|
IDS_EXT_CMC_RECIPIENT_NONCE),
|
|
EXT_ATTR_ENTRY(szOID_CMC_REG_INFO,
|
|
IDS_EXT_CMC_REG_INFO),
|
|
EXT_ATTR_ENTRY(szOID_CMC_GET_CERT,
|
|
IDS_EXT_CMC_GET_CERT),
|
|
EXT_ATTR_ENTRY(szOID_CMC_GET_CRL,
|
|
IDS_EXT_CMC_GET_CRL),
|
|
EXT_ATTR_ENTRY(szOID_CMC_REVOKE_REQUEST,
|
|
IDS_EXT_CMC_REVOKE_REQUEST),
|
|
EXT_ATTR_ENTRY(szOID_CMC_QUERY_PENDING,
|
|
IDS_EXT_CMC_QUERY_PENDING),
|
|
EXT_ATTR_ENTRY(szOID_CTL,
|
|
IDS_EXT_CTL),
|
|
EXT_ATTR_ENTRY(szOID_ARCHIVED_KEY_CERT_HASH,
|
|
IDS_EXT_ARCHIVED_KEY_CERT_HASH),
|
|
EXT_ATTR_ENTRY(szOID_PRIVATEKEY_USAGE_PERIOD,
|
|
IDS_EXT_PRIVATEKEY_USAGE_PERIOD),
|
|
EXT_ATTR_ENTRY(szOID_REQUEST_CLIENT_INFO,
|
|
IDS_EXT_REQUEST_CLIENT_INFO),
|
|
};
|
|
|
|
|
|
#define EXT_ATTR_CNT (sizeof(ExtAttrTable) / sizeof(ExtAttrTable[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Enhanced Key Usage Table (Localized via resource strings)
|
|
//--------------------------------------------------------------------------
|
|
#define ENHKEY_ENTRY(pszOID, ResourceIdORpwszName) \
|
|
OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
|
|
CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, 0, NULL
|
|
|
|
static CRYPT_OID_INFO EnhKeyTable[] = {
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_SERVER_AUTH,
|
|
IDS_ENHKEY_PKIX_KP_SERVER_AUTH),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_CLIENT_AUTH,
|
|
IDS_ENHKEY_PKIX_KP_CLIENT_AUTH),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_CODE_SIGNING,
|
|
IDS_ENHKEY_PKIX_KP_CODE_SIGNING),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_EMAIL_PROTECTION,
|
|
IDS_ENHKEY_PKIX_KP_EMAIL_PROTECTION),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_TIMESTAMP_SIGNING,
|
|
IDS_ENHKEY_PKIX_KP_TIMESTAMP_SIGNING),
|
|
ENHKEY_ENTRY(szOID_KP_CTL_USAGE_SIGNING,
|
|
IDS_ENHKEY_KP_CTL_USAGE_SIGNING),
|
|
ENHKEY_ENTRY(szOID_KP_TIME_STAMP_SIGNING,
|
|
IDS_ENHKEY_KP_TIME_STAMP_SIGNING),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_END_SYSTEM,
|
|
IDS_ENHKEY_PKIX_KP_IPSEC_END_SYSTEM),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_TUNNEL,
|
|
IDS_ENHKEY_PKIX_KP_IPSEC_TUNNEL),
|
|
ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_USER,
|
|
IDS_ENHKEY_PKIX_KP_IPSEC_USER),
|
|
// ENHKEY_ENTRY(szOID_SERVER_GATED_CRYPTO,
|
|
// IDS_ENHKEY_SERVER_GATED_CRYPTO),
|
|
// ENHKEY_ENTRY(szOID_SGC_NETSCAPE,
|
|
// IDS_ENHKEY_SGC_NETSCAPE),
|
|
ENHKEY_ENTRY(szOID_KP_EFS,
|
|
IDS_ENHKEY_KP_EFS),
|
|
ENHKEY_ENTRY(szOID_WHQL_CRYPTO,
|
|
IDS_ENHKEY_KP_WHQL),
|
|
ENHKEY_ENTRY(szOID_NT5_CRYPTO,
|
|
IDS_ENHKEY_KP_NT5),
|
|
ENHKEY_ENTRY(szOID_OEM_WHQL_CRYPTO,
|
|
IDS_ENHKEY_KP_OEM_WHQL),
|
|
ENHKEY_ENTRY(szOID_EMBEDDED_NT_CRYPTO,
|
|
IDS_ENHKEY_KP_EMBEDDED_NT),
|
|
ENHKEY_ENTRY(szOID_LICENSES,
|
|
IDS_ENHKEY_LICENSES),
|
|
ENHKEY_ENTRY(szOID_LICENSE_SERVER,
|
|
IDS_ENHKEY_LICENSES_SERVER),
|
|
ENHKEY_ENTRY(szOID_KP_SMARTCARD_LOGON,
|
|
IDS_ENHKEY_SMARTCARD_LOGON),
|
|
ENHKEY_ENTRY(szOID_DRM,
|
|
IDS_ENHKEY_DRM),
|
|
ENHKEY_ENTRY(szOID_KP_QUALIFIED_SUBORDINATION,
|
|
IDS_ENHKEY_KP_QUALIFIED_SUBORDINATION),
|
|
ENHKEY_ENTRY(szOID_KP_KEY_RECOVERY,
|
|
IDS_ENHKEY_KP_KEY_RECOVERY),
|
|
ENHKEY_ENTRY(szOID_KP_DOCUMENT_SIGNING,
|
|
IDS_ENHKEY_KP_CODE_SIGNING),
|
|
ENHKEY_ENTRY(szOID_IPSEC_KP_IKE_INTERMEDIATE,
|
|
IDS_ENHKEY_KP_IPSEC_IKE_INTERMEDIATE),
|
|
ENHKEY_ENTRY(szOID_EFS_RECOVERY,
|
|
IDS_ENHKEY_EFS_RECOVERY),
|
|
|
|
//DSIE: 8/2/2000, Post Win2K.
|
|
ENHKEY_ENTRY(szOID_ROOT_LIST_SIGNER,
|
|
IDS_ENHKEY_ROOT_LIST_SIGNER),
|
|
ENHKEY_ENTRY(szOID_ANY_APPLICATION_POLICY,
|
|
IDS_ENHKEY_ANY_POLICY),
|
|
ENHKEY_ENTRY(szOID_DS_EMAIL_REPLICATION,
|
|
IDS_ENHKEY_DS_EMAIL_REPLICATION),
|
|
ENHKEY_ENTRY(szOID_ENROLLMENT_AGENT,
|
|
IDS_ENHKEY_ENROLLMENT_AGENT),
|
|
ENHKEY_ENTRY(szOID_KP_KEY_RECOVERY_AGENT,
|
|
IDS_ENHKEY_KP_KEY_RECOVERY_AGENT),
|
|
ENHKEY_ENTRY(szOID_KP_CA_EXCHANGE,
|
|
IDS_ENHKEY_KP_CA_EXCHANGE),
|
|
ENHKEY_ENTRY(szOID_KP_LIFETIME_SIGNING,
|
|
IDS_ENHKEY_KP_LIFETIME_SIGNING),
|
|
};
|
|
#define ENHKEY_CNT (sizeof(EnhKeyTable) / sizeof(EnhKeyTable[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Policy Table (Localized via resource strings)
|
|
//--------------------------------------------------------------------------
|
|
#define POLICY_ENTRY(pszOID, ResourceIdORpwszName) \
|
|
OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
|
|
CRYPT_POLICY_OID_GROUP_ID, 0, 0, NULL
|
|
|
|
static CRYPT_OID_INFO PolicyTable[] = {
|
|
POLICY_ENTRY(szOID_ANY_CERT_POLICY,
|
|
IDS_POLICY_ANY_POLICY),
|
|
};
|
|
#define POLICY_CNT (sizeof(PolicyTable) / sizeof(PolicyTable[0]))
|
|
|
|
#if 0
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Template Table (Localized via resource strings)
|
|
//--------------------------------------------------------------------------
|
|
#define TEMPLATE_ENTRY(pszOID, ResourceIdORpwszName) \
|
|
OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
|
|
CRYPT_TEMPLATE_OID_GROUP_ID, 0, 0, NULL
|
|
|
|
static CRYPT_OID_INFO TemplateTable[] = {
|
|
};
|
|
#define TEMPLATE_CNT (sizeof(TemplateTable) / sizeof(TemplateTable[0]))
|
|
|
|
#endif
|
|
|
|
|
|
//+=========================================================================
|
|
// OID Group Tables
|
|
//
|
|
// fLocalize is set to TRUE, if the CRYPT_OID_INFO's pwszName may be
|
|
// a Resource ID that is used to get the localized name via LoadStringU().
|
|
//
|
|
// Assumption, Resource ID's <= 0xFFFF.
|
|
//==========================================================================
|
|
typedef struct _GROUP_ENTRY {
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO rgInfo;
|
|
BOOL fLocalize;
|
|
} GROUP_ENTRY, *PGROUP_ENTRY;
|
|
typedef const GROUP_ENTRY CGROUP_ENTRY, *PCGROUP_ENTRY;
|
|
|
|
static CGROUP_ENTRY GroupTable[CRYPT_LAST_OID_GROUP_ID + 1] = {
|
|
0, NULL, FALSE, // 0
|
|
HASH_ALG_CNT, HashAlgTable, FALSE, // 1
|
|
ENCRYPT_ALG_CNT, EncryptAlgTable, FALSE, // 2
|
|
PUBKEY_ALG_CNT, PubKeyAlgTable, FALSE, // 3
|
|
SIGN_ALG_CNT, SignAlgTable, FALSE, // 4
|
|
RDN_ATTR_CNT, RDNAttrTable, FALSE, // 5
|
|
EXT_ATTR_CNT, ExtAttrTable, TRUE, // 6
|
|
ENHKEY_CNT, EnhKeyTable, TRUE, // 7
|
|
POLICY_CNT, PolicyTable, TRUE, // 8
|
|
#if 0
|
|
TEMPLATE_CNT, TemplateTable, TRUE, // 9
|
|
#else
|
|
0, NULL, FALSE, // 9
|
|
#endif
|
|
};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// The following groups are dynamically updated from the registry on
|
|
// CryptFindOIDInfo's first call.
|
|
//--------------------------------------------------------------------------
|
|
static GROUP_ENTRY RegBeforeGroup;
|
|
static GROUP_ENTRY RegAfterGroup;
|
|
|
|
// Do the load once within a critical section
|
|
static BOOL fLoadedFromRegAndResources = FALSE;
|
|
static CRITICAL_SECTION LoadFromRegCriticalSection;
|
|
|
|
|
|
//+=========================================================================
|
|
// DS Group Definitions and Data Structures
|
|
//==========================================================================
|
|
|
|
typedef struct _DS_GROUP_ENTRY {
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO *rgpInfo;
|
|
} DS_GROUP_ENTRY, *PDS_GROUP_ENTRY;
|
|
typedef const DS_GROUP_ENTRY CDS_GROUP_ENTRY, *PCDS_GROUP_ENTRY;
|
|
|
|
// The DS group is dynamically updated from the DS on the first call
|
|
// to CryptFindOIDInfo or CryptEnumOIDInfo for the ENHKEY, POLICY or
|
|
// TEMPLATE groups.
|
|
static DS_GROUP_ENTRY DsGroup;
|
|
|
|
// The above DsGroup is updated every DS_RETRIEVAL_DELTA_SECONDS. Since
|
|
// any returned PCCRYPT_OID_INFO can not be freed, the following group contains
|
|
// PCCRYPT_OID_INFO entries that may have been deleted from the above DS group.
|
|
static DS_GROUP_ENTRY DsDeletedGroup;
|
|
|
|
static CRITICAL_SECTION DsCriticalSection;
|
|
|
|
// For a successful DS retrieval, the following is updated with
|
|
// CurrentTime + DS_RETRIEVAL_DELTA_SECONDS.
|
|
static FILETIME DsNextUpdateTime;
|
|
|
|
#define DS_RETRIEVAL_DELTA_SECONDS (60 * 60 * 8)
|
|
#define DS_LDAP_TIMEOUT (10 * 1000)
|
|
|
|
|
|
static void FreeDsGroups();
|
|
|
|
static PCCRYPT_OID_INFO SearchDsGroup(
|
|
IN DWORD dwKeyType,
|
|
IN void *pvKey,
|
|
IN DWORD dwGroupId
|
|
);
|
|
|
|
static BOOL EnumDsGroup(
|
|
IN DWORD dwGroupId,
|
|
IN void *pvArg,
|
|
IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
|
|
);
|
|
|
|
|
|
//+=========================================================================
|
|
// Localized Name Definitions and Data Structures
|
|
//==========================================================================
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Localized Name Information
|
|
//--------------------------------------------------------------------------
|
|
typedef struct _LOCALIZED_NAME_INFO {
|
|
LPCWSTR pwszCryptName;
|
|
union {
|
|
UINT uIDLocalizedName;
|
|
LPCWSTR pwszLocalizedName;
|
|
};
|
|
} LOCALIZED_NAME_INFO, *PLOCALIZED_NAME_INFO;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Predefined Localized Names Table (Localized via resource strings)
|
|
//--------------------------------------------------------------------------
|
|
static LOCALIZED_NAME_INFO PredefinedNameTable[] = {
|
|
// System store names
|
|
L"Root", IDS_SYS_NAME_ROOT,
|
|
L"My", IDS_SYS_NAME_MY,
|
|
L"Trust", IDS_SYS_NAME_TRUST,
|
|
L"CA", IDS_SYS_NAME_CA,
|
|
L"UserDS", IDS_SYS_NAME_USERDS,
|
|
L"SmartCard", IDS_SYS_NAME_SMARTCARD,
|
|
L"AddressBook", IDS_SYS_NAME_ADDRESSBOOK,
|
|
L"TrustedPublisher", IDS_SYS_NAME_TRUST_PUB,
|
|
L"Disallowed", IDS_SYS_NAME_DISALLOWED,
|
|
L"AuthRoot", IDS_SYS_NAME_AUTH_ROOT,
|
|
L"Request", IDS_SYS_NAME_REQUEST,
|
|
L"TrustedPeople", IDS_SYS_NAME_TRUST_PEOPLE,
|
|
|
|
// Physical store names
|
|
CERT_PHYSICAL_STORE_DEFAULT_NAME, IDS_PHY_NAME_DEFAULT,
|
|
CERT_PHYSICAL_STORE_GROUP_POLICY_NAME, IDS_PHY_NAME_GROUP_POLICY,
|
|
CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME, IDS_PHY_NAME_LOCAL_MACHINE,
|
|
CERT_PHYSICAL_STORE_DS_USER_CERTIFICATE_NAME, IDS_PHY_NAME_DS_USER_CERT,
|
|
CERT_PHYSICAL_STORE_ENTERPRISE_NAME, IDS_PHY_NAME_ENTERPRISE,
|
|
CERT_PHYSICAL_STORE_AUTH_ROOT_NAME, IDS_PHY_NAME_AUTH_ROOT,
|
|
};
|
|
#define PREDEFINED_NAME_CNT (sizeof(PredefinedNameTable) / \
|
|
sizeof(PredefinedNameTable[0]))
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Localized Name Group Table
|
|
//--------------------------------------------------------------------------
|
|
typedef struct _LOCALIZED_GROUP_ENTRY {
|
|
DWORD cInfo;
|
|
PLOCALIZED_NAME_INFO rgInfo;
|
|
} LOCALIZED_GROUP_ENTRY, *PLOCALIZED_GROUP_ENTRY;
|
|
|
|
#define REG_LOCALIZED_GROUP 0
|
|
#define PREDEFINED_LOCALIZED_GROUP 1
|
|
static LOCALIZED_GROUP_ENTRY LocalizedGroupTable[] = {
|
|
// 0 - Loaded from registry
|
|
0, NULL,
|
|
// 1 - Predefined list of names
|
|
PREDEFINED_NAME_CNT, PredefinedNameTable
|
|
};
|
|
#define LOCALIZED_GROUP_CNT (sizeof(LocalizedGroupTable) / \
|
|
sizeof(LocalizedGroupTable[0]))
|
|
|
|
// The localized names are loaded once. Uses the above
|
|
// LoadFromRegCriticalSection;
|
|
static BOOL fLoadedLocalizedNames = FALSE;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// OIDInfo allocation and free functions
|
|
//--------------------------------------------------------------------------
|
|
static void *OIDInfoAlloc(
|
|
IN size_t cbBytes
|
|
)
|
|
{
|
|
void *pv;
|
|
pv = malloc(cbBytes);
|
|
if (pv == NULL)
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
return pv;
|
|
}
|
|
|
|
static void *OIDInfoRealloc(
|
|
IN void *pvOrg,
|
|
IN size_t cb
|
|
)
|
|
{
|
|
void *pv;
|
|
if (NULL == (pv = pvOrg ? realloc(pvOrg, cb) : malloc(cb)))
|
|
SetLastError((DWORD) E_OUTOFMEMORY);
|
|
return pv;
|
|
}
|
|
|
|
static void OIDInfoFree(
|
|
IN void *pv
|
|
)
|
|
{
|
|
free(pv);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Functions called at ProcessDetach to free the groups updated from the
|
|
// registry during CryptFindOIDInfo's first call.
|
|
//--------------------------------------------------------------------------
|
|
static void FreeGroup(
|
|
PGROUP_ENTRY pGroup
|
|
)
|
|
{
|
|
DWORD cInfo = pGroup->cInfo;
|
|
PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
|
|
for ( ; cInfo > 0; cInfo--, pInfo++)
|
|
OIDInfoFree((LPSTR)pInfo->pszOID);
|
|
|
|
OIDInfoFree((PCRYPT_OID_INFO) pGroup->rgInfo);
|
|
}
|
|
|
|
static void FreeRegGroups()
|
|
{
|
|
FreeGroup(&RegBeforeGroup);
|
|
FreeGroup(&RegAfterGroup);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Free resource strings allocated in groups having localized pwszName's.
|
|
//--------------------------------------------------------------------------
|
|
static void FreeGroupResources()
|
|
{
|
|
DWORD i;
|
|
if (!fLoadedFromRegAndResources)
|
|
// No resource strings allocated
|
|
return;
|
|
|
|
for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
|
|
if (GroupTable[i].fLocalize) {
|
|
DWORD cInfo = GroupTable[i].cInfo;
|
|
PCRYPT_OID_INFO pInfo = (PCRYPT_OID_INFO) GroupTable[i].rgInfo;
|
|
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
// pwszName is set to pwszNullName if the allocation failed
|
|
if (pwszNullName != pInfo->pwszName) {
|
|
OIDInfoFree((LPWSTR) pInfo->pwszName);
|
|
pInfo->pwszName = pwszNullName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Free memory allocated for localized names
|
|
//--------------------------------------------------------------------------
|
|
static void FreeLocalizedNames()
|
|
{
|
|
if (!fLoadedLocalizedNames)
|
|
// No resource strings allocated
|
|
return;
|
|
|
|
for (DWORD i = 0; i < LOCALIZED_GROUP_CNT; i++) {
|
|
DWORD cInfo = LocalizedGroupTable[i].cInfo;
|
|
PLOCALIZED_NAME_INFO pInfo = LocalizedGroupTable[i].rgInfo;
|
|
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
LPWSTR pwszLocalizedName = (LPWSTR) pInfo->pwszLocalizedName;
|
|
if (pwszNullName != pwszLocalizedName)
|
|
OIDInfoFree(pwszLocalizedName);
|
|
}
|
|
}
|
|
|
|
OIDInfoFree(LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Dll initialization
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
I_CryptOIDInfoDllMain(
|
|
HMODULE hInst,
|
|
ULONG ulReason,
|
|
LPVOID lpReserved)
|
|
{
|
|
BOOL fRet = TRUE;
|
|
|
|
switch (ulReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
hOIDInfoInst = hInst;
|
|
fRet = Pki_InitializeCriticalSection(&LoadFromRegCriticalSection);
|
|
if (fRet) {
|
|
fRet = Pki_InitializeCriticalSection(&DsCriticalSection);
|
|
if (!fRet)
|
|
DeleteCriticalSection(&LoadFromRegCriticalSection);
|
|
}
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
FreeRegGroups();
|
|
FreeGroupResources();
|
|
FreeLocalizedNames();
|
|
DeleteCriticalSection(&LoadFromRegCriticalSection);
|
|
|
|
FreeDsGroups();
|
|
DeleteCriticalSection(&DsCriticalSection);
|
|
break;
|
|
case DLL_THREAD_DETACH:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocated and format the string consisting of the OID and GROUP_ID:
|
|
//
|
|
// For example: 1.2.3.4!6
|
|
//--------------------------------------------------------------------------
|
|
static LPSTR FormatOIDGroupString(
|
|
IN PCCRYPT_OID_INFO pInfo
|
|
)
|
|
{
|
|
LPSTR pszOIDGroupString;
|
|
DWORD cchOIDGroupString;
|
|
char szGroupId[34];
|
|
|
|
if (NULL == pInfo || pInfo->cbSize < sizeof(CRYPT_OID_INFO) ||
|
|
(DWORD_PTR) pInfo->pszOID <= 0xFFFF) {
|
|
SetLastError((DWORD) E_INVALIDARG);
|
|
return NULL;
|
|
}
|
|
|
|
szGroupId[0] = CONST_OID_GROUP_PREFIX_CHAR;
|
|
_ltoa((long) pInfo->dwGroupId, &szGroupId[1], 10);
|
|
|
|
cchOIDGroupString = strlen(pInfo->pszOID) +
|
|
strlen(szGroupId) +
|
|
1;
|
|
|
|
if (pszOIDGroupString = (LPSTR) OIDInfoAlloc(cchOIDGroupString)) {
|
|
strcpy(pszOIDGroupString, pInfo->pszOID);
|
|
strcat(pszOIDGroupString, szGroupId);
|
|
}
|
|
|
|
return pszOIDGroupString;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Wrapper function for calling CryptSetOIDFunctionValue using OID info's
|
|
// encoding type and function name.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL SetOIDInfoRegValue(
|
|
IN LPCSTR pszOIDGroupString,
|
|
IN LPCWSTR pwszValueName,
|
|
IN DWORD dwValueType,
|
|
IN const BYTE *pbValueData,
|
|
IN DWORD cbValueData
|
|
)
|
|
{
|
|
return CryptSetOIDFunctionValue(
|
|
OID_INFO_ENCODING_TYPE,
|
|
CRYPT_OID_FIND_OID_INFO_FUNC,
|
|
pszOIDGroupString,
|
|
pwszValueName,
|
|
dwValueType,
|
|
pbValueData,
|
|
cbValueData
|
|
);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Register OID information.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
CryptRegisterOIDInfo(
|
|
IN PCCRYPT_OID_INFO pInfo,
|
|
IN DWORD dwFlags
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
LPSTR pszOIDGroupString = NULL;
|
|
|
|
if (NULL == (pszOIDGroupString = FormatOIDGroupString(pInfo)))
|
|
goto FormatOIDGroupStringError;
|
|
|
|
if (pInfo->pwszName && L'\0' != *pInfo->pwszName) {
|
|
if (!SetOIDInfoRegValue(
|
|
pszOIDGroupString,
|
|
OID_INFO_NAME_VALUE_NAME,
|
|
REG_SZ,
|
|
(const BYTE *) pInfo->pwszName,
|
|
(wcslen(pInfo->pwszName) + 1) * sizeof(WCHAR)
|
|
)) goto SetOIDInfoRegValueError;
|
|
}
|
|
if (0 != pInfo->Algid) {
|
|
if (!SetOIDInfoRegValue(
|
|
pszOIDGroupString,
|
|
OID_INFO_ALGID_VALUE_NAME,
|
|
REG_DWORD,
|
|
(const BYTE *) &pInfo->Algid,
|
|
sizeof(pInfo->Algid)
|
|
)) goto SetOIDInfoRegValueError;
|
|
}
|
|
if (0 != pInfo->ExtraInfo.cbData) {
|
|
if (!SetOIDInfoRegValue(
|
|
pszOIDGroupString,
|
|
OID_INFO_EXTRA_INFO_VALUE_NAME,
|
|
REG_BINARY,
|
|
pInfo->ExtraInfo.pbData,
|
|
pInfo->ExtraInfo.cbData
|
|
)) goto SetOIDInfoRegValueError;
|
|
}
|
|
|
|
if (0 != dwFlags) {
|
|
if (!SetOIDInfoRegValue(
|
|
pszOIDGroupString,
|
|
OID_INFO_FLAGS_VALUE_NAME,
|
|
REG_DWORD,
|
|
(const BYTE *) &dwFlags,
|
|
sizeof(dwFlags)
|
|
)) goto SetOIDInfoRegValueError;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
OIDInfoFree(pszOIDGroupString);
|
|
return fResult;
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(FormatOIDGroupStringError)
|
|
TRACE_ERROR(SetOIDInfoRegValueError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Unregister OID information. Only the pszOID and dwGroupId fields are
|
|
// used to identify the OID information to be unregistered.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
CryptUnregisterOIDInfo(
|
|
IN PCCRYPT_OID_INFO pInfo
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
LPSTR pszOIDGroupString = NULL;
|
|
|
|
if (NULL == (pszOIDGroupString = FormatOIDGroupString(pInfo)))
|
|
goto FormatOIDGroupStringError;
|
|
if (!CryptUnregisterOIDFunction(
|
|
OID_INFO_ENCODING_TYPE,
|
|
CRYPT_OID_FIND_OID_INFO_FUNC,
|
|
pszOIDGroupString
|
|
))
|
|
goto UnregisterOIDFunctionError;
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
OIDInfoFree(pszOIDGroupString);
|
|
return fResult;
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(FormatOIDGroupStringError)
|
|
TRACE_ERROR(UnregisterOIDFunctionError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Called by CryptEnumOIDFunction to enumerate through all the
|
|
// registered OID information.
|
|
//
|
|
// Called within critical section
|
|
//--------------------------------------------------------------------------
|
|
static BOOL WINAPI EnumRegistryCallback(
|
|
IN DWORD dwEncodingType,
|
|
IN LPCSTR pszFuncName,
|
|
IN LPCSTR pszOID,
|
|
IN DWORD cValue,
|
|
IN const DWORD rgdwValueType[],
|
|
IN LPCWSTR const rgpwszValueName[],
|
|
IN const BYTE * const rgpbValueData[],
|
|
IN const DWORD rgcbValueData[],
|
|
IN void *pvArg
|
|
)
|
|
{
|
|
DWORD cchOID;
|
|
LPCWSTR pwszName = NULL;
|
|
DWORD cchName = 0;
|
|
LPCSTR pszGroupId;
|
|
DWORD dwGroupId = 0;
|
|
ALG_ID Algid = 0;
|
|
CRYPT_DATA_BLOB ExtraInfo = {0, NULL};
|
|
DWORD dwFlags = 0;
|
|
DWORD cbExtra;
|
|
BYTE *pbExtra;
|
|
PGROUP_ENTRY pGroup;
|
|
PCRYPT_OID_INFO pInfo;
|
|
|
|
// The pszOID consists of OID!<dwGroupId>, for example, 1.2.3!1
|
|
// Start at the end and search for the '!'
|
|
cchOID = strlen(pszOID);
|
|
pszGroupId = pszOID + cchOID;
|
|
while (pszGroupId > pszOID && CONST_OID_GROUP_PREFIX_CHAR != *pszGroupId)
|
|
pszGroupId--;
|
|
|
|
if (CONST_OID_GROUP_PREFIX_CHAR == *pszGroupId) {
|
|
cchOID = (DWORD)(pszGroupId - pszOID);
|
|
dwGroupId = (DWORD) atol(pszGroupId + 1);
|
|
} else
|
|
// Name is missing "!". Skip It.
|
|
return TRUE;
|
|
|
|
while (cValue--) {
|
|
LPCWSTR pwszValueName = rgpwszValueName[cValue];
|
|
DWORD dwValueType = rgdwValueType[cValue];
|
|
const BYTE *pbValueData = rgpbValueData[cValue];
|
|
DWORD cbValueData = rgcbValueData[cValue];
|
|
|
|
if (0 == _wcsicmp(pwszValueName, OID_INFO_NAME_VALUE_NAME)) {
|
|
if (REG_SZ == dwValueType) {
|
|
pwszName = (LPWSTR) pbValueData;
|
|
cchName = wcslen(pwszName);
|
|
}
|
|
} else if (0 == _wcsicmp(pwszValueName, OID_INFO_ALGID_VALUE_NAME)) {
|
|
if (REG_DWORD == dwValueType &&
|
|
cbValueData >= sizeof(Algid))
|
|
memcpy(&Algid, pbValueData, sizeof(Algid));
|
|
} else if (0 == _wcsicmp(pwszValueName,
|
|
OID_INFO_EXTRA_INFO_VALUE_NAME)) {
|
|
if (REG_BINARY == dwValueType) {
|
|
ExtraInfo.cbData = cbValueData;
|
|
ExtraInfo.pbData = (BYTE *) pbValueData;
|
|
}
|
|
} else if (0 == _wcsicmp(pwszValueName, OID_INFO_FLAGS_VALUE_NAME)) {
|
|
if (REG_DWORD == dwValueType &&
|
|
cbValueData >= sizeof(dwFlags))
|
|
memcpy(&dwFlags, pbValueData, sizeof(dwFlags));
|
|
}
|
|
}
|
|
|
|
cbExtra = LEN_ALIGN(cchOID + 1) +
|
|
LEN_ALIGN((cchName + 1) * sizeof(WCHAR)) +
|
|
ExtraInfo.cbData;
|
|
if (NULL == (pbExtra = (BYTE *) OIDInfoAlloc(cbExtra)))
|
|
return FALSE;
|
|
|
|
if (dwFlags & CRYPT_INSTALL_OID_INFO_BEFORE_FLAG)
|
|
pGroup = &RegBeforeGroup;
|
|
else
|
|
pGroup = &RegAfterGroup;
|
|
|
|
if (NULL == (pInfo = (PCRYPT_OID_INFO) OIDInfoRealloc(
|
|
(PCRYPT_OID_INFO) pGroup->rgInfo,
|
|
(pGroup->cInfo + 1) * sizeof(CRYPT_OID_INFO)))) {
|
|
OIDInfoFree(pbExtra);
|
|
return FALSE;
|
|
}
|
|
pGroup->rgInfo = pInfo;
|
|
pInfo = &pInfo[pGroup->cInfo++];
|
|
|
|
pInfo->cbSize = sizeof(CRYPT_OID_INFO);
|
|
pInfo->pszOID = (LPCSTR) pbExtra;
|
|
if (cchOID)
|
|
memcpy(pbExtra, pszOID, cchOID);
|
|
*( ((LPSTR) pbExtra) + cchOID) = '\0';
|
|
pbExtra += LEN_ALIGN(cchOID + 1);
|
|
|
|
pInfo->pwszName = (LPCWSTR) pbExtra;
|
|
if (cchName)
|
|
memcpy(pbExtra, pwszName, (cchName + 1) * sizeof(WCHAR));
|
|
else
|
|
*((LPWSTR) pbExtra) = L'\0';
|
|
pbExtra += LEN_ALIGN((cchName + 1) * sizeof(WCHAR));
|
|
|
|
pInfo->dwGroupId = dwGroupId;
|
|
pInfo->Algid = Algid;
|
|
pInfo->ExtraInfo.cbData = ExtraInfo.cbData;
|
|
if (ExtraInfo.cbData > 0) {
|
|
pInfo->ExtraInfo.pbData = pbExtra;
|
|
memcpy(pbExtra, ExtraInfo.pbData, ExtraInfo.cbData);
|
|
} else
|
|
pInfo->ExtraInfo.pbData = NULL;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocate and load the string for the specified resource.
|
|
//
|
|
// If LoadString or allocation fails, returns predefined pointer to an
|
|
// empty string.
|
|
//--------------------------------------------------------------------------
|
|
static LPWSTR AllocAndLoadOIDNameString(
|
|
IN UINT uID
|
|
)
|
|
{
|
|
WCHAR wszResource[MAX_RESOURCE_OID_NAME_LENGTH + 1];
|
|
int cchResource;
|
|
int cbResource;
|
|
LPWSTR pwszDst;
|
|
|
|
cchResource = LoadStringU(hOIDInfoInst, uID, wszResource,
|
|
MAX_RESOURCE_OID_NAME_LENGTH);
|
|
assert(0 < cchResource);
|
|
if (0 >= cchResource)
|
|
return (LPWSTR) pwszNullName;
|
|
|
|
cbResource = (cchResource + 1) * sizeof(WCHAR);
|
|
pwszDst = (LPWSTR) OIDInfoAlloc(cbResource);
|
|
assert(pwszDst);
|
|
if (NULL == pwszDst)
|
|
return (LPWSTR) pwszNullName;
|
|
memcpy((BYTE *) pwszDst, (BYTE *) wszResource, cbResource);
|
|
return pwszDst;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocate and copy the string.
|
|
//
|
|
// If allocation fails, returns predefined pointer to an empty string.
|
|
//--------------------------------------------------------------------------
|
|
static LPWSTR AllocAndCopyOIDNameString(
|
|
IN LPCWSTR pwszSrc
|
|
)
|
|
{
|
|
DWORD cbSrc;
|
|
LPWSTR pwszDst;
|
|
|
|
cbSrc = (wcslen(pwszSrc) + 1) * sizeof(WCHAR);
|
|
pwszDst = (LPWSTR) OIDInfoAlloc(cbSrc);
|
|
assert(pwszDst);
|
|
if (NULL == pwszDst)
|
|
return (LPWSTR) pwszNullName;
|
|
memcpy((BYTE *) pwszDst, (BYTE *) pwszSrc, cbSrc);
|
|
return pwszDst;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Does a LoadString for pwszName's initialized with resource IDs in groups
|
|
// with fLocalize set.
|
|
//--------------------------------------------------------------------------
|
|
static void LoadGroupResources()
|
|
{
|
|
DWORD i;
|
|
for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
|
|
if (GroupTable[i].fLocalize) {
|
|
DWORD cInfo = GroupTable[i].cInfo;
|
|
PCRYPT_OID_INFO pInfo = (PCRYPT_OID_INFO) GroupTable[i].rgInfo;
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
UINT_PTR uID;
|
|
uID = (UINT_PTR) pInfo->pwszName;
|
|
if (uID <= 0xFFFF)
|
|
pInfo->pwszName = AllocAndLoadOIDNameString((UINT)uID);
|
|
else
|
|
// ProcessDetach expects all pwszName's to be allocated
|
|
pInfo->pwszName = AllocAndCopyOIDNameString(
|
|
pInfo->pwszName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Load OID Information from the registry. Updates the RegBeforeGroup and
|
|
// RegAfterGroup.
|
|
//
|
|
// Loads resource strings in groups enabling localization of pwszName's.
|
|
//--------------------------------------------------------------------------
|
|
static void LoadFromRegistryAndResources()
|
|
{
|
|
if (fLoadedFromRegAndResources)
|
|
return;
|
|
|
|
EnterCriticalSection(&LoadFromRegCriticalSection);
|
|
if (!fLoadedFromRegAndResources) {
|
|
CryptEnumOIDFunction(
|
|
OID_INFO_ENCODING_TYPE,
|
|
CRYPT_OID_FIND_OID_INFO_FUNC,
|
|
NULL, // pszOID
|
|
0, // dwFlags
|
|
NULL, // pvArg
|
|
EnumRegistryCallback
|
|
);
|
|
LoadGroupResources();
|
|
fLoadedFromRegAndResources = TRUE;
|
|
}
|
|
LeaveCriticalSection(&LoadFromRegCriticalSection);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Compare the OID info according to the specified key and group.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL CompareOIDInfo(
|
|
IN DWORD dwKeyType,
|
|
IN void *pvKey,
|
|
IN DWORD dwGroupId,
|
|
IN PCCRYPT_OID_INFO pInfo
|
|
)
|
|
{
|
|
if (dwGroupId && dwGroupId != pInfo->dwGroupId)
|
|
return FALSE;
|
|
|
|
switch (dwKeyType) {
|
|
case CRYPT_OID_INFO_OID_KEY:
|
|
if (0 == _stricmp((LPSTR) pvKey, pInfo->pszOID))
|
|
return TRUE;
|
|
break;
|
|
case CRYPT_OID_INFO_NAME_KEY:
|
|
if (0 == _wcsicmp((LPWSTR) pvKey, pInfo->pwszName))
|
|
return TRUE;
|
|
break;
|
|
case CRYPT_OID_INFO_ALGID_KEY:
|
|
if (*((ALG_ID *) pvKey) == pInfo->Algid)
|
|
return TRUE;
|
|
break;
|
|
case CRYPT_OID_INFO_SIGN_KEY:
|
|
{
|
|
ALG_ID *paiKey = (ALG_ID *) pvKey;
|
|
ALG_ID aiPubKey;
|
|
|
|
if (sizeof(ALG_ID) <= pInfo->ExtraInfo.cbData)
|
|
aiPubKey = *((ALG_ID *) pInfo->ExtraInfo.pbData);
|
|
else
|
|
aiPubKey = 0;
|
|
|
|
if (paiKey[0] == pInfo->Algid &&
|
|
paiKey[1] == aiPubKey)
|
|
return TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
SetLastError((DWORD) E_INVALIDARG);
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Search the group according to the specified dwKeyType.
|
|
//
|
|
// Note, the groups updated from the registry, RegBeforeGroup and
|
|
// RegAfterGroup, may contain any GROUP_ID.
|
|
//--------------------------------------------------------------------------
|
|
static PCCRYPT_OID_INFO SearchGroup(
|
|
IN DWORD dwKeyType,
|
|
IN void *pvKey,
|
|
IN DWORD dwGroupId,
|
|
IN PCGROUP_ENTRY pGroup
|
|
)
|
|
{
|
|
DWORD cInfo = pGroup->cInfo;
|
|
PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
if (CompareOIDInfo(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId,
|
|
pInfo
|
|
))
|
|
return pInfo;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Find OID information. Returns NULL if unable to find any information
|
|
// for the specified key and group.
|
|
//--------------------------------------------------------------------------
|
|
PCCRYPT_OID_INFO
|
|
WINAPI
|
|
CryptFindOIDInfo(
|
|
IN DWORD dwKeyType,
|
|
IN void *pvKey,
|
|
IN DWORD dwGroupId // 0 => any group
|
|
)
|
|
{
|
|
PCCRYPT_OID_INFO pInfo;
|
|
|
|
LoadFromRegistryAndResources();
|
|
|
|
if (RegBeforeGroup.cInfo && NULL != (pInfo = SearchGroup(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId,
|
|
&RegBeforeGroup
|
|
))) return pInfo;
|
|
if (0 == dwGroupId) {
|
|
DWORD i;
|
|
for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
|
|
if (pInfo = SearchGroup(
|
|
dwKeyType,
|
|
pvKey,
|
|
0,
|
|
&GroupTable[i]
|
|
)) return pInfo;
|
|
}
|
|
} else if (dwGroupId <= CRYPT_LAST_OID_GROUP_ID) {
|
|
if (pInfo = SearchGroup(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId,
|
|
&GroupTable[dwGroupId]
|
|
)) return pInfo;
|
|
}
|
|
|
|
if (RegAfterGroup.cInfo && NULL != (pInfo = SearchGroup(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId,
|
|
&RegAfterGroup
|
|
))) return pInfo;
|
|
|
|
return SearchDsGroup(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId
|
|
);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Enumerate the group.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL EnumGroup(
|
|
IN DWORD dwGroupId,
|
|
IN PCGROUP_ENTRY pGroup,
|
|
IN void *pvArg,
|
|
IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
|
|
)
|
|
{
|
|
DWORD cInfo = pGroup->cInfo;
|
|
PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
if (dwGroupId && dwGroupId != pInfo->dwGroupId)
|
|
continue;
|
|
|
|
if (!pfnEnumOIDInfo(pInfo, pvArg))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Enumerate the OID information.
|
|
//
|
|
// pfnEnumOIDInfo is called for each OID information entry.
|
|
//
|
|
// Setting dwGroupId to 0 matches all groups. Otherwise, only enumerates
|
|
// entries in the specified group.
|
|
//
|
|
// dwFlags currently isn't used and must be set to 0.
|
|
//--------------------------------------------------------------------------
|
|
BOOL
|
|
WINAPI
|
|
CryptEnumOIDInfo(
|
|
IN DWORD dwGroupId,
|
|
IN DWORD dwFlags,
|
|
IN void *pvArg,
|
|
IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
|
|
)
|
|
{
|
|
LoadFromRegistryAndResources();
|
|
|
|
if (RegBeforeGroup.cInfo && !EnumGroup(
|
|
dwGroupId,
|
|
&RegBeforeGroup,
|
|
pvArg,
|
|
pfnEnumOIDInfo
|
|
)) return FALSE;
|
|
if (0 == dwGroupId) {
|
|
DWORD i;
|
|
for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
|
|
if (!EnumGroup(
|
|
0, // dwGroupId
|
|
&GroupTable[i],
|
|
pvArg,
|
|
pfnEnumOIDInfo
|
|
)) return FALSE;
|
|
}
|
|
} else if (dwGroupId <= CRYPT_LAST_OID_GROUP_ID) {
|
|
if (!EnumGroup(
|
|
dwGroupId,
|
|
&GroupTable[dwGroupId],
|
|
pvArg,
|
|
pfnEnumOIDInfo
|
|
)) return FALSE;
|
|
}
|
|
|
|
if (RegAfterGroup.cInfo && !EnumGroup(
|
|
dwGroupId,
|
|
&RegAfterGroup,
|
|
pvArg,
|
|
pfnEnumOIDInfo
|
|
)) return FALSE;
|
|
|
|
|
|
return EnumDsGroup(
|
|
dwGroupId,
|
|
pvArg,
|
|
pfnEnumOIDInfo
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//+=========================================================================
|
|
// Localized Name Functions
|
|
//==========================================================================
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Called by CryptEnumOIDFunction to enumerate through all the
|
|
// registered localized name values.
|
|
//
|
|
// Called within critical section
|
|
//
|
|
// Note at ProcessDetach, the Info entry pwszLocalizedName strings are freed.
|
|
// Therefore, for each Info entry, do a single allocation for both the
|
|
// pwszLocalizedName and pwszCryptName. The pwszCryptName immediately
|
|
// follows the pwszLocalizedName.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL WINAPI EnumRegLocalizedNamesCallback(
|
|
IN DWORD dwEncodingType,
|
|
IN LPCSTR pszFuncName,
|
|
IN LPCSTR pszOID,
|
|
IN DWORD cValue,
|
|
IN const DWORD rgdwValueType[],
|
|
IN LPCWSTR const rgpwszValueName[],
|
|
IN const BYTE * const rgpbValueData[],
|
|
IN const DWORD rgcbValueData[],
|
|
IN void *pvArg
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD cInfo = LocalizedGroupTable[REG_LOCALIZED_GROUP].cInfo;
|
|
PLOCALIZED_NAME_INFO pInfo =
|
|
LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo;
|
|
|
|
assert(CRYPT_LOCALIZED_NAME_ENCODING_TYPE == dwEncodingType);
|
|
assert(0 == _stricmp(CRYPT_OID_FIND_LOCALIZED_NAME_FUNC, pszFuncName));
|
|
assert(0 == _stricmp(CRYPT_LOCALIZED_NAME_OID, pszOID));
|
|
|
|
while (cValue--) {
|
|
if (REG_SZ == rgdwValueType[cValue]) {
|
|
LPCWSTR pwszLocalizedName = (LPCWSTR) rgpbValueData[cValue];
|
|
DWORD cchLocalizedName;
|
|
DWORD cbLocalizedName;
|
|
LPCWSTR pwszCryptName = rgpwszValueName[cValue];
|
|
DWORD cbCryptName;
|
|
|
|
LPWSTR pwszBothNames;
|
|
PLOCALIZED_NAME_INFO pNewInfo;
|
|
|
|
// Check for empty name string
|
|
cchLocalizedName = wcslen(pwszLocalizedName);
|
|
if (0 == cchLocalizedName)
|
|
continue;
|
|
|
|
cbLocalizedName = (cchLocalizedName + 1) * sizeof(WCHAR);
|
|
cbCryptName = (wcslen(pwszCryptName) + 1) * sizeof(WCHAR);
|
|
|
|
if (NULL == (pwszBothNames = (LPWSTR) OIDInfoAlloc(
|
|
cbLocalizedName + cbCryptName)))
|
|
goto OutOfMemory;
|
|
|
|
if (NULL == (pNewInfo = (PLOCALIZED_NAME_INFO) OIDInfoRealloc(
|
|
pInfo, (cInfo + 1) * sizeof(LOCALIZED_NAME_INFO)))) {
|
|
OIDInfoFree(pwszBothNames);
|
|
goto OutOfMemory;
|
|
}
|
|
pInfo = pNewInfo;
|
|
pInfo[cInfo].pwszLocalizedName = (LPCWSTR) pwszBothNames;
|
|
memcpy(pwszBothNames, pwszLocalizedName, cbLocalizedName);
|
|
pwszBothNames =
|
|
(LPWSTR) ((BYTE *) pwszBothNames + cbLocalizedName);
|
|
pInfo[cInfo].pwszCryptName = (LPCWSTR) pwszBothNames;
|
|
memcpy(pwszBothNames, pwszCryptName, cbCryptName);
|
|
cInfo++;
|
|
}
|
|
}
|
|
fResult = TRUE;
|
|
|
|
CommonReturn:
|
|
LocalizedGroupTable[REG_LOCALIZED_GROUP].cInfo = cInfo;
|
|
LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo = pInfo;
|
|
return fResult;
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
TRACE_ERROR(OutOfMemory)
|
|
}
|
|
|
|
static void LoadPredefinedNameResources()
|
|
{
|
|
for (DWORD i = 0; i < PREDEFINED_NAME_CNT; i++) {
|
|
LPWSTR pwszLocalizedName;
|
|
|
|
// Note, the following always returns a non-NULL string pointer.
|
|
pwszLocalizedName = AllocAndLoadOIDNameString(
|
|
PredefinedNameTable[i].uIDLocalizedName);
|
|
if (L'\0' == *pwszLocalizedName)
|
|
pwszLocalizedName = NULL;
|
|
PredefinedNameTable[i].pwszLocalizedName = (LPCWSTR) pwszLocalizedName;
|
|
}
|
|
}
|
|
|
|
static void LoadLocalizedNamesFromRegAndResources()
|
|
{
|
|
if (fLoadedLocalizedNames)
|
|
return;
|
|
|
|
EnterCriticalSection(&LoadFromRegCriticalSection);
|
|
if (!fLoadedLocalizedNames) {
|
|
CryptEnumOIDFunction(
|
|
CRYPT_LOCALIZED_NAME_ENCODING_TYPE,
|
|
CRYPT_OID_FIND_LOCALIZED_NAME_FUNC,
|
|
CRYPT_LOCALIZED_NAME_OID,
|
|
0, // dwFlags
|
|
NULL, // pvArg
|
|
EnumRegLocalizedNamesCallback
|
|
);
|
|
LoadPredefinedNameResources();
|
|
fLoadedLocalizedNames = TRUE;
|
|
}
|
|
LeaveCriticalSection(&LoadFromRegCriticalSection);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Find the localized name for the specified name. For example, find the
|
|
// localized name for the "Root" system store name. A case insensitive
|
|
// string comparison is done.
|
|
//
|
|
// Returns NULL if unable to find the the specified name.
|
|
//--------------------------------------------------------------------------
|
|
LPCWSTR
|
|
WINAPI
|
|
CryptFindLocalizedName(
|
|
IN LPCWSTR pwszCryptName
|
|
)
|
|
{
|
|
if (NULL == pwszCryptName || L'\0' == *pwszCryptName)
|
|
return NULL;
|
|
|
|
LoadLocalizedNamesFromRegAndResources();
|
|
|
|
for (DWORD i = 0; i < LOCALIZED_GROUP_CNT; i++) {
|
|
DWORD cInfo = LocalizedGroupTable[i].cInfo;
|
|
PLOCALIZED_NAME_INFO pInfo = LocalizedGroupTable[i].rgInfo;
|
|
for ( ; cInfo > 0; cInfo--, pInfo++) {
|
|
if (0 == _wcsicmp(pwszCryptName, pInfo->pwszCryptName))
|
|
return pInfo->pwszLocalizedName;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//+=========================================================================
|
|
// DS Group Functions
|
|
//==========================================================================
|
|
|
|
// certcli.dll has the helper function for getting the LDAP URL to the
|
|
// OID info stored in the DS.
|
|
|
|
#define sz_CERTCLI_DLL "certcli.dll"
|
|
#define sz_CAOIDGetLdapURL "CAOIDGetLdapURL"
|
|
#define sz_CAOIDFreeLdapURL "CAOIDFreeLdapURL"
|
|
|
|
typedef HRESULT (WINAPI *PFN_CA_OID_GET_LDAP_URL)(
|
|
IN DWORD dwType,
|
|
IN DWORD dwFlag,
|
|
OUT LPWSTR *ppwszURL
|
|
);
|
|
|
|
typedef HRESULT (WINAPI *PFN_CA_OID_FREE_LDAP_URL)(
|
|
IN LPCWSTR pwszURL
|
|
);
|
|
|
|
|
|
#if 1
|
|
//+-------------------------------------------------------------------------
|
|
// Gets the LDAP URL for and then uses to retrieve the OID info stored
|
|
// in the DS.
|
|
//
|
|
// Returns NULL if unable to do a successful LDAP retrieval.
|
|
//
|
|
// If the OID object doesn't exist in the directory, returns FALSE with
|
|
// LastError == ERROR_FILE_NOT_FOUND.
|
|
//
|
|
// Assumption: not in DsCriticalSection
|
|
//--------------------------------------------------------------------------
|
|
static PCRYPT_BLOB_ARRAY RetrieveDsGroupByLdapUrl()
|
|
{
|
|
PCRYPT_BLOB_ARRAY pcba = NULL;
|
|
HRESULT hr;
|
|
LPWSTR pwszUrl = NULL;
|
|
HMODULE hDll = NULL;
|
|
PFN_CA_OID_GET_LDAP_URL pfnCAOIDGetLdapURL = NULL;
|
|
PFN_CA_OID_FREE_LDAP_URL pfnCAOIDFreeLdapURL = NULL;
|
|
|
|
if (!ChainIsConnected())
|
|
goto NotConnected;
|
|
|
|
if (NULL == (hDll = LoadLibraryA(sz_CERTCLI_DLL)))
|
|
goto LoadCertCliDllError;
|
|
|
|
if (NULL == (pfnCAOIDGetLdapURL =
|
|
(PFN_CA_OID_GET_LDAP_URL) GetProcAddress(hDll,
|
|
sz_CAOIDGetLdapURL)))
|
|
goto CAOIDGetLdapURLProcAddressError;
|
|
|
|
if (NULL == (pfnCAOIDFreeLdapURL =
|
|
(PFN_CA_OID_FREE_LDAP_URL) GetProcAddress(hDll,
|
|
sz_CAOIDFreeLdapURL)))
|
|
goto CAOIDFreeLdapURLProcAddressError;
|
|
|
|
hr = pfnCAOIDGetLdapURL(
|
|
CERT_OID_TYPE_ALL,
|
|
0, // dwFlags
|
|
&pwszUrl
|
|
);
|
|
if (S_OK != hr)
|
|
goto CAOIDGetLdapURLError;
|
|
|
|
if (!ChainRetrieveObjectByUrlW (
|
|
pwszUrl,
|
|
NULL, // pszObjectOid,
|
|
CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
|
|
CRYPT_WIRE_ONLY_RETRIEVAL |
|
|
CRYPT_DONT_CACHE_RESULT |
|
|
CRYPT_OFFLINE_CHECK_RETRIEVAL |
|
|
CRYPT_LDAP_SIGN_RETRIEVAL |
|
|
CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE,
|
|
DS_LDAP_TIMEOUT,
|
|
(LPVOID*) &pcba,
|
|
NULL, // hAsyncRetrieve,
|
|
NULL, // pCredentials,
|
|
NULL, // pvVerify,
|
|
NULL // pAuxInfo
|
|
)) {
|
|
DWORD dwErr = GetLastError();
|
|
if (ERROR_FILE_NOT_FOUND == dwErr || CRYPT_E_NOT_FOUND == dwErr)
|
|
goto NoDsOIDObject;
|
|
else
|
|
goto RetrieveObjectByUrlError;
|
|
}
|
|
|
|
assert(pcba);
|
|
|
|
CommonReturn:
|
|
if (hDll) {
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if (pfnCAOIDFreeLdapURL && pwszUrl)
|
|
pfnCAOIDFreeLdapURL(pwszUrl);
|
|
|
|
FreeLibrary(hDll);
|
|
SetLastError(dwErr);
|
|
}
|
|
return pcba;
|
|
ErrorReturn:
|
|
assert(NULL == pcba);
|
|
goto CommonReturn;
|
|
|
|
SET_ERROR(LoadCertCliDllError, ERROR_FILE_NOT_FOUND)
|
|
SET_ERROR(CAOIDGetLdapURLProcAddressError, ERROR_FILE_NOT_FOUND)
|
|
SET_ERROR(CAOIDFreeLdapURLProcAddressError, ERROR_FILE_NOT_FOUND)
|
|
SET_ERROR_VAR(CAOIDGetLdapURLError, hr)
|
|
SET_ERROR(NotConnected, ERROR_NOT_CONNECTED)
|
|
SET_ERROR(NoDsOIDObject, ERROR_FILE_NOT_FOUND)
|
|
TRACE_ERROR(RetrieveObjectByUrlError)
|
|
}
|
|
|
|
#else
|
|
|
|
// Hard coded URL and credentials for testing
|
|
|
|
static PCRYPT_BLOB_ARRAY RetrieveDsGroupByLdapUrl()
|
|
{
|
|
PCRYPT_BLOB_ARRAY pcba = NULL;
|
|
|
|
CRYPT_CREDENTIALS Credentials;
|
|
CRYPT_PASSWORD_CREDENTIALSA PasswordCredentials;
|
|
|
|
// This gets overwritten by logic in cryptnet.dll
|
|
// char szUsername[] = "domain\\username";
|
|
char szUsername[] = "jettdom\\administrator";
|
|
|
|
PasswordCredentials.cbSize = sizeof( PasswordCredentials );
|
|
PasswordCredentials.pszUsername = szUsername;
|
|
// PasswordCredentials.pszPassword = "password";
|
|
PasswordCredentials.pszPassword = "";
|
|
|
|
Credentials.cbSize = sizeof( Credentials );
|
|
Credentials.pszCredentialsOid = CREDENTIAL_OID_PASSWORD_CREDENTIALS_A;
|
|
Credentials.pvCredentials = (LPVOID)&PasswordCredentials;
|
|
|
|
if (!ChainIsConnected())
|
|
goto NotConnected;
|
|
|
|
|
|
if (!ChainRetrieveObjectByUrlW (
|
|
L"ldap://jettdomdc/CN=OID,CN=Public Key Services,CN=Services,CN=Configuration,DC=jettdom,DC=nttest,DC=microsoft,DC=com?msPKI-OIDLocalizedName,displayName,msPKI-Cert-Template-OID,flags?one",
|
|
NULL, // pszObjectOid,
|
|
CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
|
|
CRYPT_WIRE_ONLY_RETRIEVAL |
|
|
CRYPT_DONT_CACHE_RESULT |
|
|
CRYPT_OFFLINE_CHECK_RETRIEVAL |
|
|
CRYPT_LDAP_SIGN_RETRIEVAL |
|
|
CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE,
|
|
DS_LDAP_TIMEOUT,
|
|
(LPVOID*) &pcba,
|
|
NULL, // hAsyncRetrieve,
|
|
&Credentials,
|
|
NULL, // pvVerify,
|
|
NULL // pAuxInfo
|
|
)) {
|
|
if (ERROR_FILE_NOT_FOUND == GetLastError())
|
|
goto NoDsOIDObject;
|
|
else
|
|
goto RetrieveObjectByUrlError;
|
|
}
|
|
|
|
assert(pcba);
|
|
|
|
CommonReturn:
|
|
return pcba;
|
|
ErrorReturn:
|
|
assert(NULL == pcba);
|
|
goto CommonReturn;
|
|
|
|
SET_ERROR(NotConnected, ERROR_NOT_CONNECTED)
|
|
TRACE_ERROR(NoDsOIDObject)
|
|
TRACE_ERROR(RetrieveObjectByUrlError)
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Frees the DS groups
|
|
//
|
|
// Assumption: only called at ProcessDetach
|
|
//--------------------------------------------------------------------------
|
|
static void FreeDsGroups()
|
|
{
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO *ppInfo;
|
|
|
|
cInfo = DsGroup.cInfo;
|
|
ppInfo = DsGroup.rgpInfo;
|
|
for ( ; cInfo > 0; cInfo--, ppInfo++)
|
|
OIDInfoFree((PCRYPT_OID_INFO) *ppInfo);
|
|
OIDInfoFree(DsGroup.rgpInfo);
|
|
|
|
cInfo = DsDeletedGroup.cInfo;
|
|
ppInfo = DsDeletedGroup.rgpInfo;
|
|
for ( ; cInfo > 0; cInfo--, ppInfo++)
|
|
OIDInfoFree((PCRYPT_OID_INFO) *ppInfo);
|
|
OIDInfoFree(DsDeletedGroup.rgpInfo);
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Adds the OID info entries to the specified DS group
|
|
//
|
|
// Assumption: already in DsCriticalSection
|
|
//--------------------------------------------------------------------------
|
|
static BOOL AddDsOIDInfo(
|
|
IN PCCRYPT_OID_INFO *ppAddInfo,
|
|
IN DWORD cAddInfo,
|
|
IN OUT PDS_GROUP_ENTRY pGroup
|
|
)
|
|
{
|
|
PCCRYPT_OID_INFO *ppInfo;
|
|
assert(cAddInfo && ppAddInfo && *ppAddInfo);
|
|
|
|
if (NULL == (ppInfo = (PCCRYPT_OID_INFO *) OIDInfoRealloc(
|
|
pGroup->rgpInfo,
|
|
(pGroup->cInfo + cAddInfo) * sizeof(PCCRYPT_OID_INFO))))
|
|
return FALSE;
|
|
|
|
pGroup->rgpInfo = ppInfo;
|
|
|
|
ppInfo = &ppInfo[pGroup->cInfo];
|
|
pGroup->cInfo += cAddInfo;
|
|
for ( ; 0 < cAddInfo; cAddInfo --, ppAddInfo++, ppInfo++)
|
|
*ppInfo = *ppAddInfo;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Moves the OID info entries from one DS group to another DS group
|
|
//
|
|
// Assumption: already in DsCriticalSection
|
|
//--------------------------------------------------------------------------
|
|
static BOOL MoveDsOIDInfo(
|
|
IN DWORD dwInfoIndex,
|
|
IN DWORD cMoveInfo,
|
|
IN OUT PDS_GROUP_ENTRY pSrcGroup,
|
|
IN OUT PDS_GROUP_ENTRY pDstGroup
|
|
)
|
|
{
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO *ppInfo;
|
|
DWORD i, j;
|
|
|
|
if (0 == cMoveInfo)
|
|
return TRUE;
|
|
|
|
assert(dwInfoIndex + cMoveInfo <= pSrcGroup->cInfo);
|
|
|
|
if (!AddDsOIDInfo(
|
|
&pSrcGroup->rgpInfo[dwInfoIndex],
|
|
cMoveInfo,
|
|
pDstGroup
|
|
))
|
|
return FALSE;
|
|
|
|
// Move all remaining infos down
|
|
cInfo = pSrcGroup->cInfo;
|
|
ppInfo = pSrcGroup->rgpInfo;
|
|
for (i = dwInfoIndex, j = i + cMoveInfo; j < cInfo; i++, j++)
|
|
ppInfo[i] = ppInfo[j];
|
|
|
|
pSrcGroup->cInfo = cInfo - cMoveInfo;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Creates the OID info by converting the LDAP DS attribute octets.
|
|
//
|
|
// If any of the cb's == 0 or not a valid converted group type, returns TRUE
|
|
// with *ppInfo = NULL
|
|
//--------------------------------------------------------------------------
|
|
static BOOL CreateDsOIDInfo(
|
|
IN BYTE *pbOID,
|
|
IN DWORD cbOID,
|
|
IN BYTE *pbName,
|
|
IN DWORD cbName,
|
|
IN BYTE *pbGroupId,
|
|
IN DWORD cbGroupId,
|
|
OUT PCCRYPT_OID_INFO *ppInfo
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
PCRYPT_OID_INFO pInfo = NULL;
|
|
char szType[2];
|
|
DWORD dwType;
|
|
DWORD dwGroupId;
|
|
|
|
int cchName;
|
|
LPWSTR pwszName;
|
|
LPSTR pszOID;
|
|
DWORD cbExtra;
|
|
|
|
*ppInfo = NULL;
|
|
|
|
if (0 == cbOID || 0 == cbName || 1 != cbGroupId)
|
|
return TRUE;
|
|
|
|
// Convert the Type bytes to the GroupId and see if a valid DS OID group
|
|
szType[0] = (char) *pbGroupId;
|
|
szType[1] = '\0';
|
|
dwType = 0;
|
|
dwType = (DWORD) atol(szType);
|
|
|
|
switch (dwType) {
|
|
case CERT_OID_TYPE_TEMPLATE:
|
|
dwGroupId = CRYPT_TEMPLATE_OID_GROUP_ID;
|
|
break;
|
|
case CERT_OID_TYPE_ISSUER_POLICY:
|
|
dwGroupId = CRYPT_POLICY_OID_GROUP_ID;
|
|
break;
|
|
case CERT_OID_TYPE_APPLICATION_POLICY:
|
|
dwGroupId = CRYPT_ENHKEY_USAGE_OID_GROUP_ID;
|
|
break;
|
|
default:
|
|
return TRUE;
|
|
}
|
|
|
|
// The name is a UTF8 encoded string
|
|
|
|
cchName = UTF8ToWideChar(
|
|
(LPSTR) pbName,
|
|
cbName,
|
|
NULL, // lpWideCharStr
|
|
0 // cchWideChar
|
|
);
|
|
|
|
if (1 > cchName)
|
|
return TRUE;
|
|
|
|
cbExtra = (cchName + 1) * sizeof(WCHAR) + (cbOID + 1);
|
|
|
|
pInfo = (PCRYPT_OID_INFO) OIDInfoAlloc(sizeof(CRYPT_OID_INFO) + cbExtra);
|
|
if (NULL == pInfo)
|
|
goto OutOfMemory;
|
|
memset(pInfo, 0, sizeof(CRYPT_OID_INFO));
|
|
|
|
pInfo->cbSize = sizeof(CRYPT_OID_INFO);
|
|
pInfo->dwGroupId = dwGroupId;
|
|
|
|
pwszName = (LPWSTR) &pInfo[1];
|
|
pInfo->pwszName = (LPCWSTR) pwszName;
|
|
cchName = UTF8ToWideChar(
|
|
(LPSTR) pbName,
|
|
cbName,
|
|
pwszName,
|
|
cchName
|
|
);
|
|
|
|
if (1 > cchName)
|
|
goto UTF8ToWideCharError;
|
|
|
|
pwszName[cchName] = L'\0';
|
|
|
|
pszOID = (LPSTR) (pwszName + (cchName + 1));
|
|
pInfo->pszOID = (LPCSTR) pszOID;
|
|
memcpy(pszOID, pbOID, cbOID);
|
|
pszOID[cbOID] = '\0';
|
|
|
|
|
|
*ppInfo = (PCCRYPT_OID_INFO) pInfo;
|
|
fResult = TRUE;
|
|
CommonReturn:
|
|
return fResult;
|
|
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR(OutOfMemory)
|
|
SET_ERROR(UTF8ToWideCharError, ERROR_INVALID_DATA)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Creates the OID info entry corresponding to the LDAP DS attribute octets.
|
|
//
|
|
// If the OID info entry already exists in the DsDeletedGroup, then, the
|
|
// OID info entry is moved from DsDeletedGroup to DsGroup. Otherwise, the
|
|
// created OID entry is added to the DsGroup.
|
|
//
|
|
// Assumption: already in DsCriticalSection
|
|
//--------------------------------------------------------------------------
|
|
static BOOL CreateAndAddDsOIDInfo(
|
|
IN BYTE *pbOID,
|
|
IN DWORD cbOID,
|
|
IN BYTE *pbName,
|
|
IN DWORD cbName,
|
|
IN BYTE *pbGroupId,
|
|
IN DWORD cbGroupId
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
PCCRYPT_OID_INFO pInfo = NULL;
|
|
|
|
DWORD cDeletedInfo;
|
|
PCCRYPT_OID_INFO *ppDeletedInfo;
|
|
DWORD i;
|
|
|
|
fResult = CreateDsOIDInfo(
|
|
pbOID,
|
|
cbOID,
|
|
pbName,
|
|
cbName,
|
|
pbGroupId,
|
|
cbGroupId,
|
|
&pInfo
|
|
);
|
|
|
|
if (NULL == pInfo)
|
|
// Either the create failed or not a valid DS OID group
|
|
return fResult;
|
|
|
|
// See if we have an entry in the DS deleted group
|
|
|
|
cDeletedInfo = DsDeletedGroup.cInfo;
|
|
ppDeletedInfo = DsDeletedGroup.rgpInfo;
|
|
for (i = 0; i < cDeletedInfo; i++) {
|
|
PCCRYPT_OID_INFO pDeletedInfo = ppDeletedInfo[i];
|
|
|
|
if (pInfo->dwGroupId == pDeletedInfo->dwGroupId &&
|
|
0 == strcmp(pInfo->pszOID, pDeletedInfo->pszOID) &&
|
|
0 == wcscmp(pInfo->pwszName, pDeletedInfo->pwszName))
|
|
break;
|
|
}
|
|
|
|
if (i < cDeletedInfo) {
|
|
if (!MoveDsOIDInfo(
|
|
i,
|
|
1, // cInfo
|
|
&DsDeletedGroup,
|
|
&DsGroup
|
|
))
|
|
goto MoveDsOIDInfoError;
|
|
OIDInfoFree((PCRYPT_OID_INFO) pInfo);
|
|
} else {
|
|
if (!AddDsOIDInfo(&pInfo, 1, &DsGroup))
|
|
goto AddDsOIDInfoError;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CommonReturn:
|
|
return fResult;
|
|
|
|
ErrorReturn:
|
|
OIDInfoFree((PCRYPT_OID_INFO) pInfo);
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR(MoveDsOIDInfoError)
|
|
TRACE_ERROR(AddDsOIDInfoError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Allocates and converts UNICODE string to ASCII.
|
|
//--------------------------------------------------------------------------
|
|
static LPSTR AllocAndWszToSz(
|
|
IN LPCWSTR pwsz
|
|
)
|
|
{
|
|
int cchMultiByte;
|
|
LPSTR psz = NULL;
|
|
|
|
cchMultiByte = WideCharToMultiByte(
|
|
CP_ACP,
|
|
0, // dwFlags
|
|
pwsz,
|
|
-1,
|
|
NULL, // psz,
|
|
0, // cchMultiByte
|
|
NULL, // lpDefaultChar
|
|
NULL // lpfUsedDefaultChar
|
|
);
|
|
|
|
if (1 < cchMultiByte) {
|
|
psz = (LPSTR) OIDInfoAlloc(cchMultiByte);
|
|
|
|
if (NULL != psz) {
|
|
cchMultiByte = WideCharToMultiByte(
|
|
CP_ACP,
|
|
0, // dwFlags
|
|
pwsz,
|
|
-1,
|
|
psz,
|
|
cchMultiByte,
|
|
NULL, // lpDefaultChar
|
|
NULL // lpfUsedDefaultChar
|
|
);
|
|
if (1 > cchMultiByte) {
|
|
OIDInfoFree(psz);
|
|
psz = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return psz;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------------------
|
|
// Helper functions to thunk APIs which don't exist on downlevels.
|
|
// oidinfo.obj is statically linked in with xenroll, which has to work on
|
|
// all downlevels (win9x, NT4, W2K, XP). Any functions which aren't supported
|
|
// on these platforms need to be thunked here to avoid a dependency violation.
|
|
//-------------------------------------------------------------------------------
|
|
|
|
#define sz_KERNEL32_DLL "kernel32.dll"
|
|
#define sz_GetSystemDefaultUILanguage "GetSystemDefaultUILanguage"
|
|
#define sz_GetUserDefaultUILanguage "GetUserDefaultUILanguage"
|
|
|
|
typedef LANGID (WINAPI *PFNGetSystemDefaultUILanguage) (
|
|
void
|
|
);
|
|
|
|
typedef LANGID (WINAPI *PFNGetUserDefaultUILanguage) (
|
|
void
|
|
);
|
|
|
|
//+------------------------------------------------------------------------------
|
|
// Helper function to thunk GetSystemDefaultUILanguage(). If this API isn't
|
|
// present, falls back to GetSystemDefaultLangID().
|
|
//------------------------------------------------------------------------------
|
|
static LANGID WINAPI MyGetSystemDefaultUILanguage(void)
|
|
{
|
|
HMODULE hKernel32 = NULL;
|
|
LANGID langidRetval;
|
|
PFNGetSystemDefaultUILanguage pfnGetSystemDefaultUILanguage = NULL;
|
|
|
|
hKernel32 = LoadLibraryA(sz_KERNEL32_DLL);
|
|
if (NULL != hKernel32) {
|
|
pfnGetSystemDefaultUILanguage = (PFNGetSystemDefaultUILanguage)GetProcAddress(hKernel32, sz_GetSystemDefaultUILanguage);
|
|
}
|
|
|
|
if (NULL != pfnGetSystemDefaultUILanguage) {
|
|
langidRetval = pfnGetSystemDefaultUILanguage();
|
|
} else {
|
|
langidRetval = GetSystemDefaultLangID();
|
|
}
|
|
|
|
if (NULL != hKernel32) {
|
|
FreeLibrary(hKernel32);
|
|
}
|
|
|
|
return langidRetval;
|
|
}
|
|
|
|
//+------------------------------------------------------------------------------
|
|
// Helper function to thunk GetUserDefaultUILanguage(). If this API isn't
|
|
// present, falls back to GetUserDefaultLangID().
|
|
//------------------------------------------------------------------------------
|
|
static LANGID WINAPI MyGetUserDefaultUILanguage(void)
|
|
{
|
|
HMODULE hKernel32 = NULL;
|
|
LANGID langidRetval;
|
|
PFNGetUserDefaultUILanguage pfnGetUserDefaultUILanguage = NULL;
|
|
|
|
hKernel32 = LoadLibraryA(sz_KERNEL32_DLL);
|
|
if (NULL != hKernel32) {
|
|
pfnGetUserDefaultUILanguage = (PFNGetUserDefaultUILanguage)GetProcAddress(hKernel32, sz_GetUserDefaultUILanguage);
|
|
}
|
|
|
|
if (NULL != pfnGetUserDefaultUILanguage) {
|
|
langidRetval = pfnGetUserDefaultUILanguage();
|
|
} else {
|
|
// Use GetSystemDefaultLangID for fallback, even in the user case.
|
|
// From weiwu: "GetUserDefaultLangID is mostly for standards and formats;
|
|
// it shouldn't be used as the UI language fallback."
|
|
langidRetval = GetSystemDefaultLangID();
|
|
}
|
|
|
|
if (NULL != hKernel32) {
|
|
FreeLibrary(hKernel32);
|
|
}
|
|
|
|
return langidRetval;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Loads the DS group by doing an LDAP URL retrieval and
|
|
// converting the DS attribute octets into the OID info entries.
|
|
//
|
|
// Do the load on the first call. Do subsequent reloads after
|
|
// DS_RETRIEVAL_DELTA_SECONDS has elapsed since a successful load.
|
|
//
|
|
// Assumption: not in DsCriticalSection
|
|
//--------------------------------------------------------------------------
|
|
static void LoadDsGroup()
|
|
{
|
|
FILETIME CurrentTime;
|
|
LONG lCmp;
|
|
|
|
PCRYPT_BLOB_ARRAY pcba = NULL;
|
|
LPSTR pszOIDAttr = NULL;
|
|
LPSTR pszNameAttr = NULL;
|
|
LPSTR pszLocalizedNameAttr = NULL;
|
|
LPSTR pszGroupAttr = NULL;
|
|
|
|
LANGID SystemDefaultLangID = 0;
|
|
|
|
LPCSTR pszPrevIndex; // not allocated
|
|
BYTE *pbOID;
|
|
DWORD cbOID;
|
|
BYTE *pbName;
|
|
DWORD cbName;
|
|
BYTE *pbLocalizedName;
|
|
DWORD cbLocalizedName;
|
|
BYTE *pbGroupId;
|
|
DWORD cbGroupId;
|
|
DWORD i;
|
|
|
|
GetSystemTimeAsFileTime(&CurrentTime);
|
|
EnterCriticalSection(&DsCriticalSection);
|
|
lCmp = CompareFileTime(&DsNextUpdateTime, &CurrentTime);
|
|
LeaveCriticalSection(&DsCriticalSection);
|
|
|
|
if (0 < lCmp)
|
|
// Current time is before the next update time
|
|
return;
|
|
|
|
if (NULL == (pcba = RetrieveDsGroupByLdapUrl()) &&
|
|
ERROR_FILE_NOT_FOUND != GetLastError())
|
|
return;
|
|
|
|
EnterCriticalSection(&DsCriticalSection);
|
|
|
|
// Move all the Ds group entries to the deleted list. As we iterate
|
|
// through the retrieved LDAP entries, most if not all of the entries
|
|
// in the deleted group will be moved back.
|
|
if (!MoveDsOIDInfo(
|
|
0, // dwInfoIndex
|
|
DsGroup.cInfo,
|
|
&DsGroup,
|
|
&DsDeletedGroup
|
|
))
|
|
goto MoveDsGroupOIDInfoError;
|
|
|
|
if (NULL == pcba)
|
|
goto NoOIDObjectReturn;
|
|
|
|
pszOIDAttr = AllocAndWszToSz(OID_PROP_OID);
|
|
pszNameAttr = AllocAndWszToSz(OID_PROP_DISPLAY_NAME);
|
|
pszLocalizedNameAttr = AllocAndWszToSz(OID_PROP_LOCALIZED_NAME);
|
|
pszGroupAttr = AllocAndWszToSz(OID_PROP_TYPE);
|
|
if (NULL == pszOIDAttr || NULL == pszNameAttr ||
|
|
NULL == pszLocalizedNameAttr|| NULL == pszGroupAttr)
|
|
goto OutOfMemory;
|
|
|
|
pszPrevIndex = "";
|
|
pbOID = NULL;
|
|
cbOID = 0;
|
|
pbName = NULL;
|
|
cbName = 0;
|
|
pbLocalizedName = NULL;
|
|
cbLocalizedName = 0;
|
|
pbGroupId = NULL;
|
|
cbGroupId = 0;
|
|
for (i = 0; i < pcba->cBlob; i++ ) {
|
|
PBYTE pb = pcba->rgBlob[i].pbData;
|
|
DWORD cb = pcba->rgBlob[i].cbData;
|
|
|
|
DWORD cbPrefix;
|
|
LPCSTR pszIndex;
|
|
LPCSTR pszAttr;
|
|
|
|
pszIndex = (LPCSTR) pb;
|
|
cbPrefix = strlen(pszIndex) + 1;
|
|
pb += cbPrefix;
|
|
cb -= cbPrefix;
|
|
|
|
pszAttr = (LPCSTR) pb;
|
|
cbPrefix = strlen(pszAttr) + 1;
|
|
pb += cbPrefix;
|
|
cb -= cbPrefix;
|
|
|
|
if (0 != strcmp(pszIndex, pszPrevIndex)) {
|
|
if (!CreateAndAddDsOIDInfo(
|
|
pbOID,
|
|
cbOID,
|
|
cbLocalizedName ? pbLocalizedName : pbName,
|
|
cbLocalizedName ? cbLocalizedName : cbName,
|
|
pbGroupId,
|
|
cbGroupId
|
|
))
|
|
goto CreateAndAddDsOIDInfoError;
|
|
pszPrevIndex = pszIndex;
|
|
pbOID = NULL;
|
|
cbOID = 0;
|
|
pbName = NULL;
|
|
cbName = 0;
|
|
pbLocalizedName = NULL;
|
|
cbLocalizedName = 0;
|
|
pbGroupId = NULL;
|
|
cbGroupId = 0;
|
|
}
|
|
|
|
if (0 == _stricmp(pszAttr, pszOIDAttr)) {
|
|
pbOID = pb;
|
|
cbOID = cb;
|
|
} else if (0 == _stricmp(pszAttr, pszNameAttr)) {
|
|
pbName = pb;
|
|
cbName = cb;
|
|
} else if (0 == _stricmp(pszAttr, pszLocalizedNameAttr)) {
|
|
// The LocalizedName consists of:
|
|
// "%d,%s", LangID, pszUTF8Name (Name isn't NULL terminated)
|
|
if (0 == cbLocalizedName) {
|
|
LPCSTR pszLangID;
|
|
|
|
// Search for the ',' delimiter and convert to a \0
|
|
pszLangID = (LPCSTR) pb;
|
|
for ( ; 0 < cb; pb++, cb--) {
|
|
if (',' == *pb) {
|
|
*pb = 0;
|
|
pb++;
|
|
cb--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (0 < cb) {
|
|
LANGID LangID = 0;
|
|
|
|
LangID = (LANGID) strtoul(pszLangID, NULL, 10);
|
|
if (0 != LangID) {
|
|
if (0 == SystemDefaultLangID) {
|
|
SystemDefaultLangID = MyGetUserDefaultUILanguage();
|
|
if (0 == SystemDefaultLangID)
|
|
SystemDefaultLangID =
|
|
MyGetSystemDefaultUILanguage();
|
|
}
|
|
if (LangID == SystemDefaultLangID) {
|
|
cbLocalizedName = cb;
|
|
pbLocalizedName = pb;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (0 == _stricmp(pszAttr, pszGroupAttr)) {
|
|
pbGroupId = pb;
|
|
cbGroupId = cb;
|
|
}
|
|
}
|
|
|
|
if (!CreateAndAddDsOIDInfo(
|
|
pbOID,
|
|
cbOID,
|
|
cbLocalizedName ? pbLocalizedName : pbName,
|
|
cbLocalizedName ? cbLocalizedName : cbName,
|
|
pbGroupId,
|
|
cbGroupId
|
|
))
|
|
goto CreateAndAddDsOIDInfoError;
|
|
|
|
|
|
NoOIDObjectReturn:
|
|
I_CryptIncrementFileTimeBySeconds(
|
|
&CurrentTime,
|
|
DS_RETRIEVAL_DELTA_SECONDS,
|
|
&DsNextUpdateTime
|
|
);
|
|
|
|
CommonReturn:
|
|
LeaveCriticalSection(&DsCriticalSection);
|
|
|
|
OIDInfoFree(pszOIDAttr);
|
|
OIDInfoFree(pszNameAttr);
|
|
OIDInfoFree(pszLocalizedNameAttr);
|
|
OIDInfoFree(pszGroupAttr);
|
|
if (pcba)
|
|
CryptMemFree(pcba);
|
|
return;
|
|
|
|
ErrorReturn:
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR(OutOfMemory)
|
|
TRACE_ERROR(MoveDsGroupOIDInfoError)
|
|
TRACE_ERROR(CreateAndAddDsOIDInfoError)
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// The DS only contains the ENHKEY, POLICY and TEMPLATE OID groups.
|
|
//--------------------------------------------------------------------------
|
|
static inline BOOL IsDsGroup(
|
|
IN DWORD dwGroupId
|
|
)
|
|
{
|
|
if (0 == dwGroupId ||
|
|
CRYPT_ENHKEY_USAGE_OID_GROUP_ID == dwGroupId ||
|
|
CRYPT_POLICY_OID_GROUP_ID == dwGroupId ||
|
|
CRYPT_TEMPLATE_OID_GROUP_ID == dwGroupId
|
|
)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// The DS only contains OID and NAME strings
|
|
//--------------------------------------------------------------------------
|
|
static inline BOOL IsDsKeyType(
|
|
IN DWORD dwKeyType
|
|
)
|
|
{
|
|
if (CRYPT_OID_INFO_OID_KEY == dwKeyType ||
|
|
CRYPT_OID_INFO_NAME_KEY == dwKeyType
|
|
)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Search the DS group according to the specified dwKeyType.
|
|
//--------------------------------------------------------------------------
|
|
static PCCRYPT_OID_INFO SearchDsGroup(
|
|
IN DWORD dwKeyType,
|
|
IN void *pvKey,
|
|
IN DWORD dwGroupId
|
|
)
|
|
{
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO *ppInfo;
|
|
PCCRYPT_OID_INFO pInfo = NULL;
|
|
|
|
if (!IsDsGroup(dwGroupId) || !IsDsKeyType(dwKeyType))
|
|
return NULL;
|
|
|
|
LoadDsGroup();
|
|
|
|
EnterCriticalSection(&DsCriticalSection);
|
|
|
|
cInfo = DsGroup.cInfo;
|
|
ppInfo = DsGroup.rgpInfo;
|
|
for ( ; cInfo > 0; cInfo--, ppInfo++) {
|
|
pInfo = *ppInfo;
|
|
if (CompareOIDInfo(
|
|
dwKeyType,
|
|
pvKey,
|
|
dwGroupId,
|
|
pInfo
|
|
))
|
|
break;
|
|
}
|
|
|
|
if (0 == cInfo)
|
|
pInfo = NULL;
|
|
|
|
LeaveCriticalSection(&DsCriticalSection);
|
|
|
|
return pInfo;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Enumerate the DS group.
|
|
//--------------------------------------------------------------------------
|
|
static BOOL EnumDsGroup(
|
|
IN DWORD dwGroupId,
|
|
IN void *pvArg,
|
|
IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
|
|
)
|
|
{
|
|
BOOL fResult;
|
|
DWORD cInfo;
|
|
PCCRYPT_OID_INFO *ppInfo = NULL;
|
|
DWORD i;
|
|
|
|
if (!IsDsGroup(dwGroupId))
|
|
return TRUE;
|
|
|
|
LoadDsGroup();
|
|
|
|
EnterCriticalSection(&DsCriticalSection);
|
|
|
|
// Make a copy of DS group OID info pointers while within the
|
|
// DS critical section
|
|
|
|
cInfo = DsGroup.cInfo;
|
|
if (0 != cInfo) {
|
|
ppInfo = (PCCRYPT_OID_INFO *) OIDInfoAlloc(
|
|
cInfo * sizeof(PCCRYPT_OID_INFO));
|
|
|
|
if (ppInfo)
|
|
memcpy(ppInfo, DsGroup.rgpInfo, cInfo * sizeof(PCCRYPT_OID_INFO));
|
|
else
|
|
cInfo = 0;
|
|
}
|
|
|
|
LeaveCriticalSection(&DsCriticalSection);
|
|
|
|
|
|
for (i = 0; i < cInfo; i++) {
|
|
PCCRYPT_OID_INFO pInfo = ppInfo[i];
|
|
|
|
if (dwGroupId && dwGroupId != pInfo->dwGroupId)
|
|
continue;
|
|
|
|
if (!pfnEnumOIDInfo(pInfo, pvArg))
|
|
goto EnumOIDInfoError;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CommonReturn:
|
|
OIDInfoFree(ppInfo);
|
|
return fResult;
|
|
ErrorReturn:
|
|
fResult = FALSE;
|
|
goto CommonReturn;
|
|
|
|
TRACE_ERROR(EnumOIDInfoError)
|
|
}
|