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.

387 lines
8.4 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: setup.cpp
  7. //
  8. // Contents:
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <assert.h>
  14. #include <accctrl.h>
  15. #include <ntldap.h>
  16. #include "certca.h"
  17. #include "cainfop.h"
  18. #include "csldap.h"
  19. #include "dssetup.h"
  20. #define __dwFILE__ __dwFILE_OCMSETUP_DSSETUP_CPP__
  21. typedef HRESULT (* LPFNDLL_INSTALL)(BOOL bInstall, LPCWSTR pszCmdLine);
  22. BOOL
  23. IsCAExistInDS(
  24. IN WCHAR const *pwszSanitizedName)
  25. {
  26. BOOL exist = FALSE;
  27. HRESULT hr;
  28. HCAINFO hCAInfo = NULL;
  29. WCHAR *pwszDSName = NULL;
  30. hr = mySanitizedNameToDSName(pwszSanitizedName, &pwszDSName);
  31. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  32. hr = CAFindByName(
  33. pwszDSName,
  34. NULL,
  35. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  36. &hCAInfo);
  37. _JumpIfErrorStr(hr, error, "IsCAExistInDS:CAFindByName", pwszDSName);
  38. if (NULL == hCAInfo)
  39. {
  40. hr = E_INVALIDARG;
  41. _JumpError(hr, error, "invalid CA in DS");
  42. }
  43. exist = TRUE;
  44. error:
  45. if (NULL != pwszDSName)
  46. {
  47. LocalFree(pwszDSName);
  48. }
  49. if (NULL != hCAInfo)
  50. {
  51. CACloseCA(hCAInfo);
  52. }
  53. return exist;
  54. }
  55. BOOL
  56. IsDSAvailable(
  57. OPTIONAL OUT bool *pfIsOldDSVersion)
  58. {
  59. HRESULT hr;
  60. BOOL available = FALSE;
  61. LDAP *pld = NULL;
  62. HMODULE hMod = NULL;
  63. if (NULL != pfIsOldDSVersion)
  64. {
  65. *pfIsOldDSVersion = false;
  66. }
  67. // fail out quickly if DS not present on domain
  68. hr = myDoesDSExist(FALSE);
  69. _JumpIfError(hr, error, "myDoesDSExist");
  70. hMod = LoadLibrary(L"wldap32.dll");
  71. if (NULL == hMod)
  72. {
  73. hr = myHLastError();
  74. _JumpErrorStr(hr, error, "LoadLibrary", L"wldap32.dll");
  75. }
  76. available = TRUE;
  77. // If the caller is checking for an old DS, turn on RLBF_REQUIRE_LDAP_INTEG
  78. // to test for the presence of a required DS bug fix:
  79. hr = myRobustLdapBindEx(
  80. 0, // dwFlags1
  81. (NULL != pfIsOldDSVersion?
  82. RLBF_REQUIRE_LDAP_INTEG : 0) |
  83. RLBF_REQUIRE_SECURE_LDAP, // dwFlags2
  84. LDAP_VERSION2, // uVersion
  85. NULL, // pwszDomainName
  86. &pld,
  87. NULL); // ppwszForestDNSName
  88. if (NULL != pfIsOldDSVersion &&
  89. CERTSRV_E_DOWNLEVEL_DC_SSL_OR_UPGRADE == hr)
  90. {
  91. *pfIsOldDSVersion = true;
  92. }
  93. _JumpIfError(hr, error, "myRobustLdapBindEx");
  94. error:
  95. if (NULL != pld)
  96. {
  97. ldap_unbind(pld);
  98. }
  99. if (NULL != hMod)
  100. {
  101. FreeLibrary(hMod);
  102. }
  103. return available;
  104. }
  105. HRESULT
  106. RemoveCAInDS(
  107. IN WCHAR const *pwszSanitizedName)
  108. {
  109. HRESULT hr;
  110. HCAINFO hCAInfo = NULL;
  111. WCHAR *pwszDSName = NULL;
  112. hr = mySanitizedNameToDSName(pwszSanitizedName, &pwszDSName);
  113. _JumpIfError(hr, error, "mySanitizedNameToDSName");
  114. hr = CAFindByName(
  115. pwszDSName,
  116. NULL,
  117. CA_FIND_INCLUDE_UNTRUSTED | CA_FIND_INCLUDE_NON_TEMPLATE_CA,
  118. &hCAInfo);
  119. _JumpIfErrorStr(hr, error, "RemoveCAInDS:CAFindByName", pwszDSName);
  120. if (NULL == hCAInfo)
  121. {
  122. hr = E_INVALIDARG;
  123. _JumpError(hr, error, "invalid CA in DS");
  124. }
  125. hr = CADeleteCA(hCAInfo);
  126. _JumpIfError(hr, error, "CADeleteCA");
  127. hr = RemoveCAMachineFromCertPublishers();
  128. _JumpIfError(hr, error, "RemoveCAMachineFromCertPublishers");
  129. if(FIsAdvancedServer())
  130. {
  131. hr = RemoveCAMachineFromPreWin2kGroup();
  132. _JumpIfError(hr, error, "RemoveCAMachineFromPreWin2kGroup");
  133. }
  134. error:
  135. if (NULL != pwszDSName)
  136. {
  137. LocalFree(pwszDSName);
  138. }
  139. if (NULL != hCAInfo)
  140. {
  141. CACloseCA(hCAInfo);
  142. }
  143. return hr;
  144. }
  145. HRESULT
  146. CreateCertDSHierarchy(VOID)
  147. {
  148. HRESULT hr = S_OK;
  149. ULONG ldaperr;
  150. LDAP *pld = NULL;
  151. LDAPMod objectClass;
  152. WCHAR *objectClassVals[3];
  153. LDAPMod *mods[2];
  154. BSTR bstrConfigDN = NULL;
  155. WCHAR * awszLocations[] = {
  156. L"CN=Public Key Services,CN=Services,",
  157. L"CN=Enrollment Services,CN=Public Key Services,CN=Services,",
  158. NULL,
  159. };
  160. WCHAR ** pwszCurLocation;
  161. DWORD cbBuffer;
  162. BSTR bstrBuffer = NULL;
  163. // bind to ds
  164. hr = myLdapOpen(
  165. NULL, // pwszDomainName
  166. RLBF_REQUIRE_SECURE_LDAP, // dwFlags
  167. &pld,
  168. NULL, // pstrDomainDN
  169. &bstrConfigDN);
  170. _JumpIfError(hr, error, "myLdapOpen");
  171. pwszCurLocation = awszLocations;
  172. // Build the Public Key Services container
  173. mods[0] = &objectClass;
  174. mods[1] = NULL;
  175. objectClass.mod_op = 0;
  176. objectClass.mod_type = TEXT("objectclass");
  177. objectClass.mod_values = objectClassVals;
  178. objectClassVals[0] = TEXT("top");
  179. objectClassVals[1] = TEXT("container");
  180. objectClassVals[2] = NULL;
  181. while(*pwszCurLocation)
  182. {
  183. cbBuffer = wcslen(*pwszCurLocation) + wcslen(bstrConfigDN) + 1;
  184. // Build a string containing the CA Location
  185. bstrBuffer = SysAllocStringLen(NULL, cbBuffer);
  186. if(bstrBuffer == NULL)
  187. {
  188. hr = E_OUTOFMEMORY;
  189. goto error;
  190. }
  191. wcscpy(bstrBuffer, *pwszCurLocation);
  192. wcscat(bstrBuffer, bstrConfigDN);
  193. ldaperr = ldap_add_s(pld, bstrBuffer, mods);
  194. SysFreeString(bstrBuffer);
  195. if(ldaperr != LDAP_SUCCESS && ldaperr != LDAP_ALREADY_EXISTS)
  196. {
  197. hr = myHLdapError(pld, ldaperr, NULL);
  198. goto error;
  199. }
  200. pwszCurLocation++;
  201. }
  202. error:
  203. myLdapClose(pld, NULL, bstrConfigDN);
  204. return(hr);
  205. }
  206. //
  207. HRESULT InitializeCertificateTemplates(VOID)
  208. {
  209. HRESULT hr = S_OK;
  210. DWORD err = ERROR_SUCCESS;
  211. HINSTANCE hCertCli = NULL;
  212. LPFNDLL_INSTALL lpfnDllInstall = NULL;
  213. hCertCli = LoadLibrary(L"certcli.dll");
  214. if(hCertCli == NULL)
  215. {
  216. hr = myHLastError();
  217. goto error;
  218. }
  219. lpfnDllInstall = (LPFNDLL_INSTALL)GetProcAddress(hCertCli, "DllInstall");
  220. if(lpfnDllInstall == NULL)
  221. {
  222. hr = myHLastError();
  223. goto error;
  224. }
  225. err = lpfnDllInstall(TRUE, L"i");
  226. hr = HRESULT_FROM_WIN32(err);
  227. error:
  228. return hr;
  229. }
  230. HRESULT
  231. DNStoDirectoryName(IN LPWSTR wszDNSDomain,
  232. OUT LPWSTR *pwszDN)
  233. {
  234. HRESULT hr = S_OK;
  235. DWORD cDN;
  236. LPWSTR wszResult = NULL;
  237. LPWSTR wszCurrent, wszNext;
  238. if (wszDNSDomain == NULL)
  239. {
  240. hr = E_POINTER;
  241. _JumpError(hr, error, "DNStoDirectoryName");
  242. }
  243. if(0==wcsncmp(wszDNSDomain, L"\\\\", 2))
  244. {
  245. // this is a DC DNS name, skip the machine name
  246. wszDNSDomain = wcschr(wszDNSDomain, L'.');
  247. // no dot found?
  248. if(!wszDNSDomain)
  249. {
  250. hr =E_UNEXPECTED;
  251. _JumpError(hr, error, "DC DNS doesn't contain at least one dot");
  252. }
  253. // jump over the dot
  254. wszDNSDomain++;
  255. // no domain name following the DC name?
  256. if(L'\0'==*wszDNSDomain)
  257. {
  258. hr = E_UNEXPECTED;
  259. _JumpError(hr, error, "DC DNS name doesn't contain a domain name");
  260. }
  261. }
  262. // Estimate the size of the output string
  263. cDN = wcslen(wszDNSDomain) + 3;
  264. wszCurrent=wszDNSDomain;
  265. for (;;)
  266. {
  267. wszCurrent = wcschr(wszCurrent, L'.');
  268. if (NULL == wszCurrent)
  269. {
  270. break;
  271. }
  272. cDN += 4; // sizeof ,DC=
  273. wszCurrent++;
  274. }
  275. cDN += 1; // NULL terminate
  276. wszResult = (LPWSTR)LocalAlloc(LMEM_FIXED, cDN * sizeof(WCHAR));
  277. if(wszResult == NULL)
  278. {
  279. hr = E_OUTOFMEMORY;
  280. _JumpError(hr, error, "LocalAlloc");
  281. }
  282. wszCurrent=wszDNSDomain;
  283. // prepend the first DC=
  284. wszNext = wszResult + 3;
  285. wcscpy(wszResult, L"DC=");
  286. while(*wszCurrent)
  287. {
  288. if(*wszCurrent != '.')
  289. {
  290. *wszNext++ = *wszCurrent++;
  291. }
  292. else
  293. {
  294. wszCurrent++;
  295. if(*wszCurrent)
  296. {
  297. wcscpy(wszNext, L",DC=");
  298. wszNext += 4;
  299. }
  300. }
  301. }
  302. *wszNext = 0;
  303. if(pwszDN)
  304. {
  305. *pwszDN = wszResult;
  306. wszResult = NULL;
  307. }
  308. error:
  309. if(wszResult)
  310. {
  311. LocalFree(wszResult);
  312. }
  313. return hr;
  314. }