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

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)
}