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.

483 lines
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: ceformat.cpp
  8. //
  9. // Contents: helper functions
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "pch.cpp"
  13. #pragma hdrstop
  14. #include "celib.h"
  15. #include <assert.h>
  16. #include <wininet.h>
  17. HRESULT
  18. ceDupString(
  19. IN WCHAR const *pwszIn,
  20. IN WCHAR **ppwszOut)
  21. {
  22. DWORD cb;
  23. HRESULT hr;
  24. cb = (wcslen(pwszIn) + 1) * sizeof(WCHAR);
  25. *ppwszOut = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
  26. if (NULL == *ppwszOut)
  27. {
  28. hr = E_OUTOFMEMORY;
  29. _JumpError(hr, error, "LocalAlloc");
  30. }
  31. CopyMemory(*ppwszOut, pwszIn, cb);
  32. hr = S_OK;
  33. error:
  34. return(hr);
  35. }
  36. #define cwcCNMAX 64 // 64 chars max for CN
  37. #define cwcCHOPHASHMAX (1 + 5) // "-%05hu" decimal USHORT hash digits
  38. #define cwcCHOPBASE (cwcCNMAX - (cwcCHOPHASHMAX + cwcSUFFIXMAX))
  39. HRESULT
  40. ceSanitizedNameToDSName(
  41. IN WCHAR const *pwszSanitizedName,
  42. OUT WCHAR **ppwszNameOut)
  43. {
  44. HRESULT hr;
  45. DWORD cwc;
  46. DWORD cwcCopy;
  47. WCHAR wszDSName[cwcCHOPBASE + cwcCHOPHASHMAX + 1];
  48. *ppwszNameOut = NULL;
  49. cwc = wcslen(pwszSanitizedName);
  50. cwcCopy = cwc;
  51. if (cwcCHOPBASE < cwcCopy)
  52. {
  53. cwcCopy = cwcCHOPBASE;
  54. }
  55. CopyMemory(wszDSName, pwszSanitizedName, cwcCopy * sizeof(WCHAR));
  56. wszDSName[cwcCopy] = L'\0';
  57. if (cwcCHOPBASE < cwc)
  58. {
  59. // Hash the rest of the name into a USHORT
  60. USHORT usHash = 0;
  61. DWORD i;
  62. WCHAR *pwsz;
  63. // Truncate an incomplete sanitized Unicode character
  64. pwsz = wcsrchr(wszDSName, L'!');
  65. if (NULL != pwsz && wcslen(pwsz) < 5)
  66. {
  67. cwcCopy -= wcslen(pwsz);
  68. *pwsz = L'\0';
  69. }
  70. for (i = cwcCopy; i < cwc; i++)
  71. {
  72. USHORT usLowBit = (0x8000 & usHash)? 1 : 0;
  73. usHash = ((usHash << 1) | usLowBit) + pwszSanitizedName[i];
  74. }
  75. wsprintf(&wszDSName[cwcCopy], L"-%05hu", usHash);
  76. assert(wcslen(wszDSName) < ARRAYSIZE(wszDSName));
  77. }
  78. hr = ceDupString(wszDSName, ppwszNameOut);
  79. _JumpIfError(hr, error, "ceDupString");
  80. error:
  81. return(hr);
  82. }
  83. HRESULT
  84. ceInternetCanonicalizeUrl(
  85. IN WCHAR const *pwszIn,
  86. OUT WCHAR **ppwszOut)
  87. {
  88. HRESULT hr;
  89. WCHAR *pwsz = NULL;
  90. assert(NULL != pwszIn);
  91. if (0 == _wcsnicmp(L"file:", pwszIn, 5))
  92. {
  93. hr = ceDupString(pwszIn, &pwsz);
  94. _JumpIfError(hr, error, "ceDupString");
  95. }
  96. else
  97. {
  98. // Calculate required buffer size by passing a very small buffer
  99. // The call will fail, and tell us how big the buffer should be.
  100. WCHAR wszPlaceHolder[1];
  101. DWORD cwc = ARRAYSIZE(wszPlaceHolder);
  102. BOOL bResult;
  103. bResult = InternetCanonicalizeUrl(
  104. pwszIn, // lpszUrl
  105. wszPlaceHolder, // lpszBuffer
  106. &cwc, // lpdwBufferLength
  107. 0); // dwFlags
  108. assert(!bResult); // This will always fail
  109. hr = ceHLastError();
  110. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
  111. {
  112. // unexpected error
  113. _JumpError(hr, error, "InternetCanonicalizeUrl");
  114. }
  115. // NOTE: InternetCanonicalizeUrl counts characters, not bytes as doc'd
  116. // cwc includes trailing L'0'
  117. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  118. if (NULL == pwsz)
  119. {
  120. hr = E_OUTOFMEMORY;
  121. _JumpError(hr, error, "LocalAlloc");
  122. }
  123. // canonicalize
  124. if (!InternetCanonicalizeUrl(
  125. pwszIn, // lpszUrl
  126. pwsz, // lpszBuffer
  127. &cwc, // lpdwBufferLength
  128. 0)) // dwFlags
  129. {
  130. hr = ceHLastError();
  131. _JumpError(hr, error, "InternetCanonicalizeUrl");
  132. }
  133. }
  134. *ppwszOut = pwsz;
  135. pwsz = NULL;
  136. hr = S_OK;
  137. error:
  138. if (NULL != pwsz)
  139. {
  140. LocalFree(pwsz);
  141. }
  142. return(hr);
  143. }
  144. // ceFormatCertsrvStringArray FormatMessage arguments:
  145. //
  146. // %1 -- Machine full DNS name: pwszServerName_p1_2;
  147. //
  148. // %2 -- Machine short name: first DNS component of pwszServerName_p1_2
  149. //
  150. // %3 -- Sanitized CA name: pwszSanitizedName_p3_7
  151. //
  152. // %4 -- Cert Filename Suffix:
  153. // if 0 == iCert_p4 && MAXDWORD == iCertTarget_p4: L""
  154. // else if MAXDWORD != iCertTarget_p4 L"(%u-%u)"
  155. // else L"(%u)"
  156. //
  157. // %5 -- DS DN path to Domain root: pwszDomainDN_p5
  158. //
  159. // %6 -- DS DN path to Configuration container: pwszConfigDN_p6
  160. //
  161. // %7 -- Sanitized CA name, truncated and hash suffix added if too long:
  162. // pwszSanitizedName_p3_7
  163. //
  164. // %8 -- CRL Filename/Key Name Suffix: L"" if 0 == iCRL_p8; else L"(%u)"
  165. //
  166. // %9 -- CRL Filename Suffix: L"" if !fDeltaCRL_p9; else L"+"
  167. //
  168. // %10 -- DS CRL attribute: L"" if !fDSAttrib_p10_11; depends on fDeltaCRL_p9
  169. //
  170. // %11 -- DS CA Cert attribute: L"" if !fDSAttrib_p10_11
  171. //
  172. // %12 -- DS user cert attribute
  173. //
  174. // %13 -- DS KRA cert attribute
  175. //
  176. // %14 -- DS cross cert pair attribute
  177. #ifndef wszDSSEARCHBASECRLATTRIBUTE
  178. #define wszDSSEARCHBASECRLATTRIBUTE L"?certificateRevocationList?base?objectclass=cRLDistributionPoint"
  179. #endif
  180. #ifndef wszDSSEARCHDELTACRLATTRIBUTE
  181. #define wszDSSEARCHDELTACRLATTRIBUTE L"?deltaRevocationList?base?objectclass=cRLDistributionPoint"
  182. #endif
  183. #ifndef wszDSSEARCHCACERTATTRIBUTE
  184. #define wszDSSEARCHCACERTATTRIBUTE L"?cACertificate?base?objectclass=certificationAuthority"
  185. #endif
  186. #ifndef wszDSSEARCHUSERCERTATTRIBUTE
  187. #define wszDSSEARCHUSERCERTATTRIBUTE L"?userCertificate?base?objectClass=*"
  188. #endif
  189. #ifndef wszDSSEARCHKRACERTATTRIBUTE
  190. #define wszDSSEARCHKRACERTATTRIBUTE L"?userCertificate?one?objectClass=msPKI-PrivateKeyRecoveryAgent"
  191. #endif
  192. #ifndef wszDSSEARCHCROSSCERTPAIRATTRIBUTE
  193. #define wszDSSEARCHCROSSCERTPAIRATTRIBUTE L"?crossCertificatePair?one?objectClass=certificationAuthority"
  194. #endif
  195. HRESULT
  196. ceFormatCertsrvStringArray(
  197. IN BOOL fURL,
  198. IN LPCWSTR pwszServerName_p1_2,
  199. IN LPCWSTR pwszSanitizedName_p3_7,
  200. IN DWORD iCert_p4,
  201. IN DWORD iCertTarget_p4,
  202. IN LPCWSTR pwszDomainDN_p5,
  203. IN LPCWSTR pwszConfigDN_p6,
  204. IN DWORD iCRL_p8,
  205. IN BOOL fDeltaCRL_p9,
  206. IN BOOL fDSAttrib_p10_11,
  207. IN DWORD cStrings,
  208. IN LPCWSTR *apwszStringsIn,
  209. OUT LPWSTR *apwszStringsOut)
  210. {
  211. HRESULT hr = S_OK;
  212. LPCWSTR apwszInsertionArray[100]; // 100 'cause this is the max number of insertion numbers allowed by FormatMessage
  213. LPWSTR pwszCurrent = NULL;
  214. BSTR strShortMachineName = NULL;
  215. DWORD i;
  216. WCHAR *pwszSanitizedDSName = NULL;
  217. WCHAR wszCertSuffix[2 * cwcFILENAMESUFFIXMAX];
  218. WCHAR wszCRLSuffix[cwcFILENAMESUFFIXMAX];
  219. WCHAR wszDeltaCRLSuffix[cwcFILENAMESUFFIXMAX];
  220. WCHAR const *pwszT;
  221. ZeroMemory(apwszStringsOut, cStrings * sizeof(apwszStringsOut[0]));
  222. ZeroMemory(apwszInsertionArray, sizeof(apwszInsertionArray));
  223. // Format the template into a real name
  224. // Initialize the insertion string array.
  225. //+================================================
  226. // Machine DNS name (%1)
  227. assert(L'1' == wszFCSAPARM_SERVERDNSNAME[1]);
  228. apwszInsertionArray[1 - 1] = pwszServerName_p1_2;
  229. //+================================================
  230. // Short Machine Name (%2)
  231. assert(L'2' == wszFCSAPARM_SERVERSHORTNAME[1]);
  232. strShortMachineName = SysAllocString(pwszServerName_p1_2);
  233. if (strShortMachineName == NULL)
  234. {
  235. hr = E_OUTOFMEMORY;
  236. _JumpIfError(hr, error, "SysAllocString");
  237. }
  238. pwszCurrent = wcschr(strShortMachineName, L'.');
  239. if (NULL != pwszCurrent)
  240. {
  241. *pwszCurrent = 0;
  242. }
  243. apwszInsertionArray[2 - 1] = strShortMachineName;
  244. //+================================================
  245. // sanitized name (%3)
  246. assert(L'3' == wszFCSAPARM_SANITIZEDCANAME[1]);
  247. apwszInsertionArray[3 - 1] = pwszSanitizedName_p3_7;
  248. //+================================================
  249. // Cert filename suffix (%4) | (%4-%4)
  250. assert(L'4' == wszFCSAPARM_CERTFILENAMESUFFIX[1]);
  251. wszCertSuffix[0] = L'\0';
  252. if (0 != iCert_p4 || MAXDWORD != iCertTarget_p4)
  253. {
  254. wsprintf(
  255. wszCertSuffix,
  256. MAXDWORD != iCertTarget_p4? L"(%u-%u)" : L"(%u)",
  257. iCert_p4,
  258. iCertTarget_p4);
  259. }
  260. apwszInsertionArray[4 - 1] = wszCertSuffix;
  261. //+================================================
  262. // Domain DN (%5)
  263. if (NULL == pwszDomainDN_p5 || L'\0' == *pwszDomainDN_p5)
  264. {
  265. pwszDomainDN_p5 = L"DC=UnavailableDomainDN";
  266. }
  267. assert(L'5' == wszFCSAPARM_DOMAINDN[1]);
  268. apwszInsertionArray[5 - 1] = pwszDomainDN_p5;
  269. //+================================================
  270. // Config DN (%6)
  271. if (NULL == pwszConfigDN_p6 || L'\0' == *pwszConfigDN_p6)
  272. {
  273. pwszConfigDN_p6 = L"DC=UnavailableConfigDN";
  274. }
  275. assert(L'6' == wszFCSAPARM_CONFIGDN[1]);
  276. apwszInsertionArray[6 - 1] = pwszConfigDN_p6;
  277. // Don't pass pwszSanitizedName_p3_7 to SysAllocStringLen with the extended
  278. // length to avoid faulting past end of pwszSanitizedName_p3_7.
  279. //+================================================
  280. // Sanitized Short Name (%7)
  281. assert(L'7' == wszFCSAPARM_SANITIZEDCANAMEHASH[1]);
  282. hr = ceSanitizedNameToDSName(pwszSanitizedName_p3_7, &pwszSanitizedDSName);
  283. _JumpIfError(hr, error, "ceSanitizedNameToDSName");
  284. apwszInsertionArray[7 - 1] = pwszSanitizedDSName;
  285. //+================================================
  286. // CRL filename suffix (%8)
  287. assert(L'8' == wszFCSAPARM_CRLFILENAMESUFFIX[1]);
  288. wszCRLSuffix[0] = L'\0';
  289. if (0 != iCRL_p8)
  290. {
  291. wsprintf(wszCRLSuffix, L"(%u)", iCRL_p8);
  292. }
  293. apwszInsertionArray[8 - 1] = wszCRLSuffix;
  294. //+================================================
  295. // Delta CRL filename suffix (%9)
  296. assert(L'9' == wszFCSAPARM_CRLDELTAFILENAMESUFFIX[1]);
  297. wszDeltaCRLSuffix[0] = L'\0';
  298. if (fDeltaCRL_p9)
  299. {
  300. wcscpy(wszDeltaCRLSuffix, L"+");
  301. }
  302. apwszInsertionArray[9 - 1] = wszDeltaCRLSuffix;
  303. //+================================================
  304. // CRL attribute (%10)
  305. assert(L'1' == wszFCSAPARM_DSCRLATTRIBUTE[1]);
  306. assert(L'0' == wszFCSAPARM_DSCRLATTRIBUTE[2]);
  307. pwszT = L"";
  308. if (fDSAttrib_p10_11)
  309. {
  310. pwszT = fDeltaCRL_p9?
  311. wszDSSEARCHDELTACRLATTRIBUTE :
  312. wszDSSEARCHBASECRLATTRIBUTE;
  313. }
  314. apwszInsertionArray[10 - 1] = pwszT;
  315. //+================================================
  316. // CA cert attribute (%11)
  317. assert(L'1' == wszFCSAPARM_DSCACERTATTRIBUTE[1]);
  318. assert(L'1' == wszFCSAPARM_DSCACERTATTRIBUTE[2]);
  319. pwszT = L"";
  320. if (fDSAttrib_p10_11)
  321. {
  322. pwszT = wszDSSEARCHCACERTATTRIBUTE;
  323. }
  324. apwszInsertionArray[11 - 1] = pwszT;
  325. //+================================================
  326. // User cert attribute (%12)
  327. assert(L'1' == wszFCSAPARM_DSUSERCERTATTRIBUTE[1]);
  328. assert(L'2' == wszFCSAPARM_DSUSERCERTATTRIBUTE[2]);
  329. pwszT = L"";
  330. if (fDSAttrib_p10_11)
  331. {
  332. pwszT = wszDSSEARCHUSERCERTATTRIBUTE;
  333. }
  334. apwszInsertionArray[12 - 1] = pwszT;
  335. //+================================================
  336. // KRA cert attribute (%13)
  337. assert(L'1' == wszFCSAPARM_DSKRACERTATTRIBUTE[1]);
  338. assert(L'3' == wszFCSAPARM_DSKRACERTATTRIBUTE[2]);
  339. pwszT = L"";
  340. if (fDSAttrib_p10_11)
  341. {
  342. pwszT = wszDSSEARCHKRACERTATTRIBUTE;
  343. }
  344. apwszInsertionArray[13 - 1] = pwszT;
  345. //+================================================
  346. // Cross cert pair attribute (%14)
  347. assert(L'1' == wszFCSAPARM_DSCROSSCERTPAIRATTRIBUTE[1]);
  348. assert(L'4' == wszFCSAPARM_DSCROSSCERTPAIRATTRIBUTE[2]);
  349. pwszT = L"";
  350. if (fDSAttrib_p10_11)
  351. {
  352. pwszT = wszDSSEARCHCROSSCERTPAIRATTRIBUTE;
  353. }
  354. apwszInsertionArray[14 - 1] = pwszT;
  355. //+================================================
  356. // Now format the strings...
  357. for (i = 0; i < cStrings; i++)
  358. {
  359. if (0 == FormatMessage(
  360. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  361. FORMAT_MESSAGE_FROM_STRING |
  362. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  363. (VOID *) apwszStringsIn[i],
  364. 0, // dwMessageID
  365. 0, // dwLanguageID
  366. (LPWSTR) &apwszStringsOut[i],
  367. wcslen(apwszStringsIn[i]),
  368. (va_list *) apwszInsertionArray))
  369. {
  370. hr = ceHLastError();
  371. _JumpError(hr, error, "FormatMessage");
  372. }
  373. if (fURL)
  374. {
  375. WCHAR *pwsz;
  376. hr = ceInternetCanonicalizeUrl(apwszStringsOut[i], &pwsz);
  377. _JumpIfError(hr, error, "ceInternetCanonicalizeUrl");
  378. LocalFree(apwszStringsOut[i]);
  379. apwszStringsOut[i] = pwsz;
  380. }
  381. }
  382. error:
  383. if (S_OK != hr)
  384. {
  385. for (i = 0; i < cStrings; i++)
  386. {
  387. if (NULL != apwszStringsOut[i])
  388. {
  389. LocalFree(apwszStringsOut[i]);
  390. apwszStringsOut[i] = NULL;
  391. }
  392. }
  393. }
  394. if (NULL != strShortMachineName)
  395. {
  396. SysFreeString(strShortMachineName);
  397. }
  398. if (NULL != pwszSanitizedDSName)
  399. {
  400. LocalFree(pwszSanitizedDSName);
  401. }
  402. return (hr);
  403. }