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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: oidinfo.cpp
  8. //
  9. // Contents: Cryptographic Object ID (OID) Info Functions
  10. //
  11. // Functions: I_CryptOIDInfoDllMain
  12. // CryptFindOIDInfo
  13. // CryptRegisterOIDInfo
  14. // CryptUnregisterOIDInfo
  15. // CryptEnumOIDInfo
  16. // CryptFindLocalizedName
  17. //
  18. // Comments:
  19. //
  20. // History: 24-May-97 philh created
  21. //--------------------------------------------------------------------------
  22. #include "global.hxx"
  23. #include <dbgdef.h>
  24. #include "wintrust.h" // wintrust.h is needed for SPC_ oids
  25. #include "chain.h" // chain.h is needed for ChainRetrieveObjectByUrlW()
  26. // and ChainIsConnected()
  27. #include "certca.h" // certca.h is needed for CAOIDGetLdapURL()
  28. // Initialized in I_CryptOIDInfoDllMain at ProcessAttach
  29. static HMODULE hOIDInfoInst;
  30. #define MAX_RESOURCE_OID_NAME_LENGTH 256
  31. static LPCWSTR pwszNullName = L"";
  32. #define LEN_ALIGN(Len) ((Len + 7) & ~7)
  33. #define CONST_OID_GROUP_PREFIX_CHAR '!'
  34. #define OID_INFO_ENCODING_TYPE 0
  35. #define OID_INFO_NAME_VALUE_NAME L"Name"
  36. #define OID_INFO_ALGID_VALUE_NAME L"Algid"
  37. #define OID_INFO_EXTRA_INFO_VALUE_NAME L"ExtraInfo"
  38. #define OID_INFO_FLAGS_VALUE_NAME L"Flags"
  39. //+=========================================================================
  40. // OID Information Tables (by GROUP_ID)
  41. //==========================================================================
  42. #define OID_INFO_LEN sizeof(CRYPT_OID_INFO)
  43. //+-------------------------------------------------------------------------
  44. // Hash Algorithm Table
  45. //--------------------------------------------------------------------------
  46. #define HASH_ALG_ENTRY(pszOID, pwszName, Algid) \
  47. OID_INFO_LEN, pszOID, pwszName, CRYPT_HASH_ALG_OID_GROUP_ID, Algid, 0, NULL
  48. static CCRYPT_OID_INFO HashAlgTable[] = {
  49. HASH_ALG_ENTRY(szOID_OIWSEC_sha1, L"sha1", CALG_SHA1),
  50. HASH_ALG_ENTRY(szOID_OIWSEC_sha1, L"sha", CALG_SHA1),
  51. HASH_ALG_ENTRY(szOID_OIWSEC_sha, L"sha", CALG_SHA),
  52. HASH_ALG_ENTRY(szOID_RSA_MD5, L"md5", CALG_MD5),
  53. HASH_ALG_ENTRY(szOID_RSA_MD4, L"md4", CALG_MD4),
  54. HASH_ALG_ENTRY(szOID_RSA_MD2, L"md2", CALG_MD2)
  55. };
  56. #define HASH_ALG_CNT (sizeof(HashAlgTable) / sizeof(HashAlgTable[0]))
  57. //+-------------------------------------------------------------------------
  58. // Encryption Algorithm Table
  59. //--------------------------------------------------------------------------
  60. #define ENCRYPT_ALG_ENTRY(pszOID, pwszName, Algid) \
  61. OID_INFO_LEN, pszOID, pwszName, CRYPT_ENCRYPT_ALG_OID_GROUP_ID, \
  62. Algid, 0, NULL
  63. static CCRYPT_OID_INFO EncryptAlgTable[] = {
  64. ENCRYPT_ALG_ENTRY(szOID_OIWSEC_desCBC, L"des", CALG_DES),
  65. ENCRYPT_ALG_ENTRY(szOID_RSA_DES_EDE3_CBC, L"3des", CALG_3DES),
  66. ENCRYPT_ALG_ENTRY(szOID_RSA_RC2CBC, L"rc2", CALG_RC2),
  67. ENCRYPT_ALG_ENTRY(szOID_RSA_RC4, L"rc4", CALG_RC4),
  68. #ifdef CMS_PKCS7
  69. ENCRYPT_ALG_ENTRY(szOID_RSA_SMIMEalgCMS3DESwrap, L"CMS3DESwrap", CALG_3DES),
  70. ENCRYPT_ALG_ENTRY(szOID_RSA_SMIMEalgCMSRC2wrap, L"CMSRC2wrap", CALG_RC2),
  71. #endif // CMS_PKCS7
  72. };
  73. #define ENCRYPT_ALG_CNT (sizeof(EncryptAlgTable) / sizeof(EncryptAlgTable[0]))
  74. //+-------------------------------------------------------------------------
  75. // Public Key Algorithm Table
  76. //--------------------------------------------------------------------------
  77. static const DWORD dwMosaicFlags = CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
  78. CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
  79. static const DWORD dwNoNullParaFlag = CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG;
  80. #define PUBKEY_ALG_ENTRY(pszOID, pwszName, Algid) \
  81. OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
  82. Algid, 0, NULL
  83. #define PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, Algid, dwFlags) \
  84. OID_INFO_LEN, pszOID, pwszName, CRYPT_PUBKEY_ALG_OID_GROUP_ID, \
  85. Algid, sizeof(dwFlags), (BYTE *) &dwFlags
  86. #define DSA_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
  87. PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DSS_SIGN, dwNoNullParaFlag)
  88. #define DH_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
  89. PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DH_SF, dwNoNullParaFlag)
  90. #ifdef CMS_PKCS7
  91. #define ESDH_PUBKEY_ALG_ENTRY(pszOID, pwszName) \
  92. PUBKEY_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_DH_EPHEM, dwNoNullParaFlag)
  93. #endif // CMS_PKCS7
  94. static CCRYPT_OID_INFO PubKeyAlgTable[] = {
  95. PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA", CALG_RSA_KEYX),
  96. DSA_PUBKEY_ALG_ENTRY(szOID_X957_DSA, L"DSA"),
  97. DH_PUBKEY_ALG_ENTRY(szOID_ANSI_X942_DH, L"DH"),
  98. PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA_KEYX", CALG_RSA_KEYX),
  99. PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA", CALG_RSA_SIGN),
  100. PUBKEY_ALG_ENTRY(szOID_RSA_RSA, L"RSA_SIGN", CALG_RSA_SIGN),
  101. DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSA"),
  102. DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSS"),
  103. DSA_PUBKEY_ALG_ENTRY(szOID_OIWSEC_dsa, L"DSA_SIGN"),
  104. DH_PUBKEY_ALG_ENTRY(szOID_RSA_DH, L"DH"),
  105. PUBKEY_ALG_ENTRY(szOID_OIWSEC_rsaXchg, L"RSA_KEYX", CALG_RSA_KEYX),
  106. PUBKEY_EXTRA_ALG_ENTRY(szOID_INFOSEC_mosaicKMandUpdSig,
  107. L"mosaicKMandUpdSig", CALG_DSS_SIGN, dwMosaicFlags),
  108. #ifdef CMS_PKCS7
  109. ESDH_PUBKEY_ALG_ENTRY(szOID_RSA_SMIMEalgESDH, L"ESDH"),
  110. #endif // CMS_PKCS7
  111. PUBKEY_ALG_ENTRY(szOID_PKIX_NO_SIGNATURE, L"NO_SIGN", CALG_NO_SIGN),
  112. };
  113. #define PUBKEY_ALG_CNT (sizeof(PubKeyAlgTable) / sizeof(PubKeyAlgTable[0]))
  114. //+-------------------------------------------------------------------------
  115. // Signature Algorithm Table
  116. //--------------------------------------------------------------------------
  117. static const ALG_ID aiRsaPubKey = CALG_RSA_SIGN;
  118. static const DWORD rgdwMosaicSign[] = {
  119. CALG_DSS_SIGN,
  120. CRYPT_OID_INHIBIT_SIGNATURE_FORMAT_FLAG |
  121. CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG
  122. };
  123. static const DWORD rgdwDssSign[] = {
  124. CALG_DSS_SIGN,
  125. CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG
  126. };
  127. #define SIGN_ALG_ENTRY(pszOID, pwszName, aiHash, aiPubKey) \
  128. OID_INFO_LEN, pszOID, pwszName, CRYPT_SIGN_ALG_OID_GROUP_ID, aiHash, \
  129. sizeof(aiPubKey), (BYTE *) &aiPubKey
  130. #define RSA_SIGN_ALG_ENTRY(pszOID, pwszName, aiHash) \
  131. SIGN_ALG_ENTRY(pszOID, pwszName, aiHash, aiRsaPubKey)
  132. #define SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, aiHash, rgdwExtra) \
  133. OID_INFO_LEN, pszOID, pwszName, CRYPT_SIGN_ALG_OID_GROUP_ID, aiHash, \
  134. sizeof(rgdwExtra), (BYTE *) rgdwExtra
  135. #define DSS_SIGN_ALG_ENTRY(pszOID, pwszName) \
  136. SIGN_EXTRA_ALG_ENTRY(pszOID, pwszName, CALG_SHA1, rgdwDssSign)
  137. static CCRYPT_OID_INFO SignAlgTable[] = {
  138. RSA_SIGN_ALG_ENTRY(szOID_RSA_SHA1RSA, L"sha1RSA", CALG_SHA1),
  139. RSA_SIGN_ALG_ENTRY(szOID_RSA_MD5RSA, L"md5RSA", CALG_MD5),
  140. DSS_SIGN_ALG_ENTRY(szOID_X957_SHA1DSA, L"sha1DSA"),
  141. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_sha1RSASign, L"sha1RSA", CALG_SHA1),
  142. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_sha1RSASign, L"shaRSA", CALG_SHA1),
  143. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_shaRSA, L"shaRSA", CALG_SHA),
  144. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md5RSA, L"md5RSA", CALG_MD5),
  145. RSA_SIGN_ALG_ENTRY(szOID_RSA_MD2RSA, L"md2RSA", CALG_MD2),
  146. RSA_SIGN_ALG_ENTRY(szOID_RSA_MD4RSA, L"md4RSA", CALG_MD4),
  147. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md4RSA, L"md4RSA", CALG_MD4),
  148. RSA_SIGN_ALG_ENTRY(szOID_OIWSEC_md4RSA2, L"md4RSA", CALG_MD4),
  149. RSA_SIGN_ALG_ENTRY(szOID_OIWDIR_md2RSA, L"md2RSA", CALG_MD2),
  150. DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_shaDSA, L"sha1DSA"),
  151. DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_shaDSA, L"shaDSA"),
  152. DSS_SIGN_ALG_ENTRY(szOID_OIWSEC_dsaSHA1,L"dsaSHA1"),
  153. SIGN_EXTRA_ALG_ENTRY(szOID_INFOSEC_mosaicUpdatedSig, L"mosaicUpdatedSig",
  154. CALG_SHA, rgdwMosaicSign),
  155. };
  156. #define SIGN_ALG_CNT (sizeof(SignAlgTable) / sizeof(SignAlgTable[0]))
  157. //+-------------------------------------------------------------------------
  158. // RDN Attribute Table
  159. //--------------------------------------------------------------------------
  160. // PLEASE UPDATE the following define in certstr.cpp if you add a new entry
  161. // with a longer pwszName
  162. // #define MAX_X500_KEY_LEN 64
  163. // Ordered lists of acceptable RDN attribute value types. 0 terminates.
  164. static const DWORD rgdwPrintableValueType[] = { CERT_RDN_PRINTABLE_STRING, 0 };
  165. static const DWORD rgdwIA5ValueType[] = { CERT_RDN_IA5_STRING, 0 };
  166. static const DWORD rgdwNumericValueType[] = { CERT_RDN_NUMERIC_STRING, 0 };
  167. static const DWORD rgdwIA5orUTF8ValueType[] = { CERT_RDN_IA5_STRING,
  168. CERT_RDN_UTF8_STRING, 0 };
  169. #define RDN_ATTR_ENTRY(pszOID, pwszName, rgdwValueType) \
  170. OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 0, \
  171. sizeof(rgdwValueType), (BYTE *) rgdwValueType
  172. #define DEFAULT_RDN_ATTR_ENTRY(pszOID, pwszName) \
  173. OID_INFO_LEN, pszOID, pwszName, CRYPT_RDN_ATTR_OID_GROUP_ID, 0, 0, NULL
  174. static CCRYPT_OID_INFO RDNAttrTable[] = {
  175. // Ordered with most commonly used key names at the beginning
  176. // Labeling attribute types:
  177. DEFAULT_RDN_ATTR_ENTRY(szOID_COMMON_NAME, L"CN"),
  178. // Geographic attribute types:
  179. DEFAULT_RDN_ATTR_ENTRY(szOID_LOCALITY_NAME, L"L"),
  180. // Organizational attribute types:
  181. DEFAULT_RDN_ATTR_ENTRY(szOID_ORGANIZATION_NAME, L"O"),
  182. DEFAULT_RDN_ATTR_ENTRY(szOID_ORGANIZATIONAL_UNIT_NAME, L"OU"),
  183. // Verisign sticks the following in their cert names. Netscape uses the
  184. // "E" instead of the "Email". Will let "E" take precedence
  185. RDN_ATTR_ENTRY(szOID_RSA_emailAddr, L"E", rgdwIA5ValueType),
  186. RDN_ATTR_ENTRY(szOID_RSA_emailAddr, L"Email", rgdwIA5ValueType),
  187. // The following aren't used in Verisign's certs
  188. // Geographic attribute types:
  189. RDN_ATTR_ENTRY(szOID_COUNTRY_NAME, L"C", rgdwPrintableValueType),
  190. DEFAULT_RDN_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME, L"S"),
  191. DEFAULT_RDN_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME, L"ST"),
  192. DEFAULT_RDN_ATTR_ENTRY(szOID_STREET_ADDRESS, L"STREET"),
  193. // Organizational attribute types:
  194. DEFAULT_RDN_ATTR_ENTRY(szOID_TITLE, L"T"),
  195. DEFAULT_RDN_ATTR_ENTRY(szOID_TITLE, L"Title"),
  196. DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"G"),
  197. DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"GN"),
  198. DEFAULT_RDN_ATTR_ENTRY(szOID_GIVEN_NAME, L"GivenName"),
  199. DEFAULT_RDN_ATTR_ENTRY(szOID_INITIALS, L"I"),
  200. DEFAULT_RDN_ATTR_ENTRY(szOID_INITIALS, L"Initials"),
  201. // Labeling attribute types:
  202. DEFAULT_RDN_ATTR_ENTRY(szOID_SUR_NAME, L"SN"),
  203. // RDN_ATTR_ENTRY(szOID_DEVICE_SERIAL_NUMBER, L"", rgdwPrintableValueType),
  204. // Pilot user attribute types:
  205. RDN_ATTR_ENTRY(szOID_DOMAIN_COMPONENT, L"DC", rgdwIA5orUTF8ValueType),
  206. // Explanatory attribute types:
  207. DEFAULT_RDN_ATTR_ENTRY(szOID_DESCRIPTION, L"Description"),
  208. // szOID_SEARCH_GUIDE "2.5.4.14"
  209. // DEFAULT_RDN_ATTR_ENTRY(szOID_BUSINESS_CATEGORY, L""),
  210. // Postal addressing attribute types:
  211. // szOID_POSTAL_ADDRESS "2.5.4.16"
  212. DEFAULT_RDN_ATTR_ENTRY(szOID_POSTAL_CODE, L"PostalCode"),
  213. DEFAULT_RDN_ATTR_ENTRY(szOID_POST_OFFICE_BOX, L"POBox"),
  214. // DEFAULT_RDN_ATTR_ENTRY(szOID_PHYSICAL_DELIVERY_OFFICE_NAME, L""),
  215. // Telecommunications addressing attribute types:
  216. RDN_ATTR_ENTRY(szOID_TELEPHONE_NUMBER, L"Phone", rgdwPrintableValueType),
  217. // szOID_TELEX_NUMBER "2.5.4.21"
  218. // szOID_TELETEXT_TERMINAL_IDENTIFIER "2.5.4.22"
  219. // szOID_FACSIMILE_TELEPHONE_NUMBER "2.5.4.23"
  220. // Following is used as a test case for a Numeric value
  221. RDN_ATTR_ENTRY(szOID_X21_ADDRESS, L"X21Address", rgdwNumericValueType),
  222. // RDN_ATTR_ENTRY(szOID_INTERNATIONAL_ISDN_NUMBER, L"", rgdwNumericValueType),
  223. // szOID_REGISTERED_ADDRESS "2.5.4.26"
  224. // RDN_ATTR_ENTRY(szOID_DESTINATION_INDICATOR, L"", rgdwPrintableValueType)
  225. // Preference attribute types:
  226. // szOID_PREFERRED_DELIVERY_METHOD "2.5.4.28"
  227. // OSI application attribute types:
  228. // szOID_PRESENTATION_ADDRESS "2.5.4.29"
  229. // szOID_SUPPORTED_APPLICATION_CONTEXT "2.5.4.30"
  230. // Relational application attribute types:
  231. // szOID_MEMBER "2.5.4.31"
  232. // szOID_OWNER "2.5.4.32"
  233. // szOID_ROLE_OCCUPANT "2.5.4.33"
  234. // szOID_SEE_ALSO "2.5.4.34"
  235. // Security attribute types:
  236. // szOID_USER_PASSWORD "2.5.4.35"
  237. // szOID_USER_CERTIFICATE "2.5.4.36"
  238. // szOID_CA_CERTIFICATE "2.5.4.37"
  239. // szOID_AUTHORITY_REVOCATION_LIST "2.5.4.38"
  240. // szOID_CERTIFICATE_REVOCATION_LIST "2.5.4.39"
  241. // szOID_CROSS_CERTIFICATE_PAIR "2.5.4.40"
  242. // Undocumented attribute types???
  243. //#define szOID_??? "2.5.4.41"
  244. DEFAULT_RDN_ATTR_ENTRY(szOID_DN_QUALIFIER, L"dnQualifier"),
  245. };
  246. #define RDN_ATTR_CNT (sizeof(RDNAttrTable) / sizeof(RDNAttrTable[0]))
  247. //+-------------------------------------------------------------------------
  248. // Extension or Attribute Table (Localized via resource strings)
  249. //--------------------------------------------------------------------------
  250. #define EXT_ATTR_ENTRY(pszOID, ResourceIdORpwszName) \
  251. OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
  252. CRYPT_EXT_OR_ATTR_OID_GROUP_ID, 0, 0, NULL
  253. static CRYPT_OID_INFO ExtAttrTable[] = {
  254. EXT_ATTR_ENTRY(szOID_AUTHORITY_KEY_IDENTIFIER2,
  255. IDS_EXT_AUTHORITY_KEY_IDENTIFIER),
  256. EXT_ATTR_ENTRY(szOID_AUTHORITY_KEY_IDENTIFIER,
  257. IDS_EXT_AUTHORITY_KEY_IDENTIFIER),
  258. EXT_ATTR_ENTRY(szOID_KEY_ATTRIBUTES,
  259. IDS_EXT_KEY_ATTRIBUTES),
  260. EXT_ATTR_ENTRY(szOID_KEY_USAGE_RESTRICTION,
  261. IDS_EXT_KEY_USAGE_RESTRICTION),
  262. EXT_ATTR_ENTRY(szOID_SUBJECT_ALT_NAME2,
  263. IDS_EXT_SUBJECT_ALT_NAME),
  264. EXT_ATTR_ENTRY(szOID_SUBJECT_ALT_NAME,
  265. IDS_EXT_SUBJECT_ALT_NAME),
  266. EXT_ATTR_ENTRY(szOID_ISSUER_ALT_NAME2,
  267. IDS_EXT_ISSUER_ALT_NAME),
  268. EXT_ATTR_ENTRY(szOID_ISSUER_ALT_NAME,
  269. IDS_EXT_ISSUER_ALT_NAME),
  270. EXT_ATTR_ENTRY(szOID_BASIC_CONSTRAINTS2,
  271. IDS_EXT_BASIC_CONSTRAINTS),
  272. EXT_ATTR_ENTRY(szOID_BASIC_CONSTRAINTS,
  273. IDS_EXT_BASIC_CONSTRAINTS),
  274. EXT_ATTR_ENTRY(szOID_KEY_USAGE,
  275. IDS_EXT_KEY_USAGE),
  276. EXT_ATTR_ENTRY(szOID_CERT_POLICIES,
  277. IDS_EXT_CERT_POLICIES),
  278. EXT_ATTR_ENTRY(szOID_SUBJECT_KEY_IDENTIFIER,
  279. IDS_EXT_SUBJECT_KEY_IDENTIFIER),
  280. EXT_ATTR_ENTRY(szOID_CRL_REASON_CODE,
  281. IDS_EXT_CRL_REASON_CODE),
  282. EXT_ATTR_ENTRY(szOID_CRL_DIST_POINTS,
  283. IDS_EXT_CRL_DIST_POINTS),
  284. EXT_ATTR_ENTRY(szOID_ENHANCED_KEY_USAGE,
  285. IDS_EXT_ENHANCED_KEY_USAGE),
  286. EXT_ATTR_ENTRY(szOID_AUTHORITY_INFO_ACCESS,
  287. IDS_EXT_AUTHORITY_INFO_ACCESS),
  288. EXT_ATTR_ENTRY(szOID_CERT_EXTENSIONS,
  289. IDS_EXT_CERT_EXTENSIONS),
  290. EXT_ATTR_ENTRY(szOID_RSA_certExtensions,
  291. IDS_EXT_CERT_EXTENSIONS),
  292. EXT_ATTR_ENTRY(szOID_NEXT_UPDATE_LOCATION,
  293. IDS_EXT_NEXT_UPDATE_LOCATION),
  294. EXT_ATTR_ENTRY(szOID_YESNO_TRUST_ATTR,
  295. IDS_EXT_YESNO_TRUST_ATTR),
  296. EXT_ATTR_ENTRY(szOID_RSA_emailAddr,
  297. IDS_EXT_RSA_emailAddr),
  298. EXT_ATTR_ENTRY(szOID_RSA_unstructName,
  299. IDS_EXT_RSA_unstructName),
  300. EXT_ATTR_ENTRY(szOID_RSA_contentType,
  301. IDS_EXT_RSA_contentType),
  302. EXT_ATTR_ENTRY(szOID_RSA_messageDigest,
  303. IDS_EXT_RSA_messageDigest),
  304. EXT_ATTR_ENTRY(szOID_RSA_signingTime,
  305. IDS_EXT_RSA_signingTime),
  306. EXT_ATTR_ENTRY(szOID_RSA_counterSign,
  307. IDS_EXT_RSA_counterSign),
  308. EXT_ATTR_ENTRY(szOID_RSA_challengePwd,
  309. IDS_EXT_RSA_challengePwd),
  310. EXT_ATTR_ENTRY(szOID_RSA_unstructAddr,
  311. IDS_EXT_RSA_unstructAddr),
  312. EXT_ATTR_ENTRY(szOID_RSA_extCertAttrs, L""),
  313. EXT_ATTR_ENTRY(szOID_RSA_SMIMECapabilities,
  314. IDS_EXT_RSA_SMIMECapabilities),
  315. EXT_ATTR_ENTRY(szOID_RSA_preferSignedData,
  316. IDS_EXT_RSA_preferSignedData),
  317. EXT_ATTR_ENTRY(szOID_PKIX_POLICY_QUALIFIER_CPS,
  318. IDS_EXT_PKIX_POLICY_QUALIFIER_CPS),
  319. EXT_ATTR_ENTRY(szOID_PKIX_POLICY_QUALIFIER_USERNOTICE,
  320. IDS_EXT_PKIX_POLICY_QUALIFIER_USERNOTICE),
  321. EXT_ATTR_ENTRY(szOID_PKIX_OCSP,
  322. IDS_EXT_PKIX_OCSP),
  323. EXT_ATTR_ENTRY(szOID_PKIX_CA_ISSUERS,
  324. IDS_EXT_PKIX_CA_ISSUERS),
  325. EXT_ATTR_ENTRY(szOID_ENROLL_CERTTYPE_EXTENSION,
  326. IDS_EXT_MS_CERTIFICATE_TEMPLATE),
  327. EXT_ATTR_ENTRY(szOID_ENROLL_CERTTYPE_EXTENSION,
  328. IDS_EXT_ENROLL_CERTTYPE),
  329. EXT_ATTR_ENTRY(szOID_CERT_MANIFOLD,
  330. IDS_EXT_CERT_MANIFOLD),
  331. EXT_ATTR_ENTRY(szOID_NETSCAPE_CERT_TYPE,
  332. IDS_EXT_NETSCAPE_CERT_TYPE),
  333. EXT_ATTR_ENTRY(szOID_NETSCAPE_BASE_URL,
  334. IDS_EXT_NETSCAPE_BASE_URL),
  335. EXT_ATTR_ENTRY(szOID_NETSCAPE_REVOCATION_URL,
  336. IDS_EXT_NETSCAPE_REVOCATION_URL),
  337. EXT_ATTR_ENTRY(szOID_NETSCAPE_CA_REVOCATION_URL,
  338. IDS_EXT_NETSCAPE_CA_REVOCATION_URL),
  339. EXT_ATTR_ENTRY(szOID_NETSCAPE_CERT_RENEWAL_URL,
  340. IDS_EXT_NETSCAPE_CERT_RENEWAL_URL),
  341. EXT_ATTR_ENTRY(szOID_NETSCAPE_CA_POLICY_URL,
  342. IDS_EXT_NETSCAPE_CA_POLICY_URL),
  343. EXT_ATTR_ENTRY(szOID_NETSCAPE_SSL_SERVER_NAME,
  344. IDS_EXT_NETSCAPE_SSL_SERVER_NAME),
  345. EXT_ATTR_ENTRY(szOID_NETSCAPE_COMMENT,
  346. IDS_EXT_NETSCAPE_COMMENT),
  347. EXT_ATTR_ENTRY(SPC_SP_AGENCY_INFO_OBJID,
  348. IDS_EXT_SPC_SP_AGENCY_INFO_OBJID),
  349. EXT_ATTR_ENTRY(SPC_FINANCIAL_CRITERIA_OBJID,
  350. IDS_EXT_SPC_FINANCIAL_CRITERIA_OBJID),
  351. EXT_ATTR_ENTRY(SPC_MINIMAL_CRITERIA_OBJID,
  352. IDS_EXT_SPC_MINIMAL_CRITERIA_OBJID),
  353. EXT_ATTR_ENTRY(szOID_COUNTRY_NAME,
  354. IDS_EXT_COUNTRY_NAME),
  355. EXT_ATTR_ENTRY(szOID_ORGANIZATION_NAME,
  356. IDS_EXT_ORGANIZATION_NAME),
  357. EXT_ATTR_ENTRY(szOID_ORGANIZATIONAL_UNIT_NAME,
  358. IDS_EXT_ORGANIZATIONAL_UNIT_NAME),
  359. EXT_ATTR_ENTRY(szOID_COMMON_NAME,
  360. IDS_EXT_COMMON_NAME),
  361. EXT_ATTR_ENTRY(szOID_LOCALITY_NAME,
  362. IDS_EXT_LOCALITY_NAME),
  363. EXT_ATTR_ENTRY(szOID_STATE_OR_PROVINCE_NAME,
  364. IDS_EXT_STATE_OR_PROVINCE_NAME),
  365. EXT_ATTR_ENTRY(szOID_TITLE,
  366. IDS_EXT_TITLE),
  367. EXT_ATTR_ENTRY(szOID_GIVEN_NAME,
  368. IDS_EXT_GIVEN_NAME),
  369. EXT_ATTR_ENTRY(szOID_INITIALS,
  370. IDS_EXT_INITIALS),
  371. EXT_ATTR_ENTRY(szOID_SUR_NAME,
  372. IDS_EXT_SUR_NAME),
  373. EXT_ATTR_ENTRY(szOID_DOMAIN_COMPONENT,
  374. IDS_EXT_DOMAIN_COMPONENT),
  375. EXT_ATTR_ENTRY(szOID_STREET_ADDRESS,
  376. IDS_EXT_STREET_ADDRESS),
  377. EXT_ATTR_ENTRY(szOID_DEVICE_SERIAL_NUMBER,
  378. IDS_EXT_DEVICE_SERIAL_NUMBER),
  379. EXT_ATTR_ENTRY(szOID_CERTSRV_CA_VERSION,
  380. IDS_EXT_CA_VERSION),
  381. EXT_ATTR_ENTRY(szOID_CERTSRV_CROSSCA_VERSION,
  382. IDS_EXT_CROSSCA_VERSION),
  383. EXT_ATTR_ENTRY(szOID_SERIALIZED,
  384. IDS_EXT_SERIALIZED),
  385. EXT_ATTR_ENTRY(szOID_NT_PRINCIPAL_NAME,
  386. IDS_EXT_NT_PRINCIPAL_NAME),
  387. EXT_ATTR_ENTRY(szOID_PRODUCT_UPDATE,
  388. IDS_EXT_PRODUCT_UPDATE),
  389. EXT_ATTR_ENTRY(szOID_ENROLLMENT_NAME_VALUE_PAIR,
  390. IDS_EXT_ENROLLMENT_NAME_VALUE_PAIR),
  391. EXT_ATTR_ENTRY(szOID_OS_VERSION,
  392. IDS_EXT_OS_VERSION),
  393. EXT_ATTR_ENTRY(szOID_ENROLLMENT_CSP_PROVIDER,
  394. IDS_EXT_ENROLLMENT_CSP_PROVIDER),
  395. EXT_ATTR_ENTRY(szOID_CRL_NUMBER,
  396. IDS_EXT_CRL_NUMBER),
  397. EXT_ATTR_ENTRY(szOID_DELTA_CRL_INDICATOR,
  398. IDS_EXT_DELTA_CRL_INDICATOR),
  399. EXT_ATTR_ENTRY(szOID_ISSUING_DIST_POINT,
  400. IDS_EXT_ISSUING_DIST_POINT),
  401. EXT_ATTR_ENTRY(szOID_FRESHEST_CRL,
  402. IDS_EXT_FRESHEST_CRL),
  403. EXT_ATTR_ENTRY(szOID_NAME_CONSTRAINTS,
  404. IDS_EXT_NAME_CONSTRAINTS),
  405. EXT_ATTR_ENTRY(szOID_POLICY_MAPPINGS,
  406. IDS_EXT_POLICY_MAPPINGS),
  407. EXT_ATTR_ENTRY(szOID_LEGACY_POLICY_MAPPINGS,
  408. IDS_EXT_POLICY_MAPPINGS),
  409. EXT_ATTR_ENTRY(szOID_POLICY_CONSTRAINTS,
  410. IDS_EXT_POLICY_CONSTRAINTS),
  411. EXT_ATTR_ENTRY(szOID_CROSS_CERT_DIST_POINTS,
  412. IDS_EXT_CROSS_CERT_DIST_POINTS),
  413. EXT_ATTR_ENTRY(szOID_APPLICATION_CERT_POLICIES,
  414. IDS_EXT_APP_POLICIES),
  415. EXT_ATTR_ENTRY(szOID_APPLICATION_POLICY_MAPPINGS,
  416. IDS_EXT_APP_POLICY_MAPPINGS),
  417. EXT_ATTR_ENTRY(szOID_APPLICATION_POLICY_CONSTRAINTS,
  418. IDS_EXT_APP_POLICY_CONSTRAINTS),
  419. // DSIE: Post Win2K, 8/2/2000.
  420. EXT_ATTR_ENTRY(szOID_CT_PKI_DATA,
  421. IDS_EXT_CT_PKI_DATA),
  422. EXT_ATTR_ENTRY(szOID_CT_PKI_RESPONSE,
  423. IDS_EXT_CT_PKI_RESPONSE),
  424. EXT_ATTR_ENTRY(szOID_CMC,
  425. IDS_EXT_CMC),
  426. EXT_ATTR_ENTRY(szOID_CMC_STATUS_INFO,
  427. IDS_EXT_CMC_STATUS_INFO),
  428. EXT_ATTR_ENTRY(szOID_CMC_ADD_EXTENSIONS,
  429. IDS_EXT_CMC_ADD_EXTENSIONS),
  430. EXT_ATTR_ENTRY(szOID_CMC_ADD_ATTRIBUTES,
  431. IDS_EXT_CMC_ADD_ATTRIBUTES),
  432. EXT_ATTR_ENTRY(szOID_CMC_ADD_ATTRIBUTES,
  433. IDS_EXT_CMC_ADD_ATTRIBUTES),
  434. EXT_ATTR_ENTRY(szOID_PKCS_7_DATA,
  435. IDS_EXT_PKCS_7_DATA),
  436. EXT_ATTR_ENTRY(szOID_PKCS_7_SIGNED,
  437. IDS_EXT_PKCS_7_SIGNED),
  438. EXT_ATTR_ENTRY(szOID_PKCS_7_ENVELOPED,
  439. IDS_EXT_PKCS_7_ENVELOPED),
  440. EXT_ATTR_ENTRY(szOID_PKCS_7_SIGNEDANDENVELOPED,
  441. IDS_EXT_PKCS_7_SIGNEDANDENVELOPED),
  442. EXT_ATTR_ENTRY(szOID_PKCS_7_DIGESTED,
  443. IDS_EXT_PKCS_7_DIGESTED),
  444. EXT_ATTR_ENTRY(szOID_PKCS_7_ENCRYPTED,
  445. IDS_EXT_PKCS_7_ENCRYPTED),
  446. EXT_ATTR_ENTRY(szOID_CERTSRV_PREVIOUS_CERT_HASH,
  447. IDS_EXT_CERTSRV_PREVIOUS_CERT_HASH),
  448. EXT_ATTR_ENTRY(szOID_CRL_VIRTUAL_BASE,
  449. IDS_EXT_CRL_VIRTUAL_BASE),
  450. EXT_ATTR_ENTRY(szOID_CRL_NEXT_PUBLISH,
  451. IDS_EXT_CRL_NEXT_PUBLISH),
  452. EXT_ATTR_ENTRY(szOID_KP_CA_EXCHANGE,
  453. IDS_EXT_KP_CA_EXCHANGE),
  454. EXT_ATTR_ENTRY(szOID_KP_KEY_RECOVERY_AGENT,
  455. IDS_EXT_KP_KEY_RECOVERY_AGENT),
  456. EXT_ATTR_ENTRY(szOID_CERTIFICATE_TEMPLATE,
  457. IDS_EXT_CERTIFICATE_TEMPLATE),
  458. EXT_ATTR_ENTRY(szOID_ENTERPRISE_OID_ROOT,
  459. IDS_EXT_ENTERPRISE_OID_ROOT),
  460. EXT_ATTR_ENTRY(szOID_RDN_DUMMY_SIGNER,
  461. IDS_EXT_RDN_DUMMY_SIGNER),
  462. EXT_ATTR_ENTRY(szOID_ARCHIVED_KEY_ATTR,
  463. IDS_EXT_ARCHIVED_KEY_ATTR),
  464. EXT_ATTR_ENTRY(szOID_CRL_SELF_CDP,
  465. IDS_EXT_CRL_SELF_CDP),
  466. EXT_ATTR_ENTRY(szOID_REQUIRE_CERT_CHAIN_POLICY,
  467. IDS_EXT_REQUIRE_CERT_CHAIN_POLICY),
  468. EXT_ATTR_ENTRY(szOID_CMC_TRANSACTION_ID,
  469. IDS_EXT_CMC_TRANSACTION_ID),
  470. EXT_ATTR_ENTRY(szOID_CMC_SENDER_NONCE,
  471. IDS_EXT_CMC_SENDER_NONCE),
  472. EXT_ATTR_ENTRY(szOID_CMC_RECIPIENT_NONCE,
  473. IDS_EXT_CMC_RECIPIENT_NONCE),
  474. EXT_ATTR_ENTRY(szOID_CMC_REG_INFO,
  475. IDS_EXT_CMC_REG_INFO),
  476. EXT_ATTR_ENTRY(szOID_CMC_GET_CERT,
  477. IDS_EXT_CMC_GET_CERT),
  478. EXT_ATTR_ENTRY(szOID_CMC_GET_CRL,
  479. IDS_EXT_CMC_GET_CRL),
  480. EXT_ATTR_ENTRY(szOID_CMC_REVOKE_REQUEST,
  481. IDS_EXT_CMC_REVOKE_REQUEST),
  482. EXT_ATTR_ENTRY(szOID_CMC_QUERY_PENDING,
  483. IDS_EXT_CMC_QUERY_PENDING),
  484. EXT_ATTR_ENTRY(szOID_CTL,
  485. IDS_EXT_CTL),
  486. EXT_ATTR_ENTRY(szOID_ARCHIVED_KEY_CERT_HASH,
  487. IDS_EXT_ARCHIVED_KEY_CERT_HASH),
  488. EXT_ATTR_ENTRY(szOID_PRIVATEKEY_USAGE_PERIOD,
  489. IDS_EXT_PRIVATEKEY_USAGE_PERIOD),
  490. EXT_ATTR_ENTRY(szOID_REQUEST_CLIENT_INFO,
  491. IDS_EXT_REQUEST_CLIENT_INFO),
  492. };
  493. #define EXT_ATTR_CNT (sizeof(ExtAttrTable) / sizeof(ExtAttrTable[0]))
  494. //+-------------------------------------------------------------------------
  495. // Enhanced Key Usage Table (Localized via resource strings)
  496. //--------------------------------------------------------------------------
  497. #define ENHKEY_ENTRY(pszOID, ResourceIdORpwszName) \
  498. OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
  499. CRYPT_ENHKEY_USAGE_OID_GROUP_ID, 0, 0, NULL
  500. static CRYPT_OID_INFO EnhKeyTable[] = {
  501. ENHKEY_ENTRY(szOID_PKIX_KP_SERVER_AUTH,
  502. IDS_ENHKEY_PKIX_KP_SERVER_AUTH),
  503. ENHKEY_ENTRY(szOID_PKIX_KP_CLIENT_AUTH,
  504. IDS_ENHKEY_PKIX_KP_CLIENT_AUTH),
  505. ENHKEY_ENTRY(szOID_PKIX_KP_CODE_SIGNING,
  506. IDS_ENHKEY_PKIX_KP_CODE_SIGNING),
  507. ENHKEY_ENTRY(szOID_PKIX_KP_EMAIL_PROTECTION,
  508. IDS_ENHKEY_PKIX_KP_EMAIL_PROTECTION),
  509. ENHKEY_ENTRY(szOID_PKIX_KP_TIMESTAMP_SIGNING,
  510. IDS_ENHKEY_PKIX_KP_TIMESTAMP_SIGNING),
  511. ENHKEY_ENTRY(szOID_KP_CTL_USAGE_SIGNING,
  512. IDS_ENHKEY_KP_CTL_USAGE_SIGNING),
  513. ENHKEY_ENTRY(szOID_KP_TIME_STAMP_SIGNING,
  514. IDS_ENHKEY_KP_TIME_STAMP_SIGNING),
  515. ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_END_SYSTEM,
  516. IDS_ENHKEY_PKIX_KP_IPSEC_END_SYSTEM),
  517. ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_TUNNEL,
  518. IDS_ENHKEY_PKIX_KP_IPSEC_TUNNEL),
  519. ENHKEY_ENTRY(szOID_PKIX_KP_IPSEC_USER,
  520. IDS_ENHKEY_PKIX_KP_IPSEC_USER),
  521. // ENHKEY_ENTRY(szOID_SERVER_GATED_CRYPTO,
  522. // IDS_ENHKEY_SERVER_GATED_CRYPTO),
  523. // ENHKEY_ENTRY(szOID_SGC_NETSCAPE,
  524. // IDS_ENHKEY_SGC_NETSCAPE),
  525. ENHKEY_ENTRY(szOID_KP_EFS,
  526. IDS_ENHKEY_KP_EFS),
  527. ENHKEY_ENTRY(szOID_WHQL_CRYPTO,
  528. IDS_ENHKEY_KP_WHQL),
  529. ENHKEY_ENTRY(szOID_NT5_CRYPTO,
  530. IDS_ENHKEY_KP_NT5),
  531. ENHKEY_ENTRY(szOID_OEM_WHQL_CRYPTO,
  532. IDS_ENHKEY_KP_OEM_WHQL),
  533. ENHKEY_ENTRY(szOID_EMBEDDED_NT_CRYPTO,
  534. IDS_ENHKEY_KP_EMBEDDED_NT),
  535. ENHKEY_ENTRY(szOID_LICENSES,
  536. IDS_ENHKEY_LICENSES),
  537. ENHKEY_ENTRY(szOID_LICENSE_SERVER,
  538. IDS_ENHKEY_LICENSES_SERVER),
  539. ENHKEY_ENTRY(szOID_KP_SMARTCARD_LOGON,
  540. IDS_ENHKEY_SMARTCARD_LOGON),
  541. ENHKEY_ENTRY(szOID_DRM,
  542. IDS_ENHKEY_DRM),
  543. ENHKEY_ENTRY(szOID_KP_QUALIFIED_SUBORDINATION,
  544. IDS_ENHKEY_KP_QUALIFIED_SUBORDINATION),
  545. ENHKEY_ENTRY(szOID_KP_KEY_RECOVERY,
  546. IDS_ENHKEY_KP_KEY_RECOVERY),
  547. ENHKEY_ENTRY(szOID_KP_DOCUMENT_SIGNING,
  548. IDS_ENHKEY_KP_CODE_SIGNING),
  549. ENHKEY_ENTRY(szOID_IPSEC_KP_IKE_INTERMEDIATE,
  550. IDS_ENHKEY_KP_IPSEC_IKE_INTERMEDIATE),
  551. ENHKEY_ENTRY(szOID_EFS_RECOVERY,
  552. IDS_ENHKEY_EFS_RECOVERY),
  553. //DSIE: 8/2/2000, Post Win2K.
  554. ENHKEY_ENTRY(szOID_ROOT_LIST_SIGNER,
  555. IDS_ENHKEY_ROOT_LIST_SIGNER),
  556. ENHKEY_ENTRY(szOID_ANY_APPLICATION_POLICY,
  557. IDS_ENHKEY_ANY_POLICY),
  558. ENHKEY_ENTRY(szOID_DS_EMAIL_REPLICATION,
  559. IDS_ENHKEY_DS_EMAIL_REPLICATION),
  560. ENHKEY_ENTRY(szOID_ENROLLMENT_AGENT,
  561. IDS_ENHKEY_ENROLLMENT_AGENT),
  562. ENHKEY_ENTRY(szOID_KP_KEY_RECOVERY_AGENT,
  563. IDS_ENHKEY_KP_KEY_RECOVERY_AGENT),
  564. ENHKEY_ENTRY(szOID_KP_CA_EXCHANGE,
  565. IDS_ENHKEY_KP_CA_EXCHANGE),
  566. ENHKEY_ENTRY(szOID_KP_LIFETIME_SIGNING,
  567. IDS_ENHKEY_KP_LIFETIME_SIGNING),
  568. };
  569. #define ENHKEY_CNT (sizeof(EnhKeyTable) / sizeof(EnhKeyTable[0]))
  570. //+-------------------------------------------------------------------------
  571. // Policy Table (Localized via resource strings)
  572. //--------------------------------------------------------------------------
  573. #define POLICY_ENTRY(pszOID, ResourceIdORpwszName) \
  574. OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
  575. CRYPT_POLICY_OID_GROUP_ID, 0, 0, NULL
  576. static CRYPT_OID_INFO PolicyTable[] = {
  577. POLICY_ENTRY(szOID_ANY_CERT_POLICY,
  578. IDS_POLICY_ANY_POLICY),
  579. };
  580. #define POLICY_CNT (sizeof(PolicyTable) / sizeof(PolicyTable[0]))
  581. #if 0
  582. //+-------------------------------------------------------------------------
  583. // Template Table (Localized via resource strings)
  584. //--------------------------------------------------------------------------
  585. #define TEMPLATE_ENTRY(pszOID, ResourceIdORpwszName) \
  586. OID_INFO_LEN, pszOID, (LPCWSTR) ResourceIdORpwszName, \
  587. CRYPT_TEMPLATE_OID_GROUP_ID, 0, 0, NULL
  588. static CRYPT_OID_INFO TemplateTable[] = {
  589. };
  590. #define TEMPLATE_CNT (sizeof(TemplateTable) / sizeof(TemplateTable[0]))
  591. #endif
  592. //+=========================================================================
  593. // OID Group Tables
  594. //
  595. // fLocalize is set to TRUE, if the CRYPT_OID_INFO's pwszName may be
  596. // a Resource ID that is used to get the localized name via LoadStringU().
  597. //
  598. // Assumption, Resource ID's <= 0xFFFF.
  599. //==========================================================================
  600. typedef struct _GROUP_ENTRY {
  601. DWORD cInfo;
  602. PCCRYPT_OID_INFO rgInfo;
  603. BOOL fLocalize;
  604. } GROUP_ENTRY, *PGROUP_ENTRY;
  605. typedef const GROUP_ENTRY CGROUP_ENTRY, *PCGROUP_ENTRY;
  606. static CGROUP_ENTRY GroupTable[CRYPT_LAST_OID_GROUP_ID + 1] = {
  607. 0, NULL, FALSE, // 0
  608. HASH_ALG_CNT, HashAlgTable, FALSE, // 1
  609. ENCRYPT_ALG_CNT, EncryptAlgTable, FALSE, // 2
  610. PUBKEY_ALG_CNT, PubKeyAlgTable, FALSE, // 3
  611. SIGN_ALG_CNT, SignAlgTable, FALSE, // 4
  612. RDN_ATTR_CNT, RDNAttrTable, FALSE, // 5
  613. EXT_ATTR_CNT, ExtAttrTable, TRUE, // 6
  614. ENHKEY_CNT, EnhKeyTable, TRUE, // 7
  615. POLICY_CNT, PolicyTable, TRUE, // 8
  616. #if 0
  617. TEMPLATE_CNT, TemplateTable, TRUE, // 9
  618. #else
  619. 0, NULL, FALSE, // 9
  620. #endif
  621. };
  622. //+-------------------------------------------------------------------------
  623. // The following groups are dynamically updated from the registry on
  624. // CryptFindOIDInfo's first call.
  625. //--------------------------------------------------------------------------
  626. static GROUP_ENTRY RegBeforeGroup;
  627. static GROUP_ENTRY RegAfterGroup;
  628. // Do the load once within a critical section
  629. static BOOL fLoadedFromRegAndResources = FALSE;
  630. static CRITICAL_SECTION LoadFromRegCriticalSection;
  631. //+=========================================================================
  632. // DS Group Definitions and Data Structures
  633. //==========================================================================
  634. typedef struct _DS_GROUP_ENTRY {
  635. DWORD cInfo;
  636. PCCRYPT_OID_INFO *rgpInfo;
  637. } DS_GROUP_ENTRY, *PDS_GROUP_ENTRY;
  638. typedef const DS_GROUP_ENTRY CDS_GROUP_ENTRY, *PCDS_GROUP_ENTRY;
  639. // The DS group is dynamically updated from the DS on the first call
  640. // to CryptFindOIDInfo or CryptEnumOIDInfo for the ENHKEY, POLICY or
  641. // TEMPLATE groups.
  642. static DS_GROUP_ENTRY DsGroup;
  643. // The above DsGroup is updated every DS_RETRIEVAL_DELTA_SECONDS. Since
  644. // any returned PCCRYPT_OID_INFO can not be freed, the following group contains
  645. // PCCRYPT_OID_INFO entries that may have been deleted from the above DS group.
  646. static DS_GROUP_ENTRY DsDeletedGroup;
  647. static CRITICAL_SECTION DsCriticalSection;
  648. // For a successful DS retrieval, the following is updated with
  649. // CurrentTime + DS_RETRIEVAL_DELTA_SECONDS.
  650. static FILETIME DsNextUpdateTime;
  651. #define DS_RETRIEVAL_DELTA_SECONDS (60 * 60 * 8)
  652. #define DS_LDAP_TIMEOUT (10 * 1000)
  653. static void FreeDsGroups();
  654. static PCCRYPT_OID_INFO SearchDsGroup(
  655. IN DWORD dwKeyType,
  656. IN void *pvKey,
  657. IN DWORD dwGroupId
  658. );
  659. static BOOL EnumDsGroup(
  660. IN DWORD dwGroupId,
  661. IN void *pvArg,
  662. IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
  663. );
  664. //+=========================================================================
  665. // Localized Name Definitions and Data Structures
  666. //==========================================================================
  667. //+-------------------------------------------------------------------------
  668. // Localized Name Information
  669. //--------------------------------------------------------------------------
  670. typedef struct _LOCALIZED_NAME_INFO {
  671. LPCWSTR pwszCryptName;
  672. union {
  673. UINT uIDLocalizedName;
  674. LPCWSTR pwszLocalizedName;
  675. };
  676. } LOCALIZED_NAME_INFO, *PLOCALIZED_NAME_INFO;
  677. //+-------------------------------------------------------------------------
  678. // Predefined Localized Names Table (Localized via resource strings)
  679. //--------------------------------------------------------------------------
  680. static LOCALIZED_NAME_INFO PredefinedNameTable[] = {
  681. // System store names
  682. L"Root", IDS_SYS_NAME_ROOT,
  683. L"My", IDS_SYS_NAME_MY,
  684. L"Trust", IDS_SYS_NAME_TRUST,
  685. L"CA", IDS_SYS_NAME_CA,
  686. L"UserDS", IDS_SYS_NAME_USERDS,
  687. L"SmartCard", IDS_SYS_NAME_SMARTCARD,
  688. L"AddressBook", IDS_SYS_NAME_ADDRESSBOOK,
  689. L"TrustedPublisher", IDS_SYS_NAME_TRUST_PUB,
  690. L"Disallowed", IDS_SYS_NAME_DISALLOWED,
  691. L"AuthRoot", IDS_SYS_NAME_AUTH_ROOT,
  692. L"Request", IDS_SYS_NAME_REQUEST,
  693. L"TrustedPeople", IDS_SYS_NAME_TRUST_PEOPLE,
  694. // Physical store names
  695. CERT_PHYSICAL_STORE_DEFAULT_NAME, IDS_PHY_NAME_DEFAULT,
  696. CERT_PHYSICAL_STORE_GROUP_POLICY_NAME, IDS_PHY_NAME_GROUP_POLICY,
  697. CERT_PHYSICAL_STORE_LOCAL_MACHINE_NAME, IDS_PHY_NAME_LOCAL_MACHINE,
  698. CERT_PHYSICAL_STORE_DS_USER_CERTIFICATE_NAME, IDS_PHY_NAME_DS_USER_CERT,
  699. CERT_PHYSICAL_STORE_ENTERPRISE_NAME, IDS_PHY_NAME_ENTERPRISE,
  700. CERT_PHYSICAL_STORE_AUTH_ROOT_NAME, IDS_PHY_NAME_AUTH_ROOT,
  701. };
  702. #define PREDEFINED_NAME_CNT (sizeof(PredefinedNameTable) / \
  703. sizeof(PredefinedNameTable[0]))
  704. //+-------------------------------------------------------------------------
  705. // Localized Name Group Table
  706. //--------------------------------------------------------------------------
  707. typedef struct _LOCALIZED_GROUP_ENTRY {
  708. DWORD cInfo;
  709. PLOCALIZED_NAME_INFO rgInfo;
  710. } LOCALIZED_GROUP_ENTRY, *PLOCALIZED_GROUP_ENTRY;
  711. #define REG_LOCALIZED_GROUP 0
  712. #define PREDEFINED_LOCALIZED_GROUP 1
  713. static LOCALIZED_GROUP_ENTRY LocalizedGroupTable[] = {
  714. // 0 - Loaded from registry
  715. 0, NULL,
  716. // 1 - Predefined list of names
  717. PREDEFINED_NAME_CNT, PredefinedNameTable
  718. };
  719. #define LOCALIZED_GROUP_CNT (sizeof(LocalizedGroupTable) / \
  720. sizeof(LocalizedGroupTable[0]))
  721. // The localized names are loaded once. Uses the above
  722. // LoadFromRegCriticalSection;
  723. static BOOL fLoadedLocalizedNames = FALSE;
  724. //+-------------------------------------------------------------------------
  725. // OIDInfo allocation and free functions
  726. //--------------------------------------------------------------------------
  727. static void *OIDInfoAlloc(
  728. IN size_t cbBytes
  729. )
  730. {
  731. void *pv;
  732. pv = malloc(cbBytes);
  733. if (pv == NULL)
  734. SetLastError((DWORD) E_OUTOFMEMORY);
  735. return pv;
  736. }
  737. static void *OIDInfoRealloc(
  738. IN void *pvOrg,
  739. IN size_t cb
  740. )
  741. {
  742. void *pv;
  743. if (NULL == (pv = pvOrg ? realloc(pvOrg, cb) : malloc(cb)))
  744. SetLastError((DWORD) E_OUTOFMEMORY);
  745. return pv;
  746. }
  747. static void OIDInfoFree(
  748. IN void *pv
  749. )
  750. {
  751. free(pv);
  752. }
  753. //+-------------------------------------------------------------------------
  754. // Functions called at ProcessDetach to free the groups updated from the
  755. // registry during CryptFindOIDInfo's first call.
  756. //--------------------------------------------------------------------------
  757. static void FreeGroup(
  758. PGROUP_ENTRY pGroup
  759. )
  760. {
  761. DWORD cInfo = pGroup->cInfo;
  762. PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
  763. for ( ; cInfo > 0; cInfo--, pInfo++)
  764. OIDInfoFree((LPSTR)pInfo->pszOID);
  765. OIDInfoFree((PCRYPT_OID_INFO) pGroup->rgInfo);
  766. }
  767. static void FreeRegGroups()
  768. {
  769. FreeGroup(&RegBeforeGroup);
  770. FreeGroup(&RegAfterGroup);
  771. }
  772. //+-------------------------------------------------------------------------
  773. // Free resource strings allocated in groups having localized pwszName's.
  774. //--------------------------------------------------------------------------
  775. static void FreeGroupResources()
  776. {
  777. DWORD i;
  778. if (!fLoadedFromRegAndResources)
  779. // No resource strings allocated
  780. return;
  781. for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
  782. if (GroupTable[i].fLocalize) {
  783. DWORD cInfo = GroupTable[i].cInfo;
  784. PCRYPT_OID_INFO pInfo = (PCRYPT_OID_INFO) GroupTable[i].rgInfo;
  785. for ( ; cInfo > 0; cInfo--, pInfo++) {
  786. // pwszName is set to pwszNullName if the allocation failed
  787. if (pwszNullName != pInfo->pwszName) {
  788. OIDInfoFree((LPWSTR) pInfo->pwszName);
  789. pInfo->pwszName = pwszNullName;
  790. }
  791. }
  792. }
  793. }
  794. }
  795. //+-------------------------------------------------------------------------
  796. // Free memory allocated for localized names
  797. //--------------------------------------------------------------------------
  798. static void FreeLocalizedNames()
  799. {
  800. if (!fLoadedLocalizedNames)
  801. // No resource strings allocated
  802. return;
  803. for (DWORD i = 0; i < LOCALIZED_GROUP_CNT; i++) {
  804. DWORD cInfo = LocalizedGroupTable[i].cInfo;
  805. PLOCALIZED_NAME_INFO pInfo = LocalizedGroupTable[i].rgInfo;
  806. for ( ; cInfo > 0; cInfo--, pInfo++) {
  807. LPWSTR pwszLocalizedName = (LPWSTR) pInfo->pwszLocalizedName;
  808. if (pwszNullName != pwszLocalizedName)
  809. OIDInfoFree(pwszLocalizedName);
  810. }
  811. }
  812. OIDInfoFree(LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo);
  813. }
  814. //+-------------------------------------------------------------------------
  815. // Dll initialization
  816. //--------------------------------------------------------------------------
  817. BOOL
  818. WINAPI
  819. I_CryptOIDInfoDllMain(
  820. HMODULE hInst,
  821. ULONG ulReason,
  822. LPVOID lpReserved)
  823. {
  824. BOOL fRet = TRUE;
  825. switch (ulReason) {
  826. case DLL_PROCESS_ATTACH:
  827. hOIDInfoInst = hInst;
  828. fRet = Pki_InitializeCriticalSection(&LoadFromRegCriticalSection);
  829. if (fRet) {
  830. fRet = Pki_InitializeCriticalSection(&DsCriticalSection);
  831. if (!fRet)
  832. DeleteCriticalSection(&LoadFromRegCriticalSection);
  833. }
  834. break;
  835. case DLL_PROCESS_DETACH:
  836. FreeRegGroups();
  837. FreeGroupResources();
  838. FreeLocalizedNames();
  839. DeleteCriticalSection(&LoadFromRegCriticalSection);
  840. FreeDsGroups();
  841. DeleteCriticalSection(&DsCriticalSection);
  842. break;
  843. case DLL_THREAD_DETACH:
  844. default:
  845. break;
  846. }
  847. return fRet;
  848. }
  849. //+-------------------------------------------------------------------------
  850. // Allocated and format the string consisting of the OID and GROUP_ID:
  851. //
  852. // For example: 1.2.3.4!6
  853. //--------------------------------------------------------------------------
  854. static LPSTR FormatOIDGroupString(
  855. IN PCCRYPT_OID_INFO pInfo
  856. )
  857. {
  858. LPSTR pszOIDGroupString;
  859. DWORD cchOIDGroupString;
  860. char szGroupId[34];
  861. if (NULL == pInfo || pInfo->cbSize < sizeof(CRYPT_OID_INFO) ||
  862. (DWORD_PTR) pInfo->pszOID <= 0xFFFF) {
  863. SetLastError((DWORD) E_INVALIDARG);
  864. return NULL;
  865. }
  866. szGroupId[0] = CONST_OID_GROUP_PREFIX_CHAR;
  867. _ltoa((long) pInfo->dwGroupId, &szGroupId[1], 10);
  868. cchOIDGroupString = strlen(pInfo->pszOID) +
  869. strlen(szGroupId) +
  870. 1;
  871. if (pszOIDGroupString = (LPSTR) OIDInfoAlloc(cchOIDGroupString)) {
  872. strcpy(pszOIDGroupString, pInfo->pszOID);
  873. strcat(pszOIDGroupString, szGroupId);
  874. }
  875. return pszOIDGroupString;
  876. }
  877. //+-------------------------------------------------------------------------
  878. // Wrapper function for calling CryptSetOIDFunctionValue using OID info's
  879. // encoding type and function name.
  880. //--------------------------------------------------------------------------
  881. static BOOL SetOIDInfoRegValue(
  882. IN LPCSTR pszOIDGroupString,
  883. IN LPCWSTR pwszValueName,
  884. IN DWORD dwValueType,
  885. IN const BYTE *pbValueData,
  886. IN DWORD cbValueData
  887. )
  888. {
  889. return CryptSetOIDFunctionValue(
  890. OID_INFO_ENCODING_TYPE,
  891. CRYPT_OID_FIND_OID_INFO_FUNC,
  892. pszOIDGroupString,
  893. pwszValueName,
  894. dwValueType,
  895. pbValueData,
  896. cbValueData
  897. );
  898. }
  899. //+-------------------------------------------------------------------------
  900. // Register OID information.
  901. //--------------------------------------------------------------------------
  902. BOOL
  903. WINAPI
  904. CryptRegisterOIDInfo(
  905. IN PCCRYPT_OID_INFO pInfo,
  906. IN DWORD dwFlags
  907. )
  908. {
  909. BOOL fResult;
  910. LPSTR pszOIDGroupString = NULL;
  911. if (NULL == (pszOIDGroupString = FormatOIDGroupString(pInfo)))
  912. goto FormatOIDGroupStringError;
  913. if (pInfo->pwszName && L'\0' != *pInfo->pwszName) {
  914. if (!SetOIDInfoRegValue(
  915. pszOIDGroupString,
  916. OID_INFO_NAME_VALUE_NAME,
  917. REG_SZ,
  918. (const BYTE *) pInfo->pwszName,
  919. (wcslen(pInfo->pwszName) + 1) * sizeof(WCHAR)
  920. )) goto SetOIDInfoRegValueError;
  921. }
  922. if (0 != pInfo->Algid) {
  923. if (!SetOIDInfoRegValue(
  924. pszOIDGroupString,
  925. OID_INFO_ALGID_VALUE_NAME,
  926. REG_DWORD,
  927. (const BYTE *) &pInfo->Algid,
  928. sizeof(pInfo->Algid)
  929. )) goto SetOIDInfoRegValueError;
  930. }
  931. if (0 != pInfo->ExtraInfo.cbData) {
  932. if (!SetOIDInfoRegValue(
  933. pszOIDGroupString,
  934. OID_INFO_EXTRA_INFO_VALUE_NAME,
  935. REG_BINARY,
  936. pInfo->ExtraInfo.pbData,
  937. pInfo->ExtraInfo.cbData
  938. )) goto SetOIDInfoRegValueError;
  939. }
  940. if (0 != dwFlags) {
  941. if (!SetOIDInfoRegValue(
  942. pszOIDGroupString,
  943. OID_INFO_FLAGS_VALUE_NAME,
  944. REG_DWORD,
  945. (const BYTE *) &dwFlags,
  946. sizeof(dwFlags)
  947. )) goto SetOIDInfoRegValueError;
  948. }
  949. fResult = TRUE;
  950. CommonReturn:
  951. OIDInfoFree(pszOIDGroupString);
  952. return fResult;
  953. ErrorReturn:
  954. fResult = FALSE;
  955. goto CommonReturn;
  956. TRACE_ERROR(FormatOIDGroupStringError)
  957. TRACE_ERROR(SetOIDInfoRegValueError)
  958. }
  959. //+-------------------------------------------------------------------------
  960. // Unregister OID information. Only the pszOID and dwGroupId fields are
  961. // used to identify the OID information to be unregistered.
  962. //--------------------------------------------------------------------------
  963. BOOL
  964. WINAPI
  965. CryptUnregisterOIDInfo(
  966. IN PCCRYPT_OID_INFO pInfo
  967. )
  968. {
  969. BOOL fResult;
  970. LPSTR pszOIDGroupString = NULL;
  971. if (NULL == (pszOIDGroupString = FormatOIDGroupString(pInfo)))
  972. goto FormatOIDGroupStringError;
  973. if (!CryptUnregisterOIDFunction(
  974. OID_INFO_ENCODING_TYPE,
  975. CRYPT_OID_FIND_OID_INFO_FUNC,
  976. pszOIDGroupString
  977. ))
  978. goto UnregisterOIDFunctionError;
  979. fResult = TRUE;
  980. CommonReturn:
  981. OIDInfoFree(pszOIDGroupString);
  982. return fResult;
  983. ErrorReturn:
  984. fResult = FALSE;
  985. goto CommonReturn;
  986. TRACE_ERROR(FormatOIDGroupStringError)
  987. TRACE_ERROR(UnregisterOIDFunctionError)
  988. }
  989. //+-------------------------------------------------------------------------
  990. // Called by CryptEnumOIDFunction to enumerate through all the
  991. // registered OID information.
  992. //
  993. // Called within critical section
  994. //--------------------------------------------------------------------------
  995. static BOOL WINAPI EnumRegistryCallback(
  996. IN DWORD dwEncodingType,
  997. IN LPCSTR pszFuncName,
  998. IN LPCSTR pszOID,
  999. IN DWORD cValue,
  1000. IN const DWORD rgdwValueType[],
  1001. IN LPCWSTR const rgpwszValueName[],
  1002. IN const BYTE * const rgpbValueData[],
  1003. IN const DWORD rgcbValueData[],
  1004. IN void *pvArg
  1005. )
  1006. {
  1007. DWORD cchOID;
  1008. LPCWSTR pwszName = NULL;
  1009. DWORD cchName = 0;
  1010. LPCSTR pszGroupId;
  1011. DWORD dwGroupId = 0;
  1012. ALG_ID Algid = 0;
  1013. CRYPT_DATA_BLOB ExtraInfo = {0, NULL};
  1014. DWORD dwFlags = 0;
  1015. DWORD cbExtra;
  1016. BYTE *pbExtra;
  1017. PGROUP_ENTRY pGroup;
  1018. PCRYPT_OID_INFO pInfo;
  1019. // The pszOID consists of OID!<dwGroupId>, for example, 1.2.3!1
  1020. // Start at the end and search for the '!'
  1021. cchOID = strlen(pszOID);
  1022. pszGroupId = pszOID + cchOID;
  1023. while (pszGroupId > pszOID && CONST_OID_GROUP_PREFIX_CHAR != *pszGroupId)
  1024. pszGroupId--;
  1025. if (CONST_OID_GROUP_PREFIX_CHAR == *pszGroupId) {
  1026. cchOID = (DWORD)(pszGroupId - pszOID);
  1027. dwGroupId = (DWORD) atol(pszGroupId + 1);
  1028. } else
  1029. // Name is missing "!". Skip It.
  1030. return TRUE;
  1031. while (cValue--) {
  1032. LPCWSTR pwszValueName = rgpwszValueName[cValue];
  1033. DWORD dwValueType = rgdwValueType[cValue];
  1034. const BYTE *pbValueData = rgpbValueData[cValue];
  1035. DWORD cbValueData = rgcbValueData[cValue];
  1036. if (0 == _wcsicmp(pwszValueName, OID_INFO_NAME_VALUE_NAME)) {
  1037. if (REG_SZ == dwValueType) {
  1038. pwszName = (LPWSTR) pbValueData;
  1039. cchName = wcslen(pwszName);
  1040. }
  1041. } else if (0 == _wcsicmp(pwszValueName, OID_INFO_ALGID_VALUE_NAME)) {
  1042. if (REG_DWORD == dwValueType &&
  1043. cbValueData >= sizeof(Algid))
  1044. memcpy(&Algid, pbValueData, sizeof(Algid));
  1045. } else if (0 == _wcsicmp(pwszValueName,
  1046. OID_INFO_EXTRA_INFO_VALUE_NAME)) {
  1047. if (REG_BINARY == dwValueType) {
  1048. ExtraInfo.cbData = cbValueData;
  1049. ExtraInfo.pbData = (BYTE *) pbValueData;
  1050. }
  1051. } else if (0 == _wcsicmp(pwszValueName, OID_INFO_FLAGS_VALUE_NAME)) {
  1052. if (REG_DWORD == dwValueType &&
  1053. cbValueData >= sizeof(dwFlags))
  1054. memcpy(&dwFlags, pbValueData, sizeof(dwFlags));
  1055. }
  1056. }
  1057. cbExtra = LEN_ALIGN(cchOID + 1) +
  1058. LEN_ALIGN((cchName + 1) * sizeof(WCHAR)) +
  1059. ExtraInfo.cbData;
  1060. if (NULL == (pbExtra = (BYTE *) OIDInfoAlloc(cbExtra)))
  1061. return FALSE;
  1062. if (dwFlags & CRYPT_INSTALL_OID_INFO_BEFORE_FLAG)
  1063. pGroup = &RegBeforeGroup;
  1064. else
  1065. pGroup = &RegAfterGroup;
  1066. if (NULL == (pInfo = (PCRYPT_OID_INFO) OIDInfoRealloc(
  1067. (PCRYPT_OID_INFO) pGroup->rgInfo,
  1068. (pGroup->cInfo + 1) * sizeof(CRYPT_OID_INFO)))) {
  1069. OIDInfoFree(pbExtra);
  1070. return FALSE;
  1071. }
  1072. pGroup->rgInfo = pInfo;
  1073. pInfo = &pInfo[pGroup->cInfo++];
  1074. pInfo->cbSize = sizeof(CRYPT_OID_INFO);
  1075. pInfo->pszOID = (LPCSTR) pbExtra;
  1076. if (cchOID)
  1077. memcpy(pbExtra, pszOID, cchOID);
  1078. *( ((LPSTR) pbExtra) + cchOID) = '\0';
  1079. pbExtra += LEN_ALIGN(cchOID + 1);
  1080. pInfo->pwszName = (LPCWSTR) pbExtra;
  1081. if (cchName)
  1082. memcpy(pbExtra, pwszName, (cchName + 1) * sizeof(WCHAR));
  1083. else
  1084. *((LPWSTR) pbExtra) = L'\0';
  1085. pbExtra += LEN_ALIGN((cchName + 1) * sizeof(WCHAR));
  1086. pInfo->dwGroupId = dwGroupId;
  1087. pInfo->Algid = Algid;
  1088. pInfo->ExtraInfo.cbData = ExtraInfo.cbData;
  1089. if (ExtraInfo.cbData > 0) {
  1090. pInfo->ExtraInfo.pbData = pbExtra;
  1091. memcpy(pbExtra, ExtraInfo.pbData, ExtraInfo.cbData);
  1092. } else
  1093. pInfo->ExtraInfo.pbData = NULL;
  1094. return TRUE;
  1095. }
  1096. //+-------------------------------------------------------------------------
  1097. // Allocate and load the string for the specified resource.
  1098. //
  1099. // If LoadString or allocation fails, returns predefined pointer to an
  1100. // empty string.
  1101. //--------------------------------------------------------------------------
  1102. static LPWSTR AllocAndLoadOIDNameString(
  1103. IN UINT uID
  1104. )
  1105. {
  1106. WCHAR wszResource[MAX_RESOURCE_OID_NAME_LENGTH + 1];
  1107. int cchResource;
  1108. int cbResource;
  1109. LPWSTR pwszDst;
  1110. cchResource = LoadStringU(hOIDInfoInst, uID, wszResource,
  1111. MAX_RESOURCE_OID_NAME_LENGTH);
  1112. assert(0 < cchResource);
  1113. if (0 >= cchResource)
  1114. return (LPWSTR) pwszNullName;
  1115. cbResource = (cchResource + 1) * sizeof(WCHAR);
  1116. pwszDst = (LPWSTR) OIDInfoAlloc(cbResource);
  1117. assert(pwszDst);
  1118. if (NULL == pwszDst)
  1119. return (LPWSTR) pwszNullName;
  1120. memcpy((BYTE *) pwszDst, (BYTE *) wszResource, cbResource);
  1121. return pwszDst;
  1122. }
  1123. //+-------------------------------------------------------------------------
  1124. // Allocate and copy the string.
  1125. //
  1126. // If allocation fails, returns predefined pointer to an empty string.
  1127. //--------------------------------------------------------------------------
  1128. static LPWSTR AllocAndCopyOIDNameString(
  1129. IN LPCWSTR pwszSrc
  1130. )
  1131. {
  1132. DWORD cbSrc;
  1133. LPWSTR pwszDst;
  1134. cbSrc = (wcslen(pwszSrc) + 1) * sizeof(WCHAR);
  1135. pwszDst = (LPWSTR) OIDInfoAlloc(cbSrc);
  1136. assert(pwszDst);
  1137. if (NULL == pwszDst)
  1138. return (LPWSTR) pwszNullName;
  1139. memcpy((BYTE *) pwszDst, (BYTE *) pwszSrc, cbSrc);
  1140. return pwszDst;
  1141. }
  1142. //+-------------------------------------------------------------------------
  1143. // Does a LoadString for pwszName's initialized with resource IDs in groups
  1144. // with fLocalize set.
  1145. //--------------------------------------------------------------------------
  1146. static void LoadGroupResources()
  1147. {
  1148. DWORD i;
  1149. for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
  1150. if (GroupTable[i].fLocalize) {
  1151. DWORD cInfo = GroupTable[i].cInfo;
  1152. PCRYPT_OID_INFO pInfo = (PCRYPT_OID_INFO) GroupTable[i].rgInfo;
  1153. for ( ; cInfo > 0; cInfo--, pInfo++) {
  1154. UINT_PTR uID;
  1155. uID = (UINT_PTR) pInfo->pwszName;
  1156. if (uID <= 0xFFFF)
  1157. pInfo->pwszName = AllocAndLoadOIDNameString((UINT)uID);
  1158. else
  1159. // ProcessDetach expects all pwszName's to be allocated
  1160. pInfo->pwszName = AllocAndCopyOIDNameString(
  1161. pInfo->pwszName);
  1162. }
  1163. }
  1164. }
  1165. }
  1166. //+-------------------------------------------------------------------------
  1167. // Load OID Information from the registry. Updates the RegBeforeGroup and
  1168. // RegAfterGroup.
  1169. //
  1170. // Loads resource strings in groups enabling localization of pwszName's.
  1171. //--------------------------------------------------------------------------
  1172. static void LoadFromRegistryAndResources()
  1173. {
  1174. if (fLoadedFromRegAndResources)
  1175. return;
  1176. EnterCriticalSection(&LoadFromRegCriticalSection);
  1177. if (!fLoadedFromRegAndResources) {
  1178. CryptEnumOIDFunction(
  1179. OID_INFO_ENCODING_TYPE,
  1180. CRYPT_OID_FIND_OID_INFO_FUNC,
  1181. NULL, // pszOID
  1182. 0, // dwFlags
  1183. NULL, // pvArg
  1184. EnumRegistryCallback
  1185. );
  1186. LoadGroupResources();
  1187. fLoadedFromRegAndResources = TRUE;
  1188. }
  1189. LeaveCriticalSection(&LoadFromRegCriticalSection);
  1190. }
  1191. //+-------------------------------------------------------------------------
  1192. // Compare the OID info according to the specified key and group.
  1193. //--------------------------------------------------------------------------
  1194. static BOOL CompareOIDInfo(
  1195. IN DWORD dwKeyType,
  1196. IN void *pvKey,
  1197. IN DWORD dwGroupId,
  1198. IN PCCRYPT_OID_INFO pInfo
  1199. )
  1200. {
  1201. if (dwGroupId && dwGroupId != pInfo->dwGroupId)
  1202. return FALSE;
  1203. switch (dwKeyType) {
  1204. case CRYPT_OID_INFO_OID_KEY:
  1205. if (0 == _stricmp((LPSTR) pvKey, pInfo->pszOID))
  1206. return TRUE;
  1207. break;
  1208. case CRYPT_OID_INFO_NAME_KEY:
  1209. if (0 == _wcsicmp((LPWSTR) pvKey, pInfo->pwszName))
  1210. return TRUE;
  1211. break;
  1212. case CRYPT_OID_INFO_ALGID_KEY:
  1213. if (*((ALG_ID *) pvKey) == pInfo->Algid)
  1214. return TRUE;
  1215. break;
  1216. case CRYPT_OID_INFO_SIGN_KEY:
  1217. {
  1218. ALG_ID *paiKey = (ALG_ID *) pvKey;
  1219. ALG_ID aiPubKey;
  1220. if (sizeof(ALG_ID) <= pInfo->ExtraInfo.cbData)
  1221. aiPubKey = *((ALG_ID *) pInfo->ExtraInfo.pbData);
  1222. else
  1223. aiPubKey = 0;
  1224. if (paiKey[0] == pInfo->Algid &&
  1225. paiKey[1] == aiPubKey)
  1226. return TRUE;
  1227. }
  1228. break;
  1229. default:
  1230. SetLastError((DWORD) E_INVALIDARG);
  1231. return FALSE;
  1232. }
  1233. return FALSE;
  1234. }
  1235. //+-------------------------------------------------------------------------
  1236. // Search the group according to the specified dwKeyType.
  1237. //
  1238. // Note, the groups updated from the registry, RegBeforeGroup and
  1239. // RegAfterGroup, may contain any GROUP_ID.
  1240. //--------------------------------------------------------------------------
  1241. static PCCRYPT_OID_INFO SearchGroup(
  1242. IN DWORD dwKeyType,
  1243. IN void *pvKey,
  1244. IN DWORD dwGroupId,
  1245. IN PCGROUP_ENTRY pGroup
  1246. )
  1247. {
  1248. DWORD cInfo = pGroup->cInfo;
  1249. PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
  1250. for ( ; cInfo > 0; cInfo--, pInfo++) {
  1251. if (CompareOIDInfo(
  1252. dwKeyType,
  1253. pvKey,
  1254. dwGroupId,
  1255. pInfo
  1256. ))
  1257. return pInfo;
  1258. }
  1259. return NULL;
  1260. }
  1261. //+-------------------------------------------------------------------------
  1262. // Find OID information. Returns NULL if unable to find any information
  1263. // for the specified key and group.
  1264. //--------------------------------------------------------------------------
  1265. PCCRYPT_OID_INFO
  1266. WINAPI
  1267. CryptFindOIDInfo(
  1268. IN DWORD dwKeyType,
  1269. IN void *pvKey,
  1270. IN DWORD dwGroupId // 0 => any group
  1271. )
  1272. {
  1273. PCCRYPT_OID_INFO pInfo;
  1274. LoadFromRegistryAndResources();
  1275. if (RegBeforeGroup.cInfo && NULL != (pInfo = SearchGroup(
  1276. dwKeyType,
  1277. pvKey,
  1278. dwGroupId,
  1279. &RegBeforeGroup
  1280. ))) return pInfo;
  1281. if (0 == dwGroupId) {
  1282. DWORD i;
  1283. for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
  1284. if (pInfo = SearchGroup(
  1285. dwKeyType,
  1286. pvKey,
  1287. 0,
  1288. &GroupTable[i]
  1289. )) return pInfo;
  1290. }
  1291. } else if (dwGroupId <= CRYPT_LAST_OID_GROUP_ID) {
  1292. if (pInfo = SearchGroup(
  1293. dwKeyType,
  1294. pvKey,
  1295. dwGroupId,
  1296. &GroupTable[dwGroupId]
  1297. )) return pInfo;
  1298. }
  1299. if (RegAfterGroup.cInfo && NULL != (pInfo = SearchGroup(
  1300. dwKeyType,
  1301. pvKey,
  1302. dwGroupId,
  1303. &RegAfterGroup
  1304. ))) return pInfo;
  1305. return SearchDsGroup(
  1306. dwKeyType,
  1307. pvKey,
  1308. dwGroupId
  1309. );
  1310. }
  1311. //+-------------------------------------------------------------------------
  1312. // Enumerate the group.
  1313. //--------------------------------------------------------------------------
  1314. static BOOL EnumGroup(
  1315. IN DWORD dwGroupId,
  1316. IN PCGROUP_ENTRY pGroup,
  1317. IN void *pvArg,
  1318. IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
  1319. )
  1320. {
  1321. DWORD cInfo = pGroup->cInfo;
  1322. PCCRYPT_OID_INFO pInfo = pGroup->rgInfo;
  1323. for ( ; cInfo > 0; cInfo--, pInfo++) {
  1324. if (dwGroupId && dwGroupId != pInfo->dwGroupId)
  1325. continue;
  1326. if (!pfnEnumOIDInfo(pInfo, pvArg))
  1327. return FALSE;
  1328. }
  1329. return TRUE;
  1330. }
  1331. //+-------------------------------------------------------------------------
  1332. // Enumerate the OID information.
  1333. //
  1334. // pfnEnumOIDInfo is called for each OID information entry.
  1335. //
  1336. // Setting dwGroupId to 0 matches all groups. Otherwise, only enumerates
  1337. // entries in the specified group.
  1338. //
  1339. // dwFlags currently isn't used and must be set to 0.
  1340. //--------------------------------------------------------------------------
  1341. BOOL
  1342. WINAPI
  1343. CryptEnumOIDInfo(
  1344. IN DWORD dwGroupId,
  1345. IN DWORD dwFlags,
  1346. IN void *pvArg,
  1347. IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
  1348. )
  1349. {
  1350. LoadFromRegistryAndResources();
  1351. if (RegBeforeGroup.cInfo && !EnumGroup(
  1352. dwGroupId,
  1353. &RegBeforeGroup,
  1354. pvArg,
  1355. pfnEnumOIDInfo
  1356. )) return FALSE;
  1357. if (0 == dwGroupId) {
  1358. DWORD i;
  1359. for (i = 1; i <= CRYPT_LAST_OID_GROUP_ID; i++) {
  1360. if (!EnumGroup(
  1361. 0, // dwGroupId
  1362. &GroupTable[i],
  1363. pvArg,
  1364. pfnEnumOIDInfo
  1365. )) return FALSE;
  1366. }
  1367. } else if (dwGroupId <= CRYPT_LAST_OID_GROUP_ID) {
  1368. if (!EnumGroup(
  1369. dwGroupId,
  1370. &GroupTable[dwGroupId],
  1371. pvArg,
  1372. pfnEnumOIDInfo
  1373. )) return FALSE;
  1374. }
  1375. if (RegAfterGroup.cInfo && !EnumGroup(
  1376. dwGroupId,
  1377. &RegAfterGroup,
  1378. pvArg,
  1379. pfnEnumOIDInfo
  1380. )) return FALSE;
  1381. return EnumDsGroup(
  1382. dwGroupId,
  1383. pvArg,
  1384. pfnEnumOIDInfo
  1385. );
  1386. }
  1387. //+=========================================================================
  1388. // Localized Name Functions
  1389. //==========================================================================
  1390. //+-------------------------------------------------------------------------
  1391. // Called by CryptEnumOIDFunction to enumerate through all the
  1392. // registered localized name values.
  1393. //
  1394. // Called within critical section
  1395. //
  1396. // Note at ProcessDetach, the Info entry pwszLocalizedName strings are freed.
  1397. // Therefore, for each Info entry, do a single allocation for both the
  1398. // pwszLocalizedName and pwszCryptName. The pwszCryptName immediately
  1399. // follows the pwszLocalizedName.
  1400. //--------------------------------------------------------------------------
  1401. static BOOL WINAPI EnumRegLocalizedNamesCallback(
  1402. IN DWORD dwEncodingType,
  1403. IN LPCSTR pszFuncName,
  1404. IN LPCSTR pszOID,
  1405. IN DWORD cValue,
  1406. IN const DWORD rgdwValueType[],
  1407. IN LPCWSTR const rgpwszValueName[],
  1408. IN const BYTE * const rgpbValueData[],
  1409. IN const DWORD rgcbValueData[],
  1410. IN void *pvArg
  1411. )
  1412. {
  1413. BOOL fResult;
  1414. DWORD cInfo = LocalizedGroupTable[REG_LOCALIZED_GROUP].cInfo;
  1415. PLOCALIZED_NAME_INFO pInfo =
  1416. LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo;
  1417. assert(CRYPT_LOCALIZED_NAME_ENCODING_TYPE == dwEncodingType);
  1418. assert(0 == _stricmp(CRYPT_OID_FIND_LOCALIZED_NAME_FUNC, pszFuncName));
  1419. assert(0 == _stricmp(CRYPT_LOCALIZED_NAME_OID, pszOID));
  1420. while (cValue--) {
  1421. if (REG_SZ == rgdwValueType[cValue]) {
  1422. LPCWSTR pwszLocalizedName = (LPCWSTR) rgpbValueData[cValue];
  1423. DWORD cchLocalizedName;
  1424. DWORD cbLocalizedName;
  1425. LPCWSTR pwszCryptName = rgpwszValueName[cValue];
  1426. DWORD cbCryptName;
  1427. LPWSTR pwszBothNames;
  1428. PLOCALIZED_NAME_INFO pNewInfo;
  1429. // Check for empty name string
  1430. cchLocalizedName = wcslen(pwszLocalizedName);
  1431. if (0 == cchLocalizedName)
  1432. continue;
  1433. cbLocalizedName = (cchLocalizedName + 1) * sizeof(WCHAR);
  1434. cbCryptName = (wcslen(pwszCryptName) + 1) * sizeof(WCHAR);
  1435. if (NULL == (pwszBothNames = (LPWSTR) OIDInfoAlloc(
  1436. cbLocalizedName + cbCryptName)))
  1437. goto OutOfMemory;
  1438. if (NULL == (pNewInfo = (PLOCALIZED_NAME_INFO) OIDInfoRealloc(
  1439. pInfo, (cInfo + 1) * sizeof(LOCALIZED_NAME_INFO)))) {
  1440. OIDInfoFree(pwszBothNames);
  1441. goto OutOfMemory;
  1442. }
  1443. pInfo = pNewInfo;
  1444. pInfo[cInfo].pwszLocalizedName = (LPCWSTR) pwszBothNames;
  1445. memcpy(pwszBothNames, pwszLocalizedName, cbLocalizedName);
  1446. pwszBothNames =
  1447. (LPWSTR) ((BYTE *) pwszBothNames + cbLocalizedName);
  1448. pInfo[cInfo].pwszCryptName = (LPCWSTR) pwszBothNames;
  1449. memcpy(pwszBothNames, pwszCryptName, cbCryptName);
  1450. cInfo++;
  1451. }
  1452. }
  1453. fResult = TRUE;
  1454. CommonReturn:
  1455. LocalizedGroupTable[REG_LOCALIZED_GROUP].cInfo = cInfo;
  1456. LocalizedGroupTable[REG_LOCALIZED_GROUP].rgInfo = pInfo;
  1457. return fResult;
  1458. ErrorReturn:
  1459. fResult = FALSE;
  1460. goto CommonReturn;
  1461. TRACE_ERROR(OutOfMemory)
  1462. }
  1463. static void LoadPredefinedNameResources()
  1464. {
  1465. for (DWORD i = 0; i < PREDEFINED_NAME_CNT; i++) {
  1466. LPWSTR pwszLocalizedName;
  1467. // Note, the following always returns a non-NULL string pointer.
  1468. pwszLocalizedName = AllocAndLoadOIDNameString(
  1469. PredefinedNameTable[i].uIDLocalizedName);
  1470. if (L'\0' == *pwszLocalizedName)
  1471. pwszLocalizedName = NULL;
  1472. PredefinedNameTable[i].pwszLocalizedName = (LPCWSTR) pwszLocalizedName;
  1473. }
  1474. }
  1475. static void LoadLocalizedNamesFromRegAndResources()
  1476. {
  1477. if (fLoadedLocalizedNames)
  1478. return;
  1479. EnterCriticalSection(&LoadFromRegCriticalSection);
  1480. if (!fLoadedLocalizedNames) {
  1481. CryptEnumOIDFunction(
  1482. CRYPT_LOCALIZED_NAME_ENCODING_TYPE,
  1483. CRYPT_OID_FIND_LOCALIZED_NAME_FUNC,
  1484. CRYPT_LOCALIZED_NAME_OID,
  1485. 0, // dwFlags
  1486. NULL, // pvArg
  1487. EnumRegLocalizedNamesCallback
  1488. );
  1489. LoadPredefinedNameResources();
  1490. fLoadedLocalizedNames = TRUE;
  1491. }
  1492. LeaveCriticalSection(&LoadFromRegCriticalSection);
  1493. }
  1494. //+-------------------------------------------------------------------------
  1495. // Find the localized name for the specified name. For example, find the
  1496. // localized name for the "Root" system store name. A case insensitive
  1497. // string comparison is done.
  1498. //
  1499. // Returns NULL if unable to find the the specified name.
  1500. //--------------------------------------------------------------------------
  1501. LPCWSTR
  1502. WINAPI
  1503. CryptFindLocalizedName(
  1504. IN LPCWSTR pwszCryptName
  1505. )
  1506. {
  1507. if (NULL == pwszCryptName || L'\0' == *pwszCryptName)
  1508. return NULL;
  1509. LoadLocalizedNamesFromRegAndResources();
  1510. for (DWORD i = 0; i < LOCALIZED_GROUP_CNT; i++) {
  1511. DWORD cInfo = LocalizedGroupTable[i].cInfo;
  1512. PLOCALIZED_NAME_INFO pInfo = LocalizedGroupTable[i].rgInfo;
  1513. for ( ; cInfo > 0; cInfo--, pInfo++) {
  1514. if (0 == _wcsicmp(pwszCryptName, pInfo->pwszCryptName))
  1515. return pInfo->pwszLocalizedName;
  1516. }
  1517. }
  1518. return NULL;
  1519. }
  1520. //+=========================================================================
  1521. // DS Group Functions
  1522. //==========================================================================
  1523. // certcli.dll has the helper function for getting the LDAP URL to the
  1524. // OID info stored in the DS.
  1525. #define sz_CERTCLI_DLL "certcli.dll"
  1526. #define sz_CAOIDGetLdapURL "CAOIDGetLdapURL"
  1527. #define sz_CAOIDFreeLdapURL "CAOIDFreeLdapURL"
  1528. typedef HRESULT (WINAPI *PFN_CA_OID_GET_LDAP_URL)(
  1529. IN DWORD dwType,
  1530. IN DWORD dwFlag,
  1531. OUT LPWSTR *ppwszURL
  1532. );
  1533. typedef HRESULT (WINAPI *PFN_CA_OID_FREE_LDAP_URL)(
  1534. IN LPCWSTR pwszURL
  1535. );
  1536. #if 1
  1537. //+-------------------------------------------------------------------------
  1538. // Gets the LDAP URL for and then uses to retrieve the OID info stored
  1539. // in the DS.
  1540. //
  1541. // Returns NULL if unable to do a successful LDAP retrieval.
  1542. //
  1543. // If the OID object doesn't exist in the directory, returns FALSE with
  1544. // LastError == ERROR_FILE_NOT_FOUND.
  1545. //
  1546. // Assumption: not in DsCriticalSection
  1547. //--------------------------------------------------------------------------
  1548. static PCRYPT_BLOB_ARRAY RetrieveDsGroupByLdapUrl()
  1549. {
  1550. PCRYPT_BLOB_ARRAY pcba = NULL;
  1551. HRESULT hr;
  1552. LPWSTR pwszUrl = NULL;
  1553. HMODULE hDll = NULL;
  1554. PFN_CA_OID_GET_LDAP_URL pfnCAOIDGetLdapURL = NULL;
  1555. PFN_CA_OID_FREE_LDAP_URL pfnCAOIDFreeLdapURL = NULL;
  1556. if (!ChainIsConnected())
  1557. goto NotConnected;
  1558. if (NULL == (hDll = LoadLibraryA(sz_CERTCLI_DLL)))
  1559. goto LoadCertCliDllError;
  1560. if (NULL == (pfnCAOIDGetLdapURL =
  1561. (PFN_CA_OID_GET_LDAP_URL) GetProcAddress(hDll,
  1562. sz_CAOIDGetLdapURL)))
  1563. goto CAOIDGetLdapURLProcAddressError;
  1564. if (NULL == (pfnCAOIDFreeLdapURL =
  1565. (PFN_CA_OID_FREE_LDAP_URL) GetProcAddress(hDll,
  1566. sz_CAOIDFreeLdapURL)))
  1567. goto CAOIDFreeLdapURLProcAddressError;
  1568. hr = pfnCAOIDGetLdapURL(
  1569. CERT_OID_TYPE_ALL,
  1570. 0, // dwFlags
  1571. &pwszUrl
  1572. );
  1573. if (S_OK != hr)
  1574. goto CAOIDGetLdapURLError;
  1575. if (!ChainRetrieveObjectByUrlW (
  1576. pwszUrl,
  1577. NULL, // pszObjectOid,
  1578. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  1579. CRYPT_WIRE_ONLY_RETRIEVAL |
  1580. CRYPT_DONT_CACHE_RESULT |
  1581. CRYPT_OFFLINE_CHECK_RETRIEVAL |
  1582. CRYPT_LDAP_SIGN_RETRIEVAL |
  1583. CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE,
  1584. DS_LDAP_TIMEOUT,
  1585. (LPVOID*) &pcba,
  1586. NULL, // hAsyncRetrieve,
  1587. NULL, // pCredentials,
  1588. NULL, // pvVerify,
  1589. NULL // pAuxInfo
  1590. )) {
  1591. DWORD dwErr = GetLastError();
  1592. if (ERROR_FILE_NOT_FOUND == dwErr || CRYPT_E_NOT_FOUND == dwErr)
  1593. goto NoDsOIDObject;
  1594. else
  1595. goto RetrieveObjectByUrlError;
  1596. }
  1597. assert(pcba);
  1598. CommonReturn:
  1599. if (hDll) {
  1600. DWORD dwErr = GetLastError();
  1601. if (pfnCAOIDFreeLdapURL && pwszUrl)
  1602. pfnCAOIDFreeLdapURL(pwszUrl);
  1603. FreeLibrary(hDll);
  1604. SetLastError(dwErr);
  1605. }
  1606. return pcba;
  1607. ErrorReturn:
  1608. assert(NULL == pcba);
  1609. goto CommonReturn;
  1610. SET_ERROR(LoadCertCliDllError, ERROR_FILE_NOT_FOUND)
  1611. SET_ERROR(CAOIDGetLdapURLProcAddressError, ERROR_FILE_NOT_FOUND)
  1612. SET_ERROR(CAOIDFreeLdapURLProcAddressError, ERROR_FILE_NOT_FOUND)
  1613. SET_ERROR_VAR(CAOIDGetLdapURLError, hr)
  1614. SET_ERROR(NotConnected, ERROR_NOT_CONNECTED)
  1615. SET_ERROR(NoDsOIDObject, ERROR_FILE_NOT_FOUND)
  1616. TRACE_ERROR(RetrieveObjectByUrlError)
  1617. }
  1618. #else
  1619. // Hard coded URL and credentials for testing
  1620. static PCRYPT_BLOB_ARRAY RetrieveDsGroupByLdapUrl()
  1621. {
  1622. PCRYPT_BLOB_ARRAY pcba = NULL;
  1623. CRYPT_CREDENTIALS Credentials;
  1624. CRYPT_PASSWORD_CREDENTIALSA PasswordCredentials;
  1625. // This gets overwritten by logic in cryptnet.dll
  1626. // char szUsername[] = "domain\\username";
  1627. char szUsername[] = "jettdom\\administrator";
  1628. PasswordCredentials.cbSize = sizeof( PasswordCredentials );
  1629. PasswordCredentials.pszUsername = szUsername;
  1630. // PasswordCredentials.pszPassword = "password";
  1631. PasswordCredentials.pszPassword = "";
  1632. Credentials.cbSize = sizeof( Credentials );
  1633. Credentials.pszCredentialsOid = CREDENTIAL_OID_PASSWORD_CREDENTIALS_A;
  1634. Credentials.pvCredentials = (LPVOID)&PasswordCredentials;
  1635. if (!ChainIsConnected())
  1636. goto NotConnected;
  1637. if (!ChainRetrieveObjectByUrlW (
  1638. 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",
  1639. NULL, // pszObjectOid,
  1640. CRYPT_RETRIEVE_MULTIPLE_OBJECTS |
  1641. CRYPT_WIRE_ONLY_RETRIEVAL |
  1642. CRYPT_DONT_CACHE_RESULT |
  1643. CRYPT_OFFLINE_CHECK_RETRIEVAL |
  1644. CRYPT_LDAP_SIGN_RETRIEVAL |
  1645. CRYPT_LDAP_INSERT_ENTRY_ATTRIBUTE,
  1646. DS_LDAP_TIMEOUT,
  1647. (LPVOID*) &pcba,
  1648. NULL, // hAsyncRetrieve,
  1649. &Credentials,
  1650. NULL, // pvVerify,
  1651. NULL // pAuxInfo
  1652. )) {
  1653. if (ERROR_FILE_NOT_FOUND == GetLastError())
  1654. goto NoDsOIDObject;
  1655. else
  1656. goto RetrieveObjectByUrlError;
  1657. }
  1658. assert(pcba);
  1659. CommonReturn:
  1660. return pcba;
  1661. ErrorReturn:
  1662. assert(NULL == pcba);
  1663. goto CommonReturn;
  1664. SET_ERROR(NotConnected, ERROR_NOT_CONNECTED)
  1665. TRACE_ERROR(NoDsOIDObject)
  1666. TRACE_ERROR(RetrieveObjectByUrlError)
  1667. }
  1668. #endif
  1669. //+-------------------------------------------------------------------------
  1670. // Frees the DS groups
  1671. //
  1672. // Assumption: only called at ProcessDetach
  1673. //--------------------------------------------------------------------------
  1674. static void FreeDsGroups()
  1675. {
  1676. DWORD cInfo;
  1677. PCCRYPT_OID_INFO *ppInfo;
  1678. cInfo = DsGroup.cInfo;
  1679. ppInfo = DsGroup.rgpInfo;
  1680. for ( ; cInfo > 0; cInfo--, ppInfo++)
  1681. OIDInfoFree((PCRYPT_OID_INFO) *ppInfo);
  1682. OIDInfoFree(DsGroup.rgpInfo);
  1683. cInfo = DsDeletedGroup.cInfo;
  1684. ppInfo = DsDeletedGroup.rgpInfo;
  1685. for ( ; cInfo > 0; cInfo--, ppInfo++)
  1686. OIDInfoFree((PCRYPT_OID_INFO) *ppInfo);
  1687. OIDInfoFree(DsDeletedGroup.rgpInfo);
  1688. }
  1689. //+-------------------------------------------------------------------------
  1690. // Adds the OID info entries to the specified DS group
  1691. //
  1692. // Assumption: already in DsCriticalSection
  1693. //--------------------------------------------------------------------------
  1694. static BOOL AddDsOIDInfo(
  1695. IN PCCRYPT_OID_INFO *ppAddInfo,
  1696. IN DWORD cAddInfo,
  1697. IN OUT PDS_GROUP_ENTRY pGroup
  1698. )
  1699. {
  1700. PCCRYPT_OID_INFO *ppInfo;
  1701. assert(cAddInfo && ppAddInfo && *ppAddInfo);
  1702. if (NULL == (ppInfo = (PCCRYPT_OID_INFO *) OIDInfoRealloc(
  1703. pGroup->rgpInfo,
  1704. (pGroup->cInfo + cAddInfo) * sizeof(PCCRYPT_OID_INFO))))
  1705. return FALSE;
  1706. pGroup->rgpInfo = ppInfo;
  1707. ppInfo = &ppInfo[pGroup->cInfo];
  1708. pGroup->cInfo += cAddInfo;
  1709. for ( ; 0 < cAddInfo; cAddInfo --, ppAddInfo++, ppInfo++)
  1710. *ppInfo = *ppAddInfo;
  1711. return TRUE;
  1712. }
  1713. //+-------------------------------------------------------------------------
  1714. // Moves the OID info entries from one DS group to another DS group
  1715. //
  1716. // Assumption: already in DsCriticalSection
  1717. //--------------------------------------------------------------------------
  1718. static BOOL MoveDsOIDInfo(
  1719. IN DWORD dwInfoIndex,
  1720. IN DWORD cMoveInfo,
  1721. IN OUT PDS_GROUP_ENTRY pSrcGroup,
  1722. IN OUT PDS_GROUP_ENTRY pDstGroup
  1723. )
  1724. {
  1725. DWORD cInfo;
  1726. PCCRYPT_OID_INFO *ppInfo;
  1727. DWORD i, j;
  1728. if (0 == cMoveInfo)
  1729. return TRUE;
  1730. assert(dwInfoIndex + cMoveInfo <= pSrcGroup->cInfo);
  1731. if (!AddDsOIDInfo(
  1732. &pSrcGroup->rgpInfo[dwInfoIndex],
  1733. cMoveInfo,
  1734. pDstGroup
  1735. ))
  1736. return FALSE;
  1737. // Move all remaining infos down
  1738. cInfo = pSrcGroup->cInfo;
  1739. ppInfo = pSrcGroup->rgpInfo;
  1740. for (i = dwInfoIndex, j = i + cMoveInfo; j < cInfo; i++, j++)
  1741. ppInfo[i] = ppInfo[j];
  1742. pSrcGroup->cInfo = cInfo - cMoveInfo;
  1743. return TRUE;
  1744. }
  1745. //+-------------------------------------------------------------------------
  1746. // Creates the OID info by converting the LDAP DS attribute octets.
  1747. //
  1748. // If any of the cb's == 0 or not a valid converted group type, returns TRUE
  1749. // with *ppInfo = NULL
  1750. //--------------------------------------------------------------------------
  1751. static BOOL CreateDsOIDInfo(
  1752. IN BYTE *pbOID,
  1753. IN DWORD cbOID,
  1754. IN BYTE *pbName,
  1755. IN DWORD cbName,
  1756. IN BYTE *pbGroupId,
  1757. IN DWORD cbGroupId,
  1758. OUT PCCRYPT_OID_INFO *ppInfo
  1759. )
  1760. {
  1761. BOOL fResult;
  1762. PCRYPT_OID_INFO pInfo = NULL;
  1763. char szType[2];
  1764. DWORD dwType;
  1765. DWORD dwGroupId;
  1766. int cchName;
  1767. LPWSTR pwszName;
  1768. LPSTR pszOID;
  1769. DWORD cbExtra;
  1770. *ppInfo = NULL;
  1771. if (0 == cbOID || 0 == cbName || 1 != cbGroupId)
  1772. return TRUE;
  1773. // Convert the Type bytes to the GroupId and see if a valid DS OID group
  1774. szType[0] = (char) *pbGroupId;
  1775. szType[1] = '\0';
  1776. dwType = 0;
  1777. dwType = (DWORD) atol(szType);
  1778. switch (dwType) {
  1779. case CERT_OID_TYPE_TEMPLATE:
  1780. dwGroupId = CRYPT_TEMPLATE_OID_GROUP_ID;
  1781. break;
  1782. case CERT_OID_TYPE_ISSUER_POLICY:
  1783. dwGroupId = CRYPT_POLICY_OID_GROUP_ID;
  1784. break;
  1785. case CERT_OID_TYPE_APPLICATION_POLICY:
  1786. dwGroupId = CRYPT_ENHKEY_USAGE_OID_GROUP_ID;
  1787. break;
  1788. default:
  1789. return TRUE;
  1790. }
  1791. // The name is a UTF8 encoded string
  1792. cchName = UTF8ToWideChar(
  1793. (LPSTR) pbName,
  1794. cbName,
  1795. NULL, // lpWideCharStr
  1796. 0 // cchWideChar
  1797. );
  1798. if (1 > cchName)
  1799. return TRUE;
  1800. cbExtra = (cchName + 1) * sizeof(WCHAR) + (cbOID + 1);
  1801. pInfo = (PCRYPT_OID_INFO) OIDInfoAlloc(sizeof(CRYPT_OID_INFO) + cbExtra);
  1802. if (NULL == pInfo)
  1803. goto OutOfMemory;
  1804. memset(pInfo, 0, sizeof(CRYPT_OID_INFO));
  1805. pInfo->cbSize = sizeof(CRYPT_OID_INFO);
  1806. pInfo->dwGroupId = dwGroupId;
  1807. pwszName = (LPWSTR) &pInfo[1];
  1808. pInfo->pwszName = (LPCWSTR) pwszName;
  1809. cchName = UTF8ToWideChar(
  1810. (LPSTR) pbName,
  1811. cbName,
  1812. pwszName,
  1813. cchName
  1814. );
  1815. if (1 > cchName)
  1816. goto UTF8ToWideCharError;
  1817. pwszName[cchName] = L'\0';
  1818. pszOID = (LPSTR) (pwszName + (cchName + 1));
  1819. pInfo->pszOID = (LPCSTR) pszOID;
  1820. memcpy(pszOID, pbOID, cbOID);
  1821. pszOID[cbOID] = '\0';
  1822. *ppInfo = (PCCRYPT_OID_INFO) pInfo;
  1823. fResult = TRUE;
  1824. CommonReturn:
  1825. return fResult;
  1826. ErrorReturn:
  1827. fResult = FALSE;
  1828. goto CommonReturn;
  1829. TRACE_ERROR(OutOfMemory)
  1830. SET_ERROR(UTF8ToWideCharError, ERROR_INVALID_DATA)
  1831. }
  1832. //+-------------------------------------------------------------------------
  1833. // Creates the OID info entry corresponding to the LDAP DS attribute octets.
  1834. //
  1835. // If the OID info entry already exists in the DsDeletedGroup, then, the
  1836. // OID info entry is moved from DsDeletedGroup to DsGroup. Otherwise, the
  1837. // created OID entry is added to the DsGroup.
  1838. //
  1839. // Assumption: already in DsCriticalSection
  1840. //--------------------------------------------------------------------------
  1841. static BOOL CreateAndAddDsOIDInfo(
  1842. IN BYTE *pbOID,
  1843. IN DWORD cbOID,
  1844. IN BYTE *pbName,
  1845. IN DWORD cbName,
  1846. IN BYTE *pbGroupId,
  1847. IN DWORD cbGroupId
  1848. )
  1849. {
  1850. BOOL fResult;
  1851. PCCRYPT_OID_INFO pInfo = NULL;
  1852. DWORD cDeletedInfo;
  1853. PCCRYPT_OID_INFO *ppDeletedInfo;
  1854. DWORD i;
  1855. fResult = CreateDsOIDInfo(
  1856. pbOID,
  1857. cbOID,
  1858. pbName,
  1859. cbName,
  1860. pbGroupId,
  1861. cbGroupId,
  1862. &pInfo
  1863. );
  1864. if (NULL == pInfo)
  1865. // Either the create failed or not a valid DS OID group
  1866. return fResult;
  1867. // See if we have an entry in the DS deleted group
  1868. cDeletedInfo = DsDeletedGroup.cInfo;
  1869. ppDeletedInfo = DsDeletedGroup.rgpInfo;
  1870. for (i = 0; i < cDeletedInfo; i++) {
  1871. PCCRYPT_OID_INFO pDeletedInfo = ppDeletedInfo[i];
  1872. if (pInfo->dwGroupId == pDeletedInfo->dwGroupId &&
  1873. 0 == strcmp(pInfo->pszOID, pDeletedInfo->pszOID) &&
  1874. 0 == wcscmp(pInfo->pwszName, pDeletedInfo->pwszName))
  1875. break;
  1876. }
  1877. if (i < cDeletedInfo) {
  1878. if (!MoveDsOIDInfo(
  1879. i,
  1880. 1, // cInfo
  1881. &DsDeletedGroup,
  1882. &DsGroup
  1883. ))
  1884. goto MoveDsOIDInfoError;
  1885. OIDInfoFree((PCRYPT_OID_INFO) pInfo);
  1886. } else {
  1887. if (!AddDsOIDInfo(&pInfo, 1, &DsGroup))
  1888. goto AddDsOIDInfoError;
  1889. }
  1890. fResult = TRUE;
  1891. CommonReturn:
  1892. return fResult;
  1893. ErrorReturn:
  1894. OIDInfoFree((PCRYPT_OID_INFO) pInfo);
  1895. fResult = FALSE;
  1896. goto CommonReturn;
  1897. TRACE_ERROR(MoveDsOIDInfoError)
  1898. TRACE_ERROR(AddDsOIDInfoError)
  1899. }
  1900. //+-------------------------------------------------------------------------
  1901. // Allocates and converts UNICODE string to ASCII.
  1902. //--------------------------------------------------------------------------
  1903. static LPSTR AllocAndWszToSz(
  1904. IN LPCWSTR pwsz
  1905. )
  1906. {
  1907. int cchMultiByte;
  1908. LPSTR psz = NULL;
  1909. cchMultiByte = WideCharToMultiByte(
  1910. CP_ACP,
  1911. 0, // dwFlags
  1912. pwsz,
  1913. -1,
  1914. NULL, // psz,
  1915. 0, // cchMultiByte
  1916. NULL, // lpDefaultChar
  1917. NULL // lpfUsedDefaultChar
  1918. );
  1919. if (1 < cchMultiByte) {
  1920. psz = (LPSTR) OIDInfoAlloc(cchMultiByte);
  1921. if (NULL != psz) {
  1922. cchMultiByte = WideCharToMultiByte(
  1923. CP_ACP,
  1924. 0, // dwFlags
  1925. pwsz,
  1926. -1,
  1927. psz,
  1928. cchMultiByte,
  1929. NULL, // lpDefaultChar
  1930. NULL // lpfUsedDefaultChar
  1931. );
  1932. if (1 > cchMultiByte) {
  1933. OIDInfoFree(psz);
  1934. psz = NULL;
  1935. }
  1936. }
  1937. }
  1938. return psz;
  1939. }
  1940. //+------------------------------------------------------------------------------
  1941. // Helper functions to thunk APIs which don't exist on downlevels.
  1942. // oidinfo.obj is statically linked in with xenroll, which has to work on
  1943. // all downlevels (win9x, NT4, W2K, XP). Any functions which aren't supported
  1944. // on these platforms need to be thunked here to avoid a dependency violation.
  1945. //-------------------------------------------------------------------------------
  1946. #define sz_KERNEL32_DLL "kernel32.dll"
  1947. #define sz_GetSystemDefaultUILanguage "GetSystemDefaultUILanguage"
  1948. #define sz_GetUserDefaultUILanguage "GetUserDefaultUILanguage"
  1949. typedef LANGID (WINAPI *PFNGetSystemDefaultUILanguage) (
  1950. void
  1951. );
  1952. typedef LANGID (WINAPI *PFNGetUserDefaultUILanguage) (
  1953. void
  1954. );
  1955. //+------------------------------------------------------------------------------
  1956. // Helper function to thunk GetSystemDefaultUILanguage(). If this API isn't
  1957. // present, falls back to GetSystemDefaultLangID().
  1958. //------------------------------------------------------------------------------
  1959. static LANGID WINAPI MyGetSystemDefaultUILanguage(void)
  1960. {
  1961. HMODULE hKernel32 = NULL;
  1962. LANGID langidRetval;
  1963. PFNGetSystemDefaultUILanguage pfnGetSystemDefaultUILanguage = NULL;
  1964. hKernel32 = LoadLibraryA(sz_KERNEL32_DLL);
  1965. if (NULL != hKernel32) {
  1966. pfnGetSystemDefaultUILanguage = (PFNGetSystemDefaultUILanguage)GetProcAddress(hKernel32, sz_GetSystemDefaultUILanguage);
  1967. }
  1968. if (NULL != pfnGetSystemDefaultUILanguage) {
  1969. langidRetval = pfnGetSystemDefaultUILanguage();
  1970. } else {
  1971. langidRetval = GetSystemDefaultLangID();
  1972. }
  1973. if (NULL != hKernel32) {
  1974. FreeLibrary(hKernel32);
  1975. }
  1976. return langidRetval;
  1977. }
  1978. //+------------------------------------------------------------------------------
  1979. // Helper function to thunk GetUserDefaultUILanguage(). If this API isn't
  1980. // present, falls back to GetUserDefaultLangID().
  1981. //------------------------------------------------------------------------------
  1982. static LANGID WINAPI MyGetUserDefaultUILanguage(void)
  1983. {
  1984. HMODULE hKernel32 = NULL;
  1985. LANGID langidRetval;
  1986. PFNGetUserDefaultUILanguage pfnGetUserDefaultUILanguage = NULL;
  1987. hKernel32 = LoadLibraryA(sz_KERNEL32_DLL);
  1988. if (NULL != hKernel32) {
  1989. pfnGetUserDefaultUILanguage = (PFNGetUserDefaultUILanguage)GetProcAddress(hKernel32, sz_GetUserDefaultUILanguage);
  1990. }
  1991. if (NULL != pfnGetUserDefaultUILanguage) {
  1992. langidRetval = pfnGetUserDefaultUILanguage();
  1993. } else {
  1994. // Use GetSystemDefaultLangID for fallback, even in the user case.
  1995. // From weiwu: "GetUserDefaultLangID is mostly for standards and formats;
  1996. // it shouldn't be used as the UI language fallback."
  1997. langidRetval = GetSystemDefaultLangID();
  1998. }
  1999. if (NULL != hKernel32) {
  2000. FreeLibrary(hKernel32);
  2001. }
  2002. return langidRetval;
  2003. }
  2004. //+-------------------------------------------------------------------------
  2005. // Loads the DS group by doing an LDAP URL retrieval and
  2006. // converting the DS attribute octets into the OID info entries.
  2007. //
  2008. // Do the load on the first call. Do subsequent reloads after
  2009. // DS_RETRIEVAL_DELTA_SECONDS has elapsed since a successful load.
  2010. //
  2011. // Assumption: not in DsCriticalSection
  2012. //--------------------------------------------------------------------------
  2013. static void LoadDsGroup()
  2014. {
  2015. FILETIME CurrentTime;
  2016. LONG lCmp;
  2017. PCRYPT_BLOB_ARRAY pcba = NULL;
  2018. LPSTR pszOIDAttr = NULL;
  2019. LPSTR pszNameAttr = NULL;
  2020. LPSTR pszLocalizedNameAttr = NULL;
  2021. LPSTR pszGroupAttr = NULL;
  2022. LANGID SystemDefaultLangID = 0;
  2023. LPCSTR pszPrevIndex; // not allocated
  2024. BYTE *pbOID;
  2025. DWORD cbOID;
  2026. BYTE *pbName;
  2027. DWORD cbName;
  2028. BYTE *pbLocalizedName;
  2029. DWORD cbLocalizedName;
  2030. BYTE *pbGroupId;
  2031. DWORD cbGroupId;
  2032. DWORD i;
  2033. GetSystemTimeAsFileTime(&CurrentTime);
  2034. EnterCriticalSection(&DsCriticalSection);
  2035. lCmp = CompareFileTime(&DsNextUpdateTime, &CurrentTime);
  2036. LeaveCriticalSection(&DsCriticalSection);
  2037. if (0 < lCmp)
  2038. // Current time is before the next update time
  2039. return;
  2040. if (NULL == (pcba = RetrieveDsGroupByLdapUrl()) &&
  2041. ERROR_FILE_NOT_FOUND != GetLastError())
  2042. return;
  2043. EnterCriticalSection(&DsCriticalSection);
  2044. // Move all the Ds group entries to the deleted list. As we iterate
  2045. // through the retrieved LDAP entries, most if not all of the entries
  2046. // in the deleted group will be moved back.
  2047. if (!MoveDsOIDInfo(
  2048. 0, // dwInfoIndex
  2049. DsGroup.cInfo,
  2050. &DsGroup,
  2051. &DsDeletedGroup
  2052. ))
  2053. goto MoveDsGroupOIDInfoError;
  2054. if (NULL == pcba)
  2055. goto NoOIDObjectReturn;
  2056. pszOIDAttr = AllocAndWszToSz(OID_PROP_OID);
  2057. pszNameAttr = AllocAndWszToSz(OID_PROP_DISPLAY_NAME);
  2058. pszLocalizedNameAttr = AllocAndWszToSz(OID_PROP_LOCALIZED_NAME);
  2059. pszGroupAttr = AllocAndWszToSz(OID_PROP_TYPE);
  2060. if (NULL == pszOIDAttr || NULL == pszNameAttr ||
  2061. NULL == pszLocalizedNameAttr|| NULL == pszGroupAttr)
  2062. goto OutOfMemory;
  2063. pszPrevIndex = "";
  2064. pbOID = NULL;
  2065. cbOID = 0;
  2066. pbName = NULL;
  2067. cbName = 0;
  2068. pbLocalizedName = NULL;
  2069. cbLocalizedName = 0;
  2070. pbGroupId = NULL;
  2071. cbGroupId = 0;
  2072. for (i = 0; i < pcba->cBlob; i++ ) {
  2073. PBYTE pb = pcba->rgBlob[i].pbData;
  2074. DWORD cb = pcba->rgBlob[i].cbData;
  2075. DWORD cbPrefix;
  2076. LPCSTR pszIndex;
  2077. LPCSTR pszAttr;
  2078. pszIndex = (LPCSTR) pb;
  2079. cbPrefix = strlen(pszIndex) + 1;
  2080. pb += cbPrefix;
  2081. cb -= cbPrefix;
  2082. pszAttr = (LPCSTR) pb;
  2083. cbPrefix = strlen(pszAttr) + 1;
  2084. pb += cbPrefix;
  2085. cb -= cbPrefix;
  2086. if (0 != strcmp(pszIndex, pszPrevIndex)) {
  2087. if (!CreateAndAddDsOIDInfo(
  2088. pbOID,
  2089. cbOID,
  2090. cbLocalizedName ? pbLocalizedName : pbName,
  2091. cbLocalizedName ? cbLocalizedName : cbName,
  2092. pbGroupId,
  2093. cbGroupId
  2094. ))
  2095. goto CreateAndAddDsOIDInfoError;
  2096. pszPrevIndex = pszIndex;
  2097. pbOID = NULL;
  2098. cbOID = 0;
  2099. pbName = NULL;
  2100. cbName = 0;
  2101. pbLocalizedName = NULL;
  2102. cbLocalizedName = 0;
  2103. pbGroupId = NULL;
  2104. cbGroupId = 0;
  2105. }
  2106. if (0 == _stricmp(pszAttr, pszOIDAttr)) {
  2107. pbOID = pb;
  2108. cbOID = cb;
  2109. } else if (0 == _stricmp(pszAttr, pszNameAttr)) {
  2110. pbName = pb;
  2111. cbName = cb;
  2112. } else if (0 == _stricmp(pszAttr, pszLocalizedNameAttr)) {
  2113. // The LocalizedName consists of:
  2114. // "%d,%s", LangID, pszUTF8Name (Name isn't NULL terminated)
  2115. if (0 == cbLocalizedName) {
  2116. LPCSTR pszLangID;
  2117. // Search for the ',' delimiter and convert to a \0
  2118. pszLangID = (LPCSTR) pb;
  2119. for ( ; 0 < cb; pb++, cb--) {
  2120. if (',' == *pb) {
  2121. *pb = 0;
  2122. pb++;
  2123. cb--;
  2124. break;
  2125. }
  2126. }
  2127. if (0 < cb) {
  2128. LANGID LangID = 0;
  2129. LangID = (LANGID) strtoul(pszLangID, NULL, 10);
  2130. if (0 != LangID) {
  2131. if (0 == SystemDefaultLangID) {
  2132. SystemDefaultLangID = MyGetUserDefaultUILanguage();
  2133. if (0 == SystemDefaultLangID)
  2134. SystemDefaultLangID =
  2135. MyGetSystemDefaultUILanguage();
  2136. }
  2137. if (LangID == SystemDefaultLangID) {
  2138. cbLocalizedName = cb;
  2139. pbLocalizedName = pb;
  2140. }
  2141. }
  2142. }
  2143. }
  2144. } else if (0 == _stricmp(pszAttr, pszGroupAttr)) {
  2145. pbGroupId = pb;
  2146. cbGroupId = cb;
  2147. }
  2148. }
  2149. if (!CreateAndAddDsOIDInfo(
  2150. pbOID,
  2151. cbOID,
  2152. cbLocalizedName ? pbLocalizedName : pbName,
  2153. cbLocalizedName ? cbLocalizedName : cbName,
  2154. pbGroupId,
  2155. cbGroupId
  2156. ))
  2157. goto CreateAndAddDsOIDInfoError;
  2158. NoOIDObjectReturn:
  2159. I_CryptIncrementFileTimeBySeconds(
  2160. &CurrentTime,
  2161. DS_RETRIEVAL_DELTA_SECONDS,
  2162. &DsNextUpdateTime
  2163. );
  2164. CommonReturn:
  2165. LeaveCriticalSection(&DsCriticalSection);
  2166. OIDInfoFree(pszOIDAttr);
  2167. OIDInfoFree(pszNameAttr);
  2168. OIDInfoFree(pszLocalizedNameAttr);
  2169. OIDInfoFree(pszGroupAttr);
  2170. if (pcba)
  2171. CryptMemFree(pcba);
  2172. return;
  2173. ErrorReturn:
  2174. goto CommonReturn;
  2175. TRACE_ERROR(OutOfMemory)
  2176. TRACE_ERROR(MoveDsGroupOIDInfoError)
  2177. TRACE_ERROR(CreateAndAddDsOIDInfoError)
  2178. }
  2179. //+-------------------------------------------------------------------------
  2180. // The DS only contains the ENHKEY, POLICY and TEMPLATE OID groups.
  2181. //--------------------------------------------------------------------------
  2182. static inline BOOL IsDsGroup(
  2183. IN DWORD dwGroupId
  2184. )
  2185. {
  2186. if (0 == dwGroupId ||
  2187. CRYPT_ENHKEY_USAGE_OID_GROUP_ID == dwGroupId ||
  2188. CRYPT_POLICY_OID_GROUP_ID == dwGroupId ||
  2189. CRYPT_TEMPLATE_OID_GROUP_ID == dwGroupId
  2190. )
  2191. return TRUE;
  2192. else
  2193. return FALSE;
  2194. }
  2195. //+-------------------------------------------------------------------------
  2196. // The DS only contains OID and NAME strings
  2197. //--------------------------------------------------------------------------
  2198. static inline BOOL IsDsKeyType(
  2199. IN DWORD dwKeyType
  2200. )
  2201. {
  2202. if (CRYPT_OID_INFO_OID_KEY == dwKeyType ||
  2203. CRYPT_OID_INFO_NAME_KEY == dwKeyType
  2204. )
  2205. return TRUE;
  2206. else
  2207. return FALSE;
  2208. }
  2209. //+-------------------------------------------------------------------------
  2210. // Search the DS group according to the specified dwKeyType.
  2211. //--------------------------------------------------------------------------
  2212. static PCCRYPT_OID_INFO SearchDsGroup(
  2213. IN DWORD dwKeyType,
  2214. IN void *pvKey,
  2215. IN DWORD dwGroupId
  2216. )
  2217. {
  2218. DWORD cInfo;
  2219. PCCRYPT_OID_INFO *ppInfo;
  2220. PCCRYPT_OID_INFO pInfo = NULL;
  2221. if (!IsDsGroup(dwGroupId) || !IsDsKeyType(dwKeyType))
  2222. return NULL;
  2223. LoadDsGroup();
  2224. EnterCriticalSection(&DsCriticalSection);
  2225. cInfo = DsGroup.cInfo;
  2226. ppInfo = DsGroup.rgpInfo;
  2227. for ( ; cInfo > 0; cInfo--, ppInfo++) {
  2228. pInfo = *ppInfo;
  2229. if (CompareOIDInfo(
  2230. dwKeyType,
  2231. pvKey,
  2232. dwGroupId,
  2233. pInfo
  2234. ))
  2235. break;
  2236. }
  2237. if (0 == cInfo)
  2238. pInfo = NULL;
  2239. LeaveCriticalSection(&DsCriticalSection);
  2240. return pInfo;
  2241. }
  2242. //+-------------------------------------------------------------------------
  2243. // Enumerate the DS group.
  2244. //--------------------------------------------------------------------------
  2245. static BOOL EnumDsGroup(
  2246. IN DWORD dwGroupId,
  2247. IN void *pvArg,
  2248. IN PFN_CRYPT_ENUM_OID_INFO pfnEnumOIDInfo
  2249. )
  2250. {
  2251. BOOL fResult;
  2252. DWORD cInfo;
  2253. PCCRYPT_OID_INFO *ppInfo = NULL;
  2254. DWORD i;
  2255. if (!IsDsGroup(dwGroupId))
  2256. return TRUE;
  2257. LoadDsGroup();
  2258. EnterCriticalSection(&DsCriticalSection);
  2259. // Make a copy of DS group OID info pointers while within the
  2260. // DS critical section
  2261. cInfo = DsGroup.cInfo;
  2262. if (0 != cInfo) {
  2263. ppInfo = (PCCRYPT_OID_INFO *) OIDInfoAlloc(
  2264. cInfo * sizeof(PCCRYPT_OID_INFO));
  2265. if (ppInfo)
  2266. memcpy(ppInfo, DsGroup.rgpInfo, cInfo * sizeof(PCCRYPT_OID_INFO));
  2267. else
  2268. cInfo = 0;
  2269. }
  2270. LeaveCriticalSection(&DsCriticalSection);
  2271. for (i = 0; i < cInfo; i++) {
  2272. PCCRYPT_OID_INFO pInfo = ppInfo[i];
  2273. if (dwGroupId && dwGroupId != pInfo->dwGroupId)
  2274. continue;
  2275. if (!pfnEnumOIDInfo(pInfo, pvArg))
  2276. goto EnumOIDInfoError;
  2277. }
  2278. fResult = TRUE;
  2279. CommonReturn:
  2280. OIDInfoFree(ppInfo);
  2281. return fResult;
  2282. ErrorReturn:
  2283. fResult = FALSE;
  2284. goto CommonReturn;
  2285. TRACE_ERROR(EnumOIDInfoError)
  2286. }