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.

2698 lines
82 KiB

  1. //--------------------------------------------------------------------
  2. // SetupUtil - implementation
  3. // Copyright (C) Microsoft Corporation, 1999
  4. //
  5. // Created by: Louis Thomas (louisth), 8-10-99
  6. //
  7. // Functions needed to set up CEP
  8. //
  9. //--------------------------------------------------------------------
  10. // includes
  11. #include "global.hxx"
  12. #include <xenroll.h>
  13. #include <dbgdef.h>
  14. #include "ErrorHandling.h"
  15. #include "SetupUtil.h"
  16. //--------------------------------------------------------------------
  17. // Constants
  18. static const WCHAR gc_wszRegKeyServices[]=L"System\\CurrentControlSet\\Services";
  19. static const WCHAR gc_wszCertSrvDir[]=L"CertSrv";
  20. // from <wincrypt.h>
  21. static const WCHAR gc_wszEnrollmentAgentOid[]=L"1.3.6.1.4.1.311.20.2.1"; //szOID_ENROLLMENT_AGENT
  22. // from ca\include\certlib.h; ca\certlib\acl.cpp
  23. const GUID GUID_ENROLL={0x0e10c968, 0x78fb, 0x11d2, {0x90, 0xd4, 0x00, 0xc0, 0x4f, 0x79, 0xdc, 0x55}};
  24. //--------------------------------------------------------------------
  25. // IIS magic
  26. #undef DEFINE_GUID
  27. #define INITGUID
  28. #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
  29. EXTERN_C const GUID name \
  30. = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
  31. #include <iwamreg.h>
  32. #include <iadmw.h>
  33. #include <iiscnfg.h>
  34. //--------------------------------------------------------------------
  35. // constants
  36. #include "..\common.h"
  37. #define MAX_METABASE_ATTEMPTS 10 // Times to bang head on wall
  38. #define METABASE_PAUSE 500 // Time to pause in msec
  39. static const WCHAR gc_wszBaseRoot[]=L"/LM/W3svc/1/ROOT";
  40. static const WCHAR gc_wszCepDllName[]=CEP_DLL_NAME;
  41. static const WCHAR gc_wszCepStoreName[]=CEP_STORE_NAME;
  42. static const WCHAR gc_wszAppPoolBase[]=L"/LM/W3svc/APPPOOLS";
  43. //---------------------------------------------------------------------
  44. // function prototypes
  45. HRESULT
  46. EnableISAPIExtension(
  47. IN LPCWSTR pcwszExtension,
  48. OUT BOOL *pfEnabledASP);
  49. HRESULT IsISAPIExtensionEnabled(
  50. LPCWSTR pcwszExtension,
  51. bool& rfEnabled);
  52. //####################################################################
  53. // module local functions
  54. //--------------------------------------------------------------------
  55. static HRESULT myHExceptionCode(EXCEPTION_POINTERS * pep)
  56. {
  57. HRESULT hr=pep->ExceptionRecord->ExceptionCode;
  58. if (!FAILED(hr)) {
  59. hr=HRESULT_FROM_WIN32(hr);
  60. }
  61. return hr;
  62. }
  63. //--------------------------------------------------------------------
  64. static HRESULT
  65. vrOpenRoot(
  66. IN IMSAdminBase *pIMeta,
  67. IN BOOL fReadOnly,
  68. IN const WCHAR * wszBaseRoot,
  69. OUT METADATA_HANDLE *phMetaRoot)
  70. {
  71. HRESULT hr;
  72. unsigned int nAttempts;
  73. // Re-try a few times to see if we can get past the block
  74. nAttempts=0;
  75. do {
  76. // Pause on retry
  77. if (0!=nAttempts) {
  78. Sleep(METABASE_PAUSE);
  79. }
  80. // Make an attempt to open the root
  81. __try {
  82. hr=pIMeta->OpenKey(
  83. METADATA_MASTER_ROOT_HANDLE,
  84. wszBaseRoot,
  85. fReadOnly?
  86. METADATA_PERMISSION_READ :
  87. (METADATA_PERMISSION_READ |
  88. METADATA_PERMISSION_WRITE),
  89. 1000,
  90. phMetaRoot);
  91. } _TrapException(hr);
  92. nAttempts++;
  93. } while (HRESULT_FROM_WIN32(ERROR_PATH_BUSY)==hr && nAttempts<MAX_METABASE_ATTEMPTS);
  94. _JumpIfError(hr, error, "OpenKey");
  95. error:
  96. return hr;
  97. }
  98. //--------------------------------------------------------------------
  99. static HRESULT GetRegString(IN HKEY hKey, IN const WCHAR * wszValue, OUT WCHAR ** pwszString)
  100. {
  101. HRESULT hr;
  102. DWORD dwDataSize;
  103. DWORD dwType;
  104. DWORD dwError;
  105. // must be cleaned up
  106. WCHAR * wszString=NULL;
  107. // init out params
  108. *pwszString=NULL;
  109. // get value
  110. dwDataSize=0;
  111. dwError=RegQueryValueExW(hKey, wszValue, NULL, &dwType, NULL, &dwDataSize);
  112. if (ERROR_SUCCESS!=dwError) {
  113. hr=HRESULT_FROM_WIN32(dwError);
  114. _JumpErrorStr(hr, error, "RegQueryValueExW", wszValue);
  115. }
  116. _Verify(REG_SZ==dwType, hr, error);
  117. wszString=(WCHAR *)LocalAlloc(LPTR, dwDataSize);
  118. _JumpIfOutOfMemory(hr, error, pwszString);
  119. dwError=RegQueryValueExW(hKey, wszValue, NULL, &dwType, (BYTE *)wszString, &dwDataSize);
  120. if (ERROR_SUCCESS!=dwError) {
  121. hr=HRESULT_FROM_WIN32(dwError);
  122. _JumpErrorStr(hr, error, "RegQueryValueExW", wszValue);
  123. }
  124. _Verify(REG_SZ==dwType, hr, error);
  125. // it worked
  126. hr=S_OK;
  127. *pwszString=wszString;
  128. wszString=NULL;
  129. error:
  130. if (NULL!=wszString) {
  131. LocalFree(wszString);
  132. }
  133. return hr;
  134. }
  135. //--------------------------------------------------------------------
  136. static HRESULT OpenCertSrvConfig(HKEY * phkey)
  137. {
  138. HRESULT hr;
  139. DWORD dwError;
  140. DWORD dwType;
  141. DWORD dwDataSize;
  142. // must be cleaned up
  143. HKEY hServices=NULL;
  144. HKEY hCertSvc=NULL;
  145. HKEY hConfig=NULL;
  146. // initialize out params
  147. *phkey=NULL;
  148. // Open HKLM\System\CurrentControlSet\Services
  149. dwError=RegOpenKeyExW(HKEY_LOCAL_MACHINE, gc_wszRegKeyServices, 0, KEY_READ, &hServices);
  150. if (ERROR_SUCCESS!=dwError) {
  151. hr=HRESULT_FROM_WIN32(dwError);
  152. _JumpErrorStr(hr, error, "RegOpenKeyEx", gc_wszRegKeyServices);
  153. }
  154. // open CertSvc\Configuration
  155. dwError=RegOpenKeyExW(hServices, wszSERVICE_NAME, 0, KEY_READ, &hCertSvc);
  156. if (ERROR_SUCCESS!=dwError) {
  157. hr=HRESULT_FROM_WIN32(dwError);
  158. _JumpErrorStr(hr, error, "RegOpenKeyEx", wszSERVICE_NAME);
  159. }
  160. dwError=RegOpenKeyExW(hCertSvc, wszREGKEYCONFIG, 0, KEY_READ, &hConfig);
  161. if (ERROR_SUCCESS!=dwError) {
  162. hr=HRESULT_FROM_WIN32(dwError);
  163. _JumpErrorStr(hr, error, "RegOpenKeyEx", wszREGKEYCONFIG);
  164. }
  165. // we were successfull
  166. hr=S_OK;
  167. *phkey=hConfig;
  168. hConfig=0;
  169. error:
  170. if (NULL!=hConfig) {
  171. RegCloseKey(hConfig);
  172. }
  173. if (NULL!=hCertSvc) {
  174. RegCloseKey(hCertSvc);
  175. }
  176. if (NULL!=hServices) {
  177. RegCloseKey(hServices);
  178. }
  179. return hr;
  180. }
  181. //--------------------------------------------------------------------
  182. static HRESULT OpenCurrentCAConfig(HKEY * phkey)
  183. {
  184. HRESULT hr;
  185. DWORD dwError;
  186. DWORD dwType;
  187. DWORD dwDataSize;
  188. // must be cleaned up
  189. HKEY hConfig=NULL;
  190. HKEY hCurConfig=NULL;
  191. WCHAR * wszActiveConfig=NULL;
  192. // initialize out params
  193. *phkey=NULL;
  194. // Open HKLM\System\CurrentControlSet\Services\CertSvc\Configuration
  195. hr=OpenCertSrvConfig(&hConfig);
  196. _JumpIfError(hr, error, "OpenCertSrvConfig");
  197. // get value "active"
  198. hr=GetRegString(hConfig, wszREGACTIVE, &wszActiveConfig);
  199. _JumpIfErrorStr(hr, error, "GetRegString", wszREGACTIVE);
  200. // and open <active>
  201. dwError=RegOpenKeyExW(hConfig, wszActiveConfig, 0, KEY_ALL_ACCESS, &hCurConfig);
  202. if (ERROR_SUCCESS!=dwError) {
  203. hr=HRESULT_FROM_WIN32(dwError);
  204. _JumpErrorStr(hr, error, "RegOpenKeyEx", wszActiveConfig);
  205. }
  206. // we were successfull
  207. hr=S_OK;
  208. *phkey=hCurConfig;
  209. hCurConfig=0;
  210. error:
  211. if (NULL!=hCurConfig) {
  212. RegCloseKey(hCurConfig);
  213. }
  214. if (NULL!=wszActiveConfig) {
  215. LocalFree(wszActiveConfig);
  216. }
  217. if (NULL!=hConfig) {
  218. RegCloseKey(hConfig);
  219. }
  220. return hr;
  221. }
  222. //--------------------------------------------------------------------
  223. // stolen from certlib.cpp. use this until Pete fixes the api.
  224. static HRESULT GetCADsName(OUT WCHAR **pwszName)
  225. {
  226. #define cwcCNMAX 64 // 64 chars max for CN
  227. #define cwcCHOPHASHMAX (1+5) // "-%05hu" decimal USHORT hash digits
  228. #define cwcSUFFIXMAX (1 + 5 + 1) // five decimal digits plus parentheses
  229. #define cwcCHOPBASE (cwcCNMAX-(cwcCHOPHASHMAX+cwcSUFFIXMAX))
  230. HRESULT hr;
  231. DWORD cwc;
  232. DWORD cwcCopy;
  233. WCHAR wszDSName[cwcCHOPBASE+cwcCHOPHASHMAX+1];
  234. // must be cleaned up
  235. HKEY hConfig=NULL;
  236. WCHAR * wszSanitizedName=NULL;
  237. // initialize out params
  238. *pwszName=NULL;
  239. // Open HKLM\System\CurrentControlSet\Services\CertSvc\Configuration
  240. hr=OpenCertSrvConfig(&hConfig);
  241. _JumpIfError(hr, error, "OpenCertSrvConfig");
  242. // get value "active" - this is the sanitized name
  243. hr=GetRegString(hConfig, wszREGACTIVE, &wszSanitizedName);
  244. _JumpIfErrorStr(hr, error, "GetRegString", wszREGACTIVE);
  245. // ----- begin stolen code -----
  246. cwc = wcslen(wszSanitizedName);
  247. cwcCopy = cwc;
  248. if (cwcCHOPBASE < cwcCopy)
  249. {
  250. cwcCopy = cwcCHOPBASE;
  251. }
  252. CopyMemory(wszDSName, wszSanitizedName, cwcCopy * sizeof(WCHAR));
  253. wszDSName[cwcCopy] = L'\0';
  254. if (cwcCHOPBASE < cwc)
  255. {
  256. // Hash the rest of the name into a USHORT
  257. USHORT usHash = 0;
  258. DWORD i;
  259. WCHAR *pwsz;
  260. // Truncate an incomplete sanitized Unicode character
  261. pwsz = wcsrchr(wszDSName, L'!');
  262. if (NULL != pwsz && wcslen(pwsz) < 5)
  263. {
  264. cwcCopy -= wcslen(pwsz);
  265. *pwsz = L'\0';
  266. }
  267. for (i = cwcCopy; i < cwc; i++)
  268. {
  269. USHORT usLowBit = (0x8000 & usHash)? 1 : 0;
  270. usHash = ((usHash << 1) | usLowBit) + wszSanitizedName[i];
  271. }
  272. wsprintf(&wszDSName[cwcCopy], L"-%05hu", usHash);
  273. //CSASSERT(wcslen(wszDSName) < ARRAYSIZE(wszDSName));
  274. }
  275. // ----- end stolen code -----
  276. *pwszName=(WCHAR *)LocalAlloc(LPTR, (wcslen(wszDSName)+1)*sizeof(WCHAR));
  277. _JumpIfOutOfMemory(hr, error, *pwszName);
  278. wcscpy(*pwszName, wszDSName);
  279. hr=S_OK;
  280. error:
  281. if (NULL!=wszSanitizedName) {
  282. LocalFree(wszSanitizedName);
  283. }
  284. if (NULL!=hConfig) {
  285. RegCloseKey(hConfig);
  286. }
  287. return hr;
  288. }
  289. //--------------------------------------------------------------------
  290. HRESULT SetSDOnCEPCertificate(BSTR bstrCertificate, SID * psidAccount)
  291. {
  292. HRESULT hr=E_FAIL;
  293. DWORD dwKeySpec=0;
  294. BOOL fFreeProv=FALSE;
  295. CERT_BLOB blobCert;
  296. DWORD dwSD=0;
  297. PACL pAcl=NULL;
  298. BOOL fDacl = TRUE;
  299. BOOL fDef = FALSE;
  300. ACL_SIZE_INFORMATION AclInfo;
  301. DWORD dwAccess=ACTRL_FILE_READ | ACTRL_FILE_READ_PROP | ACTRL_FILE_READ_ATTRIB;
  302. ACE_HEADER *pFirstAce=NULL;
  303. PSECURITY_DESCRIPTOR pNewSD = NULL;
  304. PACL pNewAcl = NULL;
  305. PSECURITY_DESCRIPTOR pSID=NULL;
  306. HCERTSTORE hCEPStore=NULL;
  307. PCERT_CONTEXT pCertContext=NULL;
  308. PCCERT_CONTEXT pCEPCert=NULL;
  309. HCRYPTPROV hProv=NULL;
  310. //open the CEP store
  311. if(NULL == (hCEPStore=CertOpenStore(
  312. CERT_STORE_PROV_SYSTEM_W,
  313. ENCODE_TYPE,
  314. NULL,
  315. CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
  316. CEP_STORE_NAME)))
  317. {
  318. hr=E_UNEXPECTED;
  319. _JumpError(hr, error, "CertOpenStore");
  320. }
  321. //get the certificate context
  322. memset(&blobCert, 0, sizeof(blobCert));
  323. blobCert.cbData = (DWORD)SysStringByteLen(bstrCertificate);
  324. blobCert.pbData = (BYTE *)bstrCertificate;
  325. if(!CryptQueryObject(
  326. CERT_QUERY_OBJECT_BLOB,
  327. &blobCert,
  328. CERT_QUERY_CONTENT_FLAG_CERT,
  329. CERT_QUERY_FORMAT_FLAG_ALL,
  330. 0,
  331. NULL,
  332. NULL,
  333. NULL,
  334. NULL,
  335. NULL,
  336. (const void **)&pCertContext))
  337. {
  338. hr=HRESULT_FROM_WIN32(GetLastError());
  339. _JumpError(hr, error, "CryptQueryObject");
  340. }
  341. if(NULL == pCertContext)
  342. {
  343. hr=E_UNEXPECTED;
  344. _JumpError(hr, error, "CryptQueryObject");
  345. }
  346. //find the certificate in CEP store
  347. if(NULL == (pCEPCert=CertFindCertificateInStore(
  348. hCEPStore,
  349. X509_ASN_ENCODING,
  350. 0,
  351. CERT_FIND_EXISTING,
  352. pCertContext,
  353. NULL)))
  354. {
  355. hr=E_UNEXPECTED;
  356. _JumpError(hr, error, "CertFindCertificateInStore");
  357. }
  358. //set the SD on the private key
  359. if(!CryptAcquireCertificatePrivateKey(pCEPCert,
  360. CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  361. NULL,
  362. &hProv,
  363. &dwKeySpec,
  364. &fFreeProv))
  365. {
  366. hr=HRESULT_FROM_WIN32(GetLastError());
  367. _JumpError(hr, error, "CryptAcquireCertificatePrivateKey");
  368. }
  369. if(!CryptGetProvParam(
  370. hProv,
  371. PP_KEYSET_SEC_DESCR,
  372. NULL,
  373. &dwSD,
  374. DACL_SECURITY_INFORMATION))
  375. {
  376. hr=HRESULT_FROM_WIN32(GetLastError());
  377. _JumpError(hr, error, "CryptAcquireCertificatePrivateKey");
  378. }
  379. pSID = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwSD);
  380. if (NULL == pSID)
  381. {
  382. hr = E_OUTOFMEMORY;
  383. _JumpError(hr, error, "LocalAlloc");
  384. }
  385. if(!CryptGetProvParam(
  386. hProv,
  387. PP_KEYSET_SEC_DESCR,
  388. (BYTE *)pSID,
  389. &dwSD,
  390. DACL_SECURITY_INFORMATION))
  391. {
  392. hr=HRESULT_FROM_WIN32(GetLastError());
  393. _JumpError(hr, error, "CryptGetProvParam");
  394. }
  395. //get acl from sd
  396. if(!GetSecurityDescriptorDacl(
  397. pSID,
  398. &fDacl,
  399. &pAcl,
  400. &fDef))
  401. {
  402. hr=HRESULT_FROM_WIN32(GetLastError());
  403. _JumpError(hr, error, "GetSecurityDescriptorDacl");
  404. }
  405. //if no dacl or everyone access, quit
  406. if((NULL==pAcl) || (FALSE == fDacl))
  407. {
  408. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  409. _JumpError(hr, error, "GetSecurityDescriptorDacl");
  410. }
  411. //get acl info
  412. if(!GetAclInformation(
  413. pAcl,
  414. &AclInfo,
  415. sizeof(AclInfo),
  416. AclSizeInformation))
  417. {
  418. hr=HRESULT_FROM_WIN32(GetLastError());
  419. _JumpError(hr, error, "GetAclInformation");
  420. }
  421. //allocate enough for new dacl since we might add a new ACE
  422. dwSD=AclInfo.AclBytesInUse
  423. +sizeof(ACCESS_ALLOWED_ACE)
  424. -sizeof(DWORD) //ACCESS_ALLOWED_ACE::SidStart
  425. +GetLengthSid(psidAccount);
  426. pNewAcl = (PACL)LocalAlloc(LPTR, dwSD);
  427. if(NULL == pNewAcl)
  428. {
  429. hr = E_OUTOFMEMORY;
  430. _JumpError(hr, error, "LocalAlloc");
  431. }
  432. if(!InitializeAcl(pNewAcl, dwSD, ACL_REVISION_DS))
  433. {
  434. hr = HRESULT_FROM_WIN32(GetLastError());
  435. _JumpError(hr, error, "InitializeAcl");
  436. }
  437. // find the first ace in the dacl
  438. if (!GetAce(pAcl, 0, (void **)&pFirstAce))
  439. {
  440. hr=HRESULT_FROM_WIN32(GetLastError());
  441. _JumpError(hr, error, "GetAce");
  442. }
  443. // add all the old aces
  444. if (!AddAce(pNewAcl, ACL_REVISION_DS, 0, pFirstAce, AclInfo.AclBytesInUse-sizeof(ACL)))
  445. {
  446. hr=HRESULT_FROM_WIN32(GetLastError());
  447. _JumpError(hr, error, "AddAce");
  448. }
  449. //add the access allowed ACE
  450. if(!AddAccessAllowedAce(pNewAcl, ACL_REVISION, dwAccess, psidAccount))
  451. {
  452. hr=HRESULT_FROM_WIN32(GetLastError());
  453. _JumpError(hr, error, "AddAccessAllowedAce");
  454. }
  455. // initialize a security descriptor.
  456. pNewSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  457. if (pNewSD == NULL)
  458. {
  459. hr = E_OUTOFMEMORY;
  460. _JumpError(hr, error, "LocalAlloc");
  461. }
  462. if(!InitializeSecurityDescriptor(pNewSD, SECURITY_DESCRIPTOR_REVISION))
  463. {
  464. hr = HRESULT_FROM_WIN32(GetLastError());
  465. _JumpError(hr, error, "InitializeSecurityDescriptor");
  466. }
  467. // add the ACL to the security descriptor.
  468. if(!SetSecurityDescriptorDacl(
  469. pNewSD,
  470. TRUE, // fDaclPresent flag
  471. pNewAcl,
  472. FALSE)) // not a default DACL
  473. {
  474. hr = HRESULT_FROM_WIN32(GetLastError());
  475. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  476. }
  477. //set sd to be protected
  478. if(!SetSecurityDescriptorControl(
  479. pNewSD,
  480. SE_DACL_PROTECTED,
  481. SE_DACL_PROTECTED))
  482. {
  483. hr = HRESULT_FROM_WIN32(GetLastError());
  484. _JumpError(hr, error, "SetSecurityDescriptorControl");
  485. }
  486. if(!IsValidSecurityDescriptor(pNewSD))
  487. {
  488. hr = HRESULT_FROM_WIN32(GetLastError());
  489. _JumpError(hr, error, "IsValidSecurityDescriptor");
  490. }
  491. //we just set it back to the privaet key
  492. if(!CryptSetProvParam(
  493. hProv,
  494. PP_KEYSET_SEC_DESCR,
  495. (BYTE*)pNewSD,
  496. DACL_SECURITY_INFORMATION))
  497. {
  498. hr = HRESULT_FROM_WIN32(GetLastError());
  499. _JumpError(hr, error, "CryptSetProvParam");
  500. }
  501. hr=S_OK;
  502. error:
  503. if(pNewSD)
  504. {
  505. LocalFree(pNewSD);
  506. }
  507. if(pSID)
  508. {
  509. LocalFree(pSID);
  510. }
  511. if(pNewAcl)
  512. {
  513. LocalFree(pNewAcl);
  514. }
  515. if(fFreeProv)
  516. {
  517. if(hProv)
  518. CryptReleaseContext(hProv, 0);
  519. }
  520. if(pCEPCert)
  521. {
  522. CertFreeCertificateContext(pCEPCert);
  523. }
  524. if(pCertContext)
  525. {
  526. CertFreeCertificateContext(pCertContext);
  527. }
  528. if(hCEPStore)
  529. {
  530. CertCloseStore(hCEPStore, 0);
  531. }
  532. return hr;
  533. }
  534. //--------------------------------------------------------------------
  535. static HRESULT EnrollForRACert(
  536. IN const WCHAR * wszDistinguishedName,
  537. IN const WCHAR * wszCSPName,
  538. IN DWORD dwCSPType,
  539. IN DWORD dwKeySize,
  540. IN DWORD dwKeySpec,
  541. IN const WCHAR * wszTemplate,
  542. IN SID *psidAccount
  543. )
  544. {
  545. HRESULT hr;
  546. LONG nDisposition;
  547. LONG nRequestID;
  548. // must be cleaned up
  549. ICEnroll3 * pXEnroll=NULL;
  550. BSTR bszConfigString=NULL;
  551. BSTR bszRequest=NULL;
  552. ICertConfig * pICertConfig=NULL;
  553. ICertRequest * pICertRequest=NULL;
  554. ICertAdmin * pICertAdmin=NULL;
  555. BSTR bszCertificate=NULL;
  556. // get the config string
  557. hr=CoCreateInstance(
  558. CLSID_CCertConfig,
  559. NULL,
  560. CLSCTX_INPROC_SERVER,
  561. IID_ICertConfig,
  562. (void **)&pICertConfig);
  563. _JumpIfError(hr, error, "CoCreateInstance(CLSID_CCertConfig)");
  564. hr = pICertConfig->GetConfig(CC_LOCALCONFIG, &bszConfigString);
  565. _JumpIfError(hr, error, "GetConfig");
  566. // create XEnroll
  567. hr=CoCreateInstance(
  568. CLSID_CEnroll,
  569. NULL,
  570. CLSCTX_INPROC_SERVER,
  571. IID_ICEnroll3,
  572. (void **)&pXEnroll);
  573. _JumpIfError(hr, error, "CoCreateInstance(CLSID_CEnroll)");
  574. // build the Offline enrollment agent cert.
  575. hr=pXEnroll->put_ProviderName((WCHAR *)wszCSPName);
  576. _JumpIfError(hr, error, "put_ProviderName");
  577. hr=pXEnroll->put_ProviderType(dwCSPType);
  578. _JumpIfError(hr, error, "put_ProviderType");
  579. hr=pXEnroll->put_ProviderFlags(CRYPT_MACHINE_KEYSET); // used in CryptAcquireContext
  580. _JumpIfError(hr, error, "put_ProviderFlags");
  581. hr=pXEnroll->put_GenKeyFlags(dwKeySize<<16);
  582. _JumpIfError(hr, error, "put_GenKeyFlags");
  583. hr=pXEnroll->put_KeySpec(dwKeySpec);
  584. _JumpIfError(hr, error, "put_KeySpec");
  585. hr=pXEnroll->put_LimitExchangeKeyToEncipherment(AT_KEYEXCHANGE==dwKeySpec);
  586. _JumpIfError(hr, error, "put_LimitExchangeKeyToEncipherment");
  587. hr=pXEnroll->put_UseExistingKeySet(FALSE);
  588. _JumpIfError(hr, error, "put_UseExistingKeySet");
  589. hr=pXEnroll->put_RequestStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE); // the keys attached to the dummy request cert go in the local machine store
  590. _JumpIfError(hr, error, "put_RequestStoreFlags");
  591. hr=pXEnroll->addCertTypeToRequest((WCHAR *)wszTemplate);
  592. _JumpIfErrorStr(hr, error, "addCertTypeToRequest", wszTemplate);
  593. hr=pXEnroll->createPKCS10((WCHAR *)wszDistinguishedName, (WCHAR *)gc_wszEnrollmentAgentOid, &bszRequest);
  594. _JumpIfError(hr, error, "CreatePKCS10");
  595. // create ICertRequest
  596. hr=CoCreateInstance(
  597. CLSID_CCertRequest,
  598. NULL,
  599. CLSCTX_INPROC_SERVER,
  600. IID_ICertRequest,
  601. (void **)&pICertRequest);
  602. _JumpIfError(hr, error, "CoCreateInstance(CLSID_CCertRequest)");
  603. // request the cert
  604. hr=pICertRequest->Submit(CR_IN_BASE64, bszRequest, NULL, bszConfigString, &nDisposition);
  605. _JumpIfError(hr, error, "Submit");
  606. // did we get it?
  607. if (CR_DISP_UNDER_SUBMISSION==nDisposition) {
  608. // we need to approve it. No problem!
  609. hr=pICertRequest->GetRequestId(&nRequestID);
  610. _JumpIfError(hr, error, "GetRequestId");
  611. // create ICertAdmin
  612. hr=CoCreateInstance(
  613. CLSID_CCertAdmin,
  614. NULL,
  615. CLSCTX_INPROC_SERVER,
  616. IID_ICertAdmin,
  617. (void **)&pICertAdmin);
  618. _JumpIfError(hr, error, "CoCreateInstance(CLSID_CCertAdmin)");
  619. // resubmit it
  620. hr=pICertAdmin->ResubmitRequest(bszConfigString, nRequestID, &nDisposition);
  621. _JumpIfError(hr, error, "ResubmitRequest");
  622. // This should have worked, but we're going to ignore the
  623. // returned disposition and use the one from the next call.
  624. // now, get the cert that we just approved
  625. hr=pICertRequest->RetrievePending(nRequestID, bszConfigString, &nDisposition);
  626. _JumpIfError(hr, error, "RetrievePending");
  627. }
  628. // We should have it by now.
  629. _Verify(CR_DISP_ISSUED==nDisposition, hr, error);
  630. // grab the cert from the CA
  631. hr=pICertRequest->GetCertificate(CR_OUT_BASE64, &bszCertificate);
  632. _JumpIfError(hr, error, "GetCertificate");
  633. // install the cert
  634. hr=pXEnroll->put_MyStoreName((WCHAR *)gc_wszCepStoreName); // We have to use our special store
  635. _JumpIfError(hr, error, "put_MyStoreName");
  636. hr=pXEnroll->put_MyStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE); // the keys attached to the final cert also go in the local machine store
  637. _JumpIfError(hr, error, "put_MyStoreFlags");
  638. hr=pXEnroll->put_RootStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
  639. _JumpIfError(hr, error, "put_RootStoreFlags");
  640. hr=pXEnroll->put_CAStoreFlags(CERT_SYSTEM_STORE_LOCAL_MACHINE);
  641. _JumpIfError(hr, error, "put_CAStoreFlags");
  642. hr=pXEnroll->put_SPCFileName(L"");
  643. _JumpIfError(hr, error, "put_MyStoreName");
  644. hr=pXEnroll->acceptPKCS7(bszCertificate);
  645. _JumpIfError(hr, error, "acceptPKCS7");
  646. //set the SD on the private key of the enrolled certificate
  647. if(psidAccount)
  648. {
  649. hr=SetSDOnCEPCertificate(bszCertificate, psidAccount);
  650. _JumpIfError(hr, error, "acceptPKCS7");
  651. }
  652. // all done
  653. hr=S_OK;
  654. error:
  655. if(NULL!=pICertConfig){
  656. pICertConfig->Release();
  657. }
  658. if (NULL!=bszCertificate) {
  659. SysFreeString(bszCertificate);
  660. }
  661. if (NULL!=pICertAdmin) {
  662. pICertAdmin->Release();
  663. }
  664. if (NULL!=pICertRequest) {
  665. pICertRequest->Release();
  666. }
  667. if (NULL!=bszRequest) {
  668. SysFreeString(bszRequest);
  669. }
  670. if (NULL!=bszConfigString) {
  671. SysFreeString(bszConfigString);
  672. }
  673. if (NULL!=pXEnroll) {
  674. pXEnroll->Release();
  675. }
  676. return hr;
  677. }
  678. //--------------------------------------------------------------------
  679. // DEBUG, not used
  680. static BOOL DumpTokenGroups(void)
  681. {
  682. #define MAX_NAME 256
  683. DWORD i, dwSize = 0, dwResult = 0;
  684. HANDLE hToken;
  685. PTOKEN_GROUPS pGroupInfo;
  686. SID_NAME_USE SidType;
  687. char lpName[MAX_NAME];
  688. char lpDomain[MAX_NAME];
  689. SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
  690. // Open a handle to the access token for the calling process.
  691. if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken )) {
  692. wprintf( L"OpenProcessToken Error %u\n", GetLastError() );
  693. return FALSE;
  694. }
  695. // Call GetTokenInformation to get the buffer size.
  696. if(!GetTokenInformation(hToken, TokenGroups, NULL, dwSize, &dwSize)) {
  697. dwResult = GetLastError();
  698. if( dwResult != ERROR_INSUFFICIENT_BUFFER ) {
  699. wprintf( L"GetTokenInformation Error %u\n", dwResult );
  700. return FALSE;
  701. }
  702. }
  703. // Allocate the buffer.
  704. pGroupInfo = (PTOKEN_GROUPS) GlobalAlloc( GPTR, dwSize );
  705. // Call GetTokenInformation again to get the group information.
  706. if(! GetTokenInformation(hToken, TokenGroups, pGroupInfo,
  707. dwSize, &dwSize ) ) {
  708. wprintf( L"GetTokenInformation Error %u\n", GetLastError() );
  709. return FALSE;
  710. }
  711. // Loop through the group SIDs looking for the administrator SID.
  712. for(i=0; i<pGroupInfo->GroupCount; i++) {
  713. // Lookup the account name and print it.
  714. dwSize = MAX_NAME;
  715. if( !LookupAccountSidA( NULL, pGroupInfo->Groups[i].Sid,
  716. lpName, &dwSize, lpDomain,
  717. &dwSize, &SidType ) ) {
  718. dwResult = GetLastError();
  719. if( dwResult == ERROR_NONE_MAPPED )
  720. strcpy( lpName, "NONE_MAPPED" );
  721. else {
  722. wprintf(L"LookupAccountSid Error %u\n", GetLastError());
  723. return FALSE;
  724. }
  725. }
  726. char * szSid=NULL;
  727. if (!ConvertSidToStringSidA(pGroupInfo->Groups[i].Sid, &szSid)) {
  728. wprintf(L"ConvertSidToStringSid Error %u\n", GetLastError());
  729. return FALSE;
  730. }
  731. // Find out if the SID is enabled in the token
  732. char * szEnable;
  733. if (pGroupInfo->Groups[i].Attributes & SE_GROUP_ENABLED) {
  734. szEnable="enabled";
  735. } else if (pGroupInfo->Groups[i].Attributes & SE_GROUP_USE_FOR_DENY_ONLY) {
  736. szEnable="deny-only";
  737. } else {
  738. szEnable="not enabled";
  739. }
  740. wprintf( L"Member of %hs\\%hs (%hs) (%hs)\n",
  741. lpDomain, lpName, szSid, szEnable );
  742. LocalFree(szSid);
  743. }
  744. if ( pGroupInfo )
  745. GlobalFree( pGroupInfo );
  746. return TRUE;
  747. }
  748. //--------------------------------------------------------------------
  749. // DEBUG, not used
  750. static void DumpAcl(PACL pAcl, ACL_SIZE_INFORMATION aclsizeinfo)
  751. {
  752. HRESULT hr;
  753. unsigned int nIndex;
  754. DWORD dwError;
  755. wprintf(L"/-- begin ACL ---\n");
  756. for (nIndex=0; nIndex<aclsizeinfo.AceCount; nIndex++) {
  757. ACE_HEADER * pAceHeader;
  758. PSID pSid=NULL;
  759. wprintf(L"| ");
  760. if (!GetAce(pAcl, nIndex, (void**)&pAceHeader)) {
  761. hr=HRESULT_FROM_WIN32(GetLastError());
  762. wprintf(L" (GetAce failed:0x%08X)\n", hr);
  763. continue;
  764. }
  765. wprintf(L"[");
  766. if (ACCESS_ALLOWED_ACE_TYPE==pAceHeader->AceType) {
  767. wprintf(L"aA_");
  768. pSid=&((ACCESS_ALLOWED_ACE *)pAceHeader)->SidStart;
  769. } else if (ACCESS_DENIED_ACE_TYPE==pAceHeader->AceType) {
  770. wprintf(L"aD_");
  771. pSid=&((ACCESS_DENIED_ACE *)pAceHeader)->SidStart;
  772. } else if (ACCESS_ALLOWED_OBJECT_ACE_TYPE==pAceHeader->AceType) {
  773. wprintf(L"aAo");
  774. pSid=&((ACCESS_ALLOWED_OBJECT_ACE *)pAceHeader)->SidStart;
  775. if (((ACCESS_ALLOWED_OBJECT_ACE *)pAceHeader)->Flags!=(ACE_OBJECT_TYPE_PRESENT|ACE_INHERITED_OBJECT_TYPE_PRESENT)) {
  776. pSid=((BYTE *)pSid)-sizeof(GUID);
  777. }
  778. } else if (ACCESS_DENIED_OBJECT_ACE_TYPE==pAceHeader->AceType) {
  779. wprintf(L"aDo");
  780. pSid=&((ACCESS_DENIED_OBJECT_ACE *)pAceHeader)->SidStart;
  781. if (((ACCESS_DENIED_OBJECT_ACE *)pAceHeader)->Flags!=(ACE_OBJECT_TYPE_PRESENT|ACE_INHERITED_OBJECT_TYPE_PRESENT)) {
  782. pSid=((BYTE *)pSid)-sizeof(GUID);
  783. }
  784. } else {
  785. wprintf(L"sa?");
  786. }
  787. wprintf(L"] ");
  788. if (NULL!=pSid) {
  789. // print the sid
  790. {
  791. WCHAR wszName[MAX_NAME];
  792. WCHAR wszDomain[MAX_NAME];
  793. DWORD dwSize=MAX_NAME;
  794. SID_NAME_USE SidType;
  795. if(!LookupAccountSidW(
  796. NULL, pSid,
  797. wszName, &dwSize, wszDomain,
  798. &dwSize, &SidType))
  799. {
  800. dwError=GetLastError();
  801. if (dwError==ERROR_NONE_MAPPED) {
  802. wprintf(L"(Unknown)");
  803. } else {
  804. hr=HRESULT_FROM_WIN32(dwError);
  805. wprintf(L"(Error 0x%08X)", hr);
  806. }
  807. } else {
  808. wprintf(L"%ws\\%ws", wszDomain, wszName);
  809. }
  810. }
  811. {
  812. WCHAR * wszSid=NULL;
  813. if (!ConvertSidToStringSidW(pSid, &wszSid)) {
  814. hr=HRESULT_FROM_WIN32(GetLastError());
  815. wprintf(L"(Error 0x%08X)", hr);
  816. } else {
  817. wprintf(L" %ws", wszSid);
  818. LocalFree(wszSid);
  819. }
  820. }
  821. }
  822. wprintf(L"\n");
  823. }
  824. wprintf(L"\\-- end ACL ---\n");
  825. }
  826. //--------------------------------------------------------------------
  827. static HRESULT GetRootDomEntitySid(SID ** ppSid, DWORD dwEntityRid)
  828. {
  829. HRESULT hr;
  830. NET_API_STATUS nasError;
  831. unsigned int nSubAuthorities;
  832. unsigned int nSubAuthIndex;
  833. // must be cleaned up
  834. SID * psidRootDomEntity=NULL;
  835. USER_MODALS_INFO_2 * pumi2=NULL;
  836. DOMAIN_CONTROLLER_INFOW * pdci=NULL;
  837. DOMAIN_CONTROLLER_INFOW * pdciForest=NULL;
  838. // initialize out params
  839. *ppSid=NULL;
  840. // get the forest name
  841. nasError=DsGetDcNameW(NULL, NULL, NULL, NULL, 0, &pdciForest);
  842. if (NERR_Success!=nasError) {
  843. hr=HRESULT_FROM_WIN32(nasError);
  844. _JumpError(hr, error, "DsGetDcNameW");
  845. }
  846. // get the top level DC name
  847. nasError=DsGetDcNameW(NULL, pdciForest->DnsForestName, NULL, NULL, 0, &pdci);
  848. if (NERR_Success!=nasError) {
  849. hr=HRESULT_FROM_WIN32(nasError);
  850. _JumpError(hr, error, "DsGetDcNameW");
  851. }
  852. // get the domain Sid on the top level DC.
  853. nasError=NetUserModalsGet(pdci->DomainControllerName, 2, (LPBYTE *)&pumi2);
  854. if(NERR_Success!=nasError) {
  855. hr=HRESULT_FROM_WIN32(nasError);
  856. _JumpError(hr, error, "NetUserModalsGet");
  857. }
  858. nSubAuthorities=*GetSidSubAuthorityCount(pumi2->usrmod2_domain_id);
  859. // allocate storage for new Sid. account domain Sid + account Rid
  860. psidRootDomEntity=(SID *)LocalAlloc(LPTR, GetSidLengthRequired((UCHAR)(nSubAuthorities+1)));
  861. _JumpIfOutOfMemory(hr, error, psidRootDomEntity);
  862. // copy the first few peices into the SID
  863. if (!InitializeSid(psidRootDomEntity,
  864. GetSidIdentifierAuthority(pumi2->usrmod2_domain_id),
  865. (BYTE)(nSubAuthorities+1)))
  866. {
  867. hr=HRESULT_FROM_WIN32(GetLastError());
  868. _JumpError(hr, error, "InitializeSid");
  869. }
  870. // copy existing subauthorities from account domain Sid into new Sid
  871. for (nSubAuthIndex=0; nSubAuthIndex < nSubAuthorities ; nSubAuthIndex++) {
  872. *GetSidSubAuthority(psidRootDomEntity, nSubAuthIndex)=
  873. *GetSidSubAuthority(pumi2->usrmod2_domain_id, nSubAuthIndex);
  874. }
  875. // append Rid to new Sid
  876. *GetSidSubAuthority(psidRootDomEntity, nSubAuthorities)=dwEntityRid;
  877. *ppSid=psidRootDomEntity;
  878. psidRootDomEntity=NULL;
  879. hr=S_OK;
  880. error:
  881. if (NULL!=psidRootDomEntity) {
  882. LocalFree(psidRootDomEntity);
  883. }
  884. if (NULL!=pdci) {
  885. NetApiBufferFree(pdci);
  886. }
  887. if (NULL!=pdci) {
  888. NetApiBufferFree(pdciForest);
  889. }
  890. if (NULL!=pumi2) {
  891. NetApiBufferFree(pumi2);
  892. }
  893. return hr;
  894. }
  895. //--------------------------------------------------------------------
  896. static HRESULT GetEntAdminSid(SID ** ppSid)
  897. {
  898. return GetRootDomEntitySid(ppSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS);
  899. }
  900. //--------------------------------------------------------------------
  901. static HRESULT GetRootDomAdminSid(SID ** ppSid)
  902. {
  903. return GetRootDomEntitySid(ppSid, DOMAIN_GROUP_RID_ADMINS);
  904. }
  905. //--------------------------------------------------------------------
  906. static HRESULT GetThisComputerSid(SID ** ppSid)
  907. {
  908. HRESULT hr;
  909. DWORD cchSize;
  910. DWORD dwSidSize;
  911. DWORD dwDomainSize;
  912. SID_NAME_USE snu;
  913. // must be cleaned up
  914. SID * psidThisComputer=NULL;
  915. WCHAR * wszName=NULL;
  916. WCHAR * wszDomain=NULL;
  917. // initialize out params
  918. *ppSid=NULL;
  919. // get the size of the computer's name
  920. cchSize=0;
  921. _Verify(!GetComputerObjectNameW(NameSamCompatible, NULL, &cchSize), hr, error);
  922. if (ERROR_INSUFFICIENT_BUFFER!=GetLastError()) {
  923. hr=HRESULT_FROM_WIN32(GetLastError());
  924. _JumpError(hr, error, "GetComputerObjectNameW");
  925. }
  926. // bug in GetComputerObjectNameW
  927. cchSize++;
  928. // allocate memory
  929. wszName=(WCHAR *)LocalAlloc(LPTR, cchSize*sizeof(WCHAR));
  930. _JumpIfOutOfMemory(hr, error, wszName);
  931. // get the computer's name
  932. if (!GetComputerObjectNameW(NameSamCompatible, wszName, &cchSize)) {
  933. hr=HRESULT_FROM_WIN32(GetLastError());
  934. _JumpError(hr, error, "GetComputerObjectNameW");
  935. }
  936. // get the size of the sid
  937. dwSidSize=0;
  938. dwDomainSize=0;
  939. _Verify(!LookupAccountNameW(NULL, wszName, NULL, &dwSidSize, NULL, &dwDomainSize, &snu), hr, error);
  940. if (ERROR_INSUFFICIENT_BUFFER!=GetLastError()) {
  941. hr=HRESULT_FROM_WIN32(GetLastError());
  942. _JumpError(hr, error, "LookupAccountNameW");
  943. }
  944. // allocate memory
  945. wszDomain=(WCHAR *)LocalAlloc(LPTR, dwDomainSize*sizeof(WCHAR));
  946. _JumpIfOutOfMemory(hr, error, wszDomain);
  947. psidThisComputer=(SID *)LocalAlloc(LPTR, dwSidSize);
  948. _JumpIfOutOfMemory(hr, error, psidThisComputer);
  949. // get the sid
  950. if (!LookupAccountNameW(NULL, wszName, psidThisComputer, &dwSidSize, wszDomain, &dwDomainSize, &snu)) {
  951. hr=HRESULT_FROM_WIN32(GetLastError());
  952. _JumpError(hr, error, "LookupAccountNameW");
  953. }
  954. // success!
  955. *ppSid=psidThisComputer;
  956. psidThisComputer=NULL;
  957. hr=S_OK;
  958. error:
  959. if (NULL!=psidThisComputer) {
  960. LocalFree(psidThisComputer);
  961. }
  962. if (NULL!=wszName) {
  963. LocalFree(wszName);
  964. }
  965. if (NULL!=wszDomain) {
  966. LocalFree(wszDomain);
  967. }
  968. return hr;
  969. }
  970. //--------------------------------------------------------------------
  971. static HRESULT ConfirmAccess(PSECURITY_DESCRIPTOR * ppSD, SID * pTrustworthySid, BOOL * pbSDChanged)
  972. {
  973. //define ENROLL_ACCESS_MASK (0x130)
  974. HRESULT hr;
  975. PACL pAcl;
  976. BOOL bAclPresent;
  977. BOOL bDefaultAcl;
  978. unsigned int nIndex;
  979. ACL_SIZE_INFORMATION aclsizeinfo;
  980. bool bSidInAcl;
  981. // must be cleaned up
  982. PSECURITY_DESCRIPTOR pAbsSD=NULL;
  983. ACL * pAbsDacl=NULL;
  984. ACL * pAbsSacl=NULL;
  985. SID * pAbsOwner=NULL;
  986. SID * pAbsPriGrp=NULL;
  987. ACL * pNewDacl=NULL;
  988. PSECURITY_DESCRIPTOR pNewSD=NULL;
  989. // initialize out params
  990. *pbSDChanged=FALSE;
  991. // get the (D)ACL from the security descriptor
  992. if (!GetSecurityDescriptorDacl(*ppSD, &bAclPresent, &pAcl, &bDefaultAcl)) {
  993. hr=HRESULT_FROM_WIN32(GetLastError());
  994. _JumpError(hr, error, "GetSecurityDescriptorDacl");
  995. }
  996. _Verify(bAclPresent, hr, error);
  997. if (NULL==pAcl) {
  998. hr=E_FAIL;
  999. _JumpError(hr, error, "GetSecurityDescriptorDacl");
  1000. }
  1001. // find out how many ACEs
  1002. if (!GetAclInformation(pAcl, &aclsizeinfo, sizeof(aclsizeinfo), AclSizeInformation)) {
  1003. hr=HRESULT_FROM_WIN32(GetLastError());
  1004. _JumpError(hr, error, "GetAclInformation");
  1005. }
  1006. //DumpAcl(pAcl,aclsizeinfo);
  1007. // find our sid in the acl
  1008. bSidInAcl=false;
  1009. for (nIndex=0; nIndex<aclsizeinfo.AceCount; nIndex++) {
  1010. ACE_HEADER * pAceHeader;
  1011. ACCESS_ALLOWED_OBJECT_ACE * pAccessAce;
  1012. PSID pSid=NULL;
  1013. if (!GetAce(pAcl, nIndex, (void**)&pAceHeader)) {
  1014. hr=HRESULT_FROM_WIN32(GetLastError());
  1015. _JumpError(hr, error, "GetAce");
  1016. }
  1017. // find the sid for this ACE
  1018. if (ACCESS_ALLOWED_OBJECT_ACE_TYPE!=pAceHeader->AceType && ACCESS_DENIED_OBJECT_ACE_TYPE!=pAceHeader->AceType) {
  1019. // we are only interested in OBJECT ace types
  1020. continue;
  1021. }
  1022. // note that ACCESS_ALLOWED_OBJECT_ACE and ACCESS_DENIED_OBJECT_ACE are the same structurally.
  1023. pAccessAce=(ACCESS_ALLOWED_OBJECT_ACE *)pAceHeader;
  1024. _Verify(ACE_OBJECT_TYPE_PRESENT==pAccessAce->Flags, hr, error);
  1025. pSid=((BYTE *)&pAccessAce->SidStart)-sizeof(GUID);
  1026. // confirm the GUID
  1027. if (!IsEqualGUID(pAccessAce->ObjectType, GUID_ENROLL)) {
  1028. continue;
  1029. }
  1030. // make sure this is the sid we are looking for
  1031. if (!EqualSid(pSid, pTrustworthySid)) {
  1032. continue;
  1033. }
  1034. // Was this a denial?
  1035. if (ACCESS_DENIED_OBJECT_ACE_TYPE==pAceHeader->AceType) {
  1036. // It's not anymore!
  1037. pAceHeader->AceType=ACCESS_ALLOWED_OBJECT_ACE_TYPE;
  1038. *pbSDChanged=TRUE;
  1039. }
  1040. // is the mask wrong?
  1041. if (0==(pAccessAce->Mask&ACTRL_DS_CONTROL_ACCESS)) {
  1042. // It's not anymore!
  1043. pAccessAce->Mask|=ACTRL_DS_CONTROL_ACCESS;
  1044. *pbSDChanged=TRUE;
  1045. }
  1046. // The sid is now in the acl and set to allow access.
  1047. bSidInAcl=true;
  1048. break;
  1049. }
  1050. // Was the sid in the acl?
  1051. if (false==bSidInAcl) {
  1052. SECURITY_DESCRIPTOR_CONTROL sdcon;
  1053. DWORD dwRevision;
  1054. DWORD dwNewAclSize;
  1055. DWORD dwAbsSDSize=0;
  1056. DWORD dwDaclSize=0;
  1057. DWORD dwSaclSize=0;
  1058. DWORD dwOwnerSize=0;
  1059. DWORD dwPriGrpSize=0;
  1060. ACE_HEADER * pFirstAce;
  1061. DWORD dwRelSDSize=0;
  1062. // we have to be self-relative
  1063. if (!GetSecurityDescriptorControl(*ppSD, &sdcon, &dwRevision)) {
  1064. hr=HRESULT_FROM_WIN32(GetLastError());
  1065. _JumpError(hr, error, "GetSecurityDescriptorControl");
  1066. }
  1067. _Verify(sdcon&SE_SELF_RELATIVE, hr, error);
  1068. // get the sizes
  1069. _Verify(!MakeAbsoluteSD(*ppSD, NULL, &dwAbsSDSize, NULL, &dwDaclSize, NULL, &dwSaclSize, NULL, &dwOwnerSize, NULL, &dwPriGrpSize), hr, error);
  1070. if (ERROR_INSUFFICIENT_BUFFER!=GetLastError()) {
  1071. hr=HRESULT_FROM_WIN32(GetLastError());
  1072. _JumpError(hr, error, "MakeAbsoluteSD");
  1073. }
  1074. // allocate memory
  1075. pAbsSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwAbsSDSize);
  1076. _JumpIfOutOfMemory(hr, error, pAbsSD);
  1077. pAbsDacl=(ACL * )LocalAlloc(LPTR, dwDaclSize);
  1078. _JumpIfOutOfMemory(hr, error, pAbsDacl);
  1079. pAbsSacl=(ACL * )LocalAlloc(LPTR, dwSaclSize);
  1080. _JumpIfOutOfMemory(hr, error, pAbsSacl);
  1081. pAbsOwner=(SID *)LocalAlloc(LPTR, dwOwnerSize);
  1082. _JumpIfOutOfMemory(hr, error, pAbsOwner);
  1083. pAbsPriGrp=(SID *)LocalAlloc(LPTR, dwPriGrpSize);
  1084. _JumpIfOutOfMemory(hr, error, pAbsPriGrp);
  1085. // copy the SD to the memory buffers
  1086. if (!MakeAbsoluteSD(*ppSD, pAbsSD, &dwAbsSDSize, pAbsDacl, &dwDaclSize, pAbsSacl, &dwSaclSize, pAbsOwner, &dwOwnerSize, pAbsPriGrp, &dwPriGrpSize)) {
  1087. hr=HRESULT_FROM_WIN32(GetLastError());
  1088. _JumpError(hr, error, "MakeAbsoluteSD");
  1089. }
  1090. // get the current size info for the dacl
  1091. if (!GetAclInformation(pAbsDacl, &aclsizeinfo, sizeof(aclsizeinfo), AclSizeInformation)) {
  1092. hr=HRESULT_FROM_WIN32(GetLastError());
  1093. _JumpError(hr, error, "GetAclInformation");
  1094. }
  1095. // figure out the new size
  1096. dwNewAclSize=aclsizeinfo.AclBytesInUse+sizeof(_ACCESS_ALLOWED_OBJECT_ACE)
  1097. -sizeof(GUID) //ACCESS_ALLOWED_OBJECT_ACE::InheritedObjectType
  1098. -sizeof(DWORD) //ACCESS_ALLOWED_OBJECT_ACE::SidStart
  1099. +GetLengthSid(pTrustworthySid);
  1100. // allocate memory
  1101. pNewDacl=(ACL *)LocalAlloc(LPTR, dwNewAclSize);
  1102. _JumpIfOutOfMemory(hr, error, pNewDacl);
  1103. // init the header
  1104. if (!InitializeAcl(pNewDacl, dwNewAclSize, ACL_REVISION_DS)) {
  1105. hr=HRESULT_FROM_WIN32(GetLastError());
  1106. _JumpError(hr, error, "InitializeAcl");
  1107. }
  1108. // find the first ace in the dacl
  1109. if (!GetAce(pAbsDacl, 0, (void **)&pFirstAce)) {
  1110. hr=HRESULT_FROM_WIN32(GetLastError());
  1111. _JumpError(hr, error, "GetAce");
  1112. }
  1113. // add all the old aces
  1114. if (!AddAce(pNewDacl, ACL_REVISION_DS, 0, pFirstAce, aclsizeinfo.AclBytesInUse-sizeof(ACL))) {
  1115. hr=HRESULT_FROM_WIN32(GetLastError());
  1116. _JumpError(hr, error, "AddAce");
  1117. }
  1118. // finally, add the new acl
  1119. if (!AddAccessAllowedObjectAce(pNewDacl, ACL_REVISION_DS, OBJECT_INHERIT_ACE, ACTRL_DS_CONTROL_ACCESS, (GUID *)&GUID_ENROLL, NULL, pTrustworthySid)) {
  1120. hr=HRESULT_FROM_WIN32(GetLastError());
  1121. _JumpError(hr, error, "AddAccessAllowedObjectAce");
  1122. }
  1123. // stick the new dacl in the sd
  1124. if (!SetSecurityDescriptorDacl(pAbsSD, TRUE, pNewDacl, FALSE)) {
  1125. hr=HRESULT_FROM_WIN32(GetLastError());
  1126. _JumpError(hr, error, "SetSecurityDescriptorDacl");
  1127. }
  1128. // compact everything back together
  1129. // get the size
  1130. _Verify(!MakeSelfRelativeSD(pAbsSD, NULL, &dwRelSDSize), hr, error);
  1131. if (ERROR_INSUFFICIENT_BUFFER!=GetLastError()) {
  1132. hr=HRESULT_FROM_WIN32(GetLastError());
  1133. _JumpError(hr, error, "MakeSelfRelativeSD");
  1134. }
  1135. // allocate memory
  1136. pNewSD=(PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, dwRelSDSize);
  1137. _JumpIfOutOfMemory(hr, error, pNewSD);
  1138. // copy the SD to the new memory buffer
  1139. if (!MakeSelfRelativeSD(pAbsSD, pNewSD, &dwRelSDSize)) {
  1140. hr=HRESULT_FROM_WIN32(GetLastError());
  1141. _JumpError(hr, error, "MakeSelfRelativeSD");
  1142. }
  1143. // Whew! We made it!
  1144. LocalFree(*ppSD);
  1145. *ppSD=pNewSD;
  1146. pNewSD=NULL;
  1147. *pbSDChanged=TRUE;
  1148. } // <- end if sid not in acl
  1149. _Verify(IsValidSecurityDescriptor(*ppSD), hr, error);
  1150. hr=S_OK;
  1151. error:
  1152. if (NULL!=pNewSD) {
  1153. LocalFree(pNewSD);
  1154. }
  1155. if (NULL!=pNewDacl) {
  1156. LocalFree(pNewDacl);
  1157. }
  1158. if (NULL!=pAbsSD) {
  1159. LocalFree(pAbsSD);
  1160. }
  1161. if (NULL!=pAbsDacl) {
  1162. LocalFree(pAbsDacl);
  1163. }
  1164. if (NULL!=pAbsSacl) {
  1165. LocalFree(pAbsSacl);
  1166. }
  1167. if (NULL!=pAbsOwner) {
  1168. LocalFree(pAbsOwner);
  1169. }
  1170. if (NULL!=pAbsPriGrp) {
  1171. LocalFree(pAbsPriGrp);
  1172. }
  1173. return hr;
  1174. }
  1175. //####################################################################
  1176. // public functions
  1177. //--------------------------------------------------------------------
  1178. BOOL IsNT5(void)
  1179. {
  1180. HRESULT hr;
  1181. OSVERSIONINFO ovi;
  1182. static BOOL s_fDone=FALSE;
  1183. static BOOL s_fNT5=FALSE;
  1184. if (!s_fDone) {
  1185. s_fDone=TRUE;
  1186. // get and confirm platform info
  1187. ovi.dwOSVersionInfoSize = sizeof(ovi);
  1188. if (!GetVersionEx(&ovi)) {
  1189. hr=HRESULT_FROM_WIN32(GetLastError());
  1190. _JumpError(hr, error, "GetVersionEx");
  1191. }
  1192. if (VER_PLATFORM_WIN32_NT!=ovi.dwPlatformId) {
  1193. hr=ERROR_CANCELLED;
  1194. _JumpError(hr, error, "Not a supported OS");
  1195. }
  1196. if ((5 <= ovi.dwMajorVersion) && (1 <= ovi.dwMinorVersion)){
  1197. s_fNT5=TRUE;
  1198. }
  1199. }
  1200. error:
  1201. return s_fNT5;
  1202. }
  1203. //--------------------------------------------------------------------
  1204. BOOL IsIISInstalled(void)
  1205. {
  1206. HRESULT hr;
  1207. // must be cleaned up
  1208. IMSAdminBase * pIMeta=NULL;
  1209. hr=CoCreateInstance(
  1210. CLSID_MSAdminBase,
  1211. NULL,
  1212. CLSCTX_ALL,
  1213. IID_IMSAdminBase,
  1214. (VOID **) &pIMeta);
  1215. if (FAILED(hr)) {
  1216. _IgnoreError(hr, "CoCreateInstance(CLSID_MSAdminBase)");
  1217. }
  1218. //error:
  1219. if (NULL!=pIMeta) {
  1220. pIMeta->Release();
  1221. }
  1222. return (S_OK==hr);
  1223. }
  1224. //--------------------------------------------------------------------
  1225. HRESULT CEPUpdateApplicationPool(BOOL fDC, const WCHAR * pwszApplicationPool, BOOL fLocalSystem, const WCHAR * pwszUserName, const WCHAR * pwszPassword)
  1226. {
  1227. HRESULT hr=E_FAIL;
  1228. METADATA_RECORD mr;
  1229. DWORD dwLogonMethod=MD_LOGON_INTERACTIVE;
  1230. DWORD dwAppPoolID=MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
  1231. DWORD dwTimeout=0;
  1232. // must be cleaned up
  1233. WCHAR * wszFullAppPath=NULL; // "/lm/w3svc/apppools/SCEP"
  1234. IMSAdminBase * pIMeta=NULL;
  1235. METADATA_HANDLE hMetaRoot=NULL;
  1236. METADATA_HANDLE hMetaKey=NULL;
  1237. //check input parameter
  1238. if(NULL==pwszApplicationPool)
  1239. {
  1240. hr=E_INVALIDARG;
  1241. _JumpIfError(hr, error, "paramCheck");
  1242. }
  1243. //change the logon type to network logon on the DC so that the domain account does not have
  1244. //to have the local logon provilege to the DC; NETWORK logon does not have the correct token
  1245. //to validate user on the network; since we are running the DC, we should be validate locally
  1246. //and everything should just work.
  1247. if(fDC)
  1248. dwLogonMethod=MD_LOGON_NETWORK;
  1249. if(fLocalSystem)
  1250. {
  1251. dwAppPoolID=MD_APPPOOL_IDENTITY_TYPE_LOCALSYSTEM;
  1252. }
  1253. else
  1254. {
  1255. dwAppPoolID=MD_APPPOOL_IDENTITY_TYPE_SPECIFICUSER;
  1256. if((NULL==pwszUserName) || (NULL==pwszPassword))
  1257. {
  1258. hr=E_INVALIDARG;
  1259. _JumpIfError(hr, error, "paramCheck");
  1260. }
  1261. }
  1262. wszFullAppPath=(WCHAR *)LocalAlloc(LPTR, (wcslen(gc_wszAppPoolBase)+1+wcslen(pwszApplicationPool)+1)*sizeof(WCHAR));
  1263. _JumpIfOutOfMemory(hr, error, wszFullAppPath);
  1264. wcscpy(wszFullAppPath, gc_wszAppPoolBase);
  1265. wcscat(wszFullAppPath, L"/");
  1266. wcscat(wszFullAppPath, pwszApplicationPool);
  1267. // Create an instance of the metabase object
  1268. hr=CoCreateInstance(
  1269. CLSID_MSAdminBase,
  1270. NULL,
  1271. CLSCTX_ALL,
  1272. IID_IMSAdminBase,
  1273. (void **) &pIMeta);
  1274. _JumpIfError(hr, error, "CoCreateInstance(CLSID_MSAdminBase)");
  1275. // open the top level
  1276. hr=vrOpenRoot(pIMeta, FALSE, gc_wszAppPoolBase, &hMetaRoot);
  1277. _JumpIfError(hr, error, "vrOpenRoot");
  1278. // Add new VDir called "SCEP"
  1279. hr=pIMeta->AddKey(hMetaRoot, pwszApplicationPool);
  1280. if(HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)==hr)
  1281. {
  1282. // That's fine.
  1283. _IgnoreError(hr, "AddKey");
  1284. }
  1285. else
  1286. {
  1287. _JumpIfErrorStr(hr, error, "AddKey", pwszApplicationPool);
  1288. }
  1289. // close the root key
  1290. hr=pIMeta->CloseKey(hMetaRoot);
  1291. hMetaRoot=NULL;
  1292. _JumpIfError(hr, error, "CloseKey");
  1293. // Open the new VDir at /lm/w3svc/apppools/SCEP
  1294. hr=pIMeta->OpenKey(
  1295. METADATA_MASTER_ROOT_HANDLE,
  1296. wszFullAppPath,
  1297. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1298. 1000,
  1299. &hMetaKey);
  1300. _JumpIfErrorStr(hr, error, "OpenKey", wszFullAppPath);
  1301. //set properties on this application
  1302. if(FALSE == fLocalSystem)
  1303. {
  1304. //set the UserName
  1305. memset(&mr, 0, sizeof(METADATA_RECORD));
  1306. mr.dwMDIdentifier=MD_WAM_USER_NAME;
  1307. mr.dwMDAttributes=METADATA_INHERIT;
  1308. mr.dwMDUserType=IIS_MD_UT_FILE;
  1309. mr.dwMDDataType=STRING_METADATA;
  1310. mr.dwMDDataLen=(wcslen(pwszUserName)+1)*sizeof(WCHAR);
  1311. mr.pbMDData=(BYTE *)(pwszUserName);
  1312. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1313. _JumpIfError(hr, error, "SetData");
  1314. //set the password
  1315. memset(&mr, 0, sizeof(METADATA_RECORD));
  1316. mr.dwMDIdentifier=MD_WAM_PWD;
  1317. mr.dwMDAttributes=METADATA_INHERIT | METADATA_SECURE;
  1318. mr.dwMDUserType=IIS_MD_UT_FILE;
  1319. mr.dwMDDataType=STRING_METADATA;
  1320. mr.dwMDDataLen=(wcslen(pwszPassword)+1)*sizeof(WCHAR);
  1321. mr.pbMDData=(BYTE *)(pwszPassword);
  1322. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1323. _JumpIfError(hr, error, "SetData");
  1324. //set the logon method
  1325. memset(&mr, 0, sizeof(METADATA_RECORD));
  1326. mr.dwMDIdentifier=MD_LOGON_METHOD;
  1327. mr.dwMDAttributes=METADATA_INHERIT;
  1328. mr.dwMDUserType=IIS_MD_UT_FILE;
  1329. mr.dwMDDataType=DWORD_METADATA;
  1330. mr.dwMDDataLen=sizeof(dwLogonMethod);
  1331. mr.pbMDData=(BYTE *)(&dwLogonMethod);
  1332. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1333. _JumpIfError(hr, error, "SetData");
  1334. }
  1335. //set the application identity
  1336. memset(&mr, 0, sizeof(METADATA_RECORD));
  1337. mr.dwMDIdentifier=MD_APPPOOL_IDENTITY_TYPE;
  1338. mr.dwMDAttributes=METADATA_INHERIT;
  1339. mr.dwMDUserType=IIS_MD_UT_SERVER;
  1340. mr.dwMDDataType=DWORD_METADATA;
  1341. mr.dwMDDataLen=sizeof(dwAppPoolID);
  1342. mr.pbMDData=(BYTE *)(&dwAppPoolID);
  1343. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1344. _JumpIfError(hr, error, "SetData");
  1345. #ifdef MD_APPPOOL_FRIENDLY_NAME
  1346. //set the application pool friendly name
  1347. memset(&mr, 0, sizeof(METADATA_RECORD));
  1348. mr.dwMDIdentifier=MD_APPPOOL_FRIENDLY_NAME;
  1349. mr.dwMDAttributes=METADATA_NO_ATTRIBUTES;
  1350. mr.dwMDUserType=IIS_MD_UT_SERVER;
  1351. mr.dwMDDataType=STRING_METADATA;
  1352. mr.dwMDDataLen=(wcslen(pwszApplicationPool)+1)*sizeof(WCHAR);
  1353. mr.pbMDData=(BYTE *)(pwszApplicationPool);
  1354. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1355. _JumpIfError(hr, error, "SetData");
  1356. #endif
  1357. //set the PeriodicRestartTime to 0
  1358. memset(&mr, 0, sizeof(METADATA_RECORD));
  1359. mr.dwMDIdentifier=MD_APPPOOL_PERIODIC_RESTART_TIME;
  1360. mr.dwMDAttributes=METADATA_INHERIT;
  1361. mr.dwMDUserType=IIS_MD_UT_SERVER;
  1362. mr.dwMDDataType=DWORD_METADATA;
  1363. mr.dwMDDataLen=sizeof(dwTimeout);
  1364. mr.pbMDData=(BYTE *)(&dwTimeout);
  1365. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1366. _JumpIfError(hr, error, "SetData");
  1367. //set the IDleTimeOut to 0
  1368. memset(&mr, 0, sizeof(METADATA_RECORD));
  1369. mr.dwMDIdentifier=MD_APPPOOL_IDLE_TIMEOUT;
  1370. mr.dwMDAttributes=METADATA_INHERIT;
  1371. mr.dwMDUserType=IIS_MD_UT_SERVER;
  1372. mr.dwMDDataType=DWORD_METADATA;
  1373. mr.dwMDDataLen=sizeof(dwTimeout);
  1374. mr.pbMDData=(BYTE *)(&dwTimeout);
  1375. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1376. _JumpIfError(hr, error, "SetData");
  1377. // done with this key.
  1378. hr=pIMeta->CloseKey(hMetaKey);
  1379. hMetaKey=NULL;
  1380. _JumpIfError(hr, error, "CloseKey");
  1381. // Flush out the changes and close
  1382. pIMeta->SaveData();
  1383. hr=S_OK;
  1384. error:
  1385. if (NULL!=wszFullAppPath)
  1386. {
  1387. LocalFree(wszFullAppPath);
  1388. }
  1389. if (NULL!=hMetaKey)
  1390. {
  1391. pIMeta->CloseKey(hMetaKey);
  1392. }
  1393. if (NULL!=hMetaRoot)
  1394. {
  1395. pIMeta->CloseKey(hMetaRoot);
  1396. }
  1397. if (NULL!=pIMeta)
  1398. {
  1399. pIMeta->Release();
  1400. }
  1401. return hr;
  1402. }
  1403. //--------------------------------------------------------------------
  1404. HRESULT AddVDir(IN BOOL fDC,
  1405. IN const WCHAR * wszDirectory,
  1406. IN const WCHAR * wszApplicationPool,
  1407. IN BOOL fLocalSystem,
  1408. IN const WCHAR * wszUserName,
  1409. IN const WCHAR * wszPassword)
  1410. {
  1411. HRESULT hr;
  1412. METADATA_RECORD mr;
  1413. DWORD dwAccessPerms;
  1414. DWORD dwAuthenticationType;
  1415. const WCHAR * wszKeyType=IIS_CLASS_WEB_VDIR_W;
  1416. WCHAR wszSysDirBuf[MAX_PATH + 2];
  1417. bool fISAPIEnabled=false;
  1418. BOOL fEnabled=FALSE;
  1419. // must be cleaned up
  1420. IMSAdminBase * pIMeta=NULL;
  1421. IWamAdmin * pIWam=NULL;
  1422. IIISApplicationAdmin *pIIISAppAdmin=NULL;
  1423. METADATA_HANDLE hMetaRoot=NULL;
  1424. METADATA_HANDLE hMetaKey=NULL;
  1425. WCHAR * wszPhysicalPath=NULL; // "c:\winnt\system32\certsrv\mscep"
  1426. WCHAR * wszRelativeVirtualPath=NULL; // "certsrv/mscep"
  1427. WCHAR * wszFullVirtualPath=NULL; // "/LM/W3svc/1/ROOT/certsrv/mscep"
  1428. WCHAR * wszFullPhysicalPath=NULL; // "c:\winnt\system32\certsrv\mscep\mscep.dll"
  1429. // build the directories
  1430. if (FALSE==GetSystemDirectoryW(wszSysDirBuf, MAX_PATH + 2)) {
  1431. hr=HRESULT_FROM_WIN32(GetLastError());
  1432. _JumpError(hr, error, "GetSystemDirectory");
  1433. }
  1434. wszPhysicalPath=(WCHAR *)LocalAlloc(LPTR, (wcslen(wszSysDirBuf)+1+wcslen(gc_wszCertSrvDir)+1+wcslen(wszDirectory)+1)*sizeof(WCHAR));
  1435. _JumpIfOutOfMemory(hr, error, wszPhysicalPath);
  1436. wcscpy(wszPhysicalPath, wszSysDirBuf);
  1437. wcscat(wszPhysicalPath, L"\\");
  1438. wcscat(wszPhysicalPath, gc_wszCertSrvDir);
  1439. wcscat(wszPhysicalPath, L"\\");
  1440. wcscat(wszPhysicalPath, wszDirectory);
  1441. wszRelativeVirtualPath=(WCHAR *)LocalAlloc(LPTR, (wcslen(gc_wszCertSrvDir)+1+wcslen(wszDirectory)+1)*sizeof(WCHAR));
  1442. _JumpIfOutOfMemory(hr, error, wszRelativeVirtualPath);
  1443. wcscpy(wszRelativeVirtualPath, gc_wszCertSrvDir);
  1444. wcscat(wszRelativeVirtualPath, L"/");
  1445. wcscat(wszRelativeVirtualPath, wszDirectory);
  1446. wszFullVirtualPath=(WCHAR *)LocalAlloc(LPTR, (wcslen(gc_wszBaseRoot)+1+wcslen(wszRelativeVirtualPath)+1)*sizeof(WCHAR));
  1447. _JumpIfOutOfMemory(hr, error, wszFullVirtualPath);
  1448. wcscpy(wszFullVirtualPath, gc_wszBaseRoot);
  1449. wcscat(wszFullVirtualPath, L"/");
  1450. wcscat(wszFullVirtualPath, wszRelativeVirtualPath);
  1451. wszFullPhysicalPath=(WCHAR *)LocalAlloc(LPTR, (wcslen(wszPhysicalPath)+1+wcslen(L"\\")+wcslen(CEP_DLL_NAME)) * sizeof(WCHAR));
  1452. _JumpIfOutOfMemory(hr, error, wszFullPhysicalPath);
  1453. wcscpy(wszFullPhysicalPath, wszPhysicalPath);
  1454. wcscat(wszFullPhysicalPath, L"\\");
  1455. wcscat(wszFullPhysicalPath, CEP_DLL_NAME);
  1456. //enable the ISAPI Extension on IIS
  1457. hr=IsISAPIExtensionEnabled(wszFullPhysicalPath, fISAPIEnabled);
  1458. //do not respond to error for backward compatibility of previous IDS build
  1459. if((S_OK == hr) && (!fISAPIEnabled))
  1460. {
  1461. hr=EnableISAPIExtension(wszFullPhysicalPath, &fEnabled);
  1462. _JumpIfError(hr, error, "EnableISAPIExtension");
  1463. }
  1464. // Create an instance of the metabase object
  1465. hr=CoCreateInstance(
  1466. CLSID_MSAdminBase,
  1467. NULL,
  1468. CLSCTX_ALL,
  1469. IID_IMSAdminBase,
  1470. (void **) &pIMeta);
  1471. _JumpIfError(hr, error, "CoCreateInstance(CLSID_MSAdminBase)");
  1472. // open the top level
  1473. hr=vrOpenRoot(pIMeta, FALSE/*not read-only*/, gc_wszBaseRoot, &hMetaRoot);
  1474. _JumpIfError(hr, error, "vrOpenRoot");
  1475. // Add new VDir called gc_wszVRootName
  1476. __try {
  1477. hr=pIMeta->AddKey(hMetaRoot, wszRelativeVirtualPath);
  1478. } _TrapException(hr);
  1479. if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)==hr) {
  1480. // That's fine.
  1481. _IgnoreError(hr, "AddKey");
  1482. } else {
  1483. _JumpIfErrorStr(hr, error, "AddKey", wszRelativeVirtualPath);
  1484. }
  1485. // close the root key
  1486. __try {
  1487. hr=pIMeta->CloseKey(hMetaRoot);
  1488. } _TrapException(hr);
  1489. hMetaRoot=NULL;
  1490. _JumpIfError(hr, error, "CloseKey");
  1491. // Open the new VDir
  1492. __try {
  1493. hr=pIMeta->OpenKey(
  1494. METADATA_MASTER_ROOT_HANDLE,
  1495. wszFullVirtualPath,
  1496. METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
  1497. 1000,
  1498. &hMetaKey);
  1499. } _TrapException(hr);
  1500. _JumpIfErrorStr(hr, error, "OpenKey", wszFullVirtualPath);
  1501. // Set the physical path for this VDir
  1502. // virtual root path
  1503. mr.dwMDIdentifier=MD_VR_PATH;
  1504. mr.dwMDAttributes=METADATA_INHERIT;
  1505. mr.dwMDUserType=IIS_MD_UT_FILE;
  1506. mr.dwMDDataType=STRING_METADATA;
  1507. mr.dwMDDataLen=(wcslen(wszPhysicalPath)+1)*sizeof(WCHAR);
  1508. mr.pbMDData=(BYTE *)(wszPhysicalPath);
  1509. __try {
  1510. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1511. } _TrapException(hr);
  1512. _JumpIfError(hr, error, "SetData");
  1513. // access permissions on VRoots: read & execute
  1514. dwAccessPerms=MD_ACCESS_EXECUTE | MD_ACCESS_READ;
  1515. mr.dwMDIdentifier=MD_ACCESS_PERM;
  1516. mr.dwMDAttributes=METADATA_INHERIT;
  1517. mr.dwMDUserType=IIS_MD_UT_FILE;
  1518. mr.dwMDDataType=DWORD_METADATA;
  1519. mr.dwMDDataLen=sizeof(dwAccessPerms);
  1520. mr.pbMDData=(BYTE *)(&dwAccessPerms);
  1521. __try {
  1522. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1523. } _TrapException(hr);
  1524. _JumpIfError(hr, error, "SetData");
  1525. // indicate that what we created is a vroot - set the key type
  1526. mr.dwMDIdentifier=MD_KEY_TYPE;
  1527. mr.dwMDAttributes=METADATA_NO_ATTRIBUTES;
  1528. mr.dwMDUserType=IIS_MD_UT_SERVER;
  1529. mr.dwMDDataType=STRING_METADATA;
  1530. mr.dwMDDataLen=(wcslen(wszKeyType)+1)*sizeof(WCHAR);
  1531. mr.pbMDData=(BYTE *)(wszKeyType);
  1532. __try {
  1533. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1534. } _TrapException(hr);
  1535. _JumpIfError(hr, error, "SetData");
  1536. // set authentication to be anonymous or NTLM
  1537. dwAuthenticationType=MD_AUTH_ANONYMOUS|MD_AUTH_NT;
  1538. mr.dwMDIdentifier=MD_AUTHORIZATION;
  1539. mr.dwMDAttributes=METADATA_INHERIT;
  1540. mr.dwMDUserType=IIS_MD_UT_FILE;
  1541. mr.dwMDDataType=DWORD_METADATA;
  1542. mr.dwMDDataLen=sizeof(dwAuthenticationType);
  1543. mr.pbMDData=reinterpret_cast<BYTE *>(&dwAuthenticationType);
  1544. __try {
  1545. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1546. } _TrapException(hr);
  1547. _JumpIfError(hr, error, "SetData");
  1548. // set the default document
  1549. mr.dwMDIdentifier=MD_DEFAULT_LOAD_FILE;
  1550. mr.dwMDAttributes=METADATA_NO_ATTRIBUTES;
  1551. mr.dwMDUserType=IIS_MD_UT_FILE;
  1552. mr.dwMDDataType=STRING_METADATA;
  1553. mr.dwMDDataLen=(wcslen(gc_wszCepDllName)+1)*sizeof(WCHAR);
  1554. mr.pbMDData=(BYTE *)(gc_wszCepDllName);
  1555. __try {
  1556. hr=pIMeta->SetData(hMetaKey, L"", &mr);
  1557. } _TrapException(hr);
  1558. _JumpIfError(hr, error, "SetData");
  1559. // done with this key.
  1560. __try {
  1561. hr=pIMeta->CloseKey(hMetaKey);
  1562. } _TrapException(hr);
  1563. hMetaKey=NULL;
  1564. _JumpIfError(hr, error, "CloseKey");
  1565. // Flush out the changes and close
  1566. __try {
  1567. hr=pIMeta->SaveData();
  1568. } _TrapException(hr);
  1569. // _JumpIfError(hr, "SaveData");
  1570. if (FAILED(hr)) {
  1571. _IgnoreError(hr, "SaveData");
  1572. }
  1573. hr=S_OK;
  1574. // Create a 'web application' so that scrdenrl.dll runs in-process
  1575. // Create an instance of the metabase object
  1576. hr=CoCreateInstance(
  1577. CLSID_WamAdmin,
  1578. NULL,
  1579. CLSCTX_ALL,
  1580. IID_IWamAdmin,
  1581. (void **) &pIWam);
  1582. _JumpIfError(hr, error, "CoCreateInstance(CLSID_WamAdmin)");
  1583. // Create the application running in-process
  1584. __try {
  1585. hr=pIWam->AppCreate(wszFullVirtualPath, TRUE);
  1586. } _TrapException(hr);
  1587. _JumpIfError(hr, error, "AppCreate");
  1588. //create an application pool
  1589. hr=CoCreateInstance(
  1590. CLSID_WamAdmin,
  1591. NULL,
  1592. CLSCTX_ALL,
  1593. IID_IIISApplicationAdmin,
  1594. (void **) &pIIISAppAdmin);
  1595. _JumpIfError(hr, error, "CoCreateInstance(IID_IIISApplicationAdmin)");
  1596. hr=pIIISAppAdmin->CreateApplication(wszFullVirtualPath, eAppRunInProc, wszApplicationPool, TRUE);
  1597. if(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS))
  1598. {
  1599. // That's fine since installation can be run multiple times
  1600. _IgnoreError(hr, "CreateApplication");
  1601. }
  1602. else
  1603. {
  1604. _JumpIfErrorStr(hr, error, "CreateApplication", wszFullVirtualPath);
  1605. }
  1606. //update an application pool
  1607. hr=CEPUpdateApplicationPool(fDC, wszApplicationPool, fLocalSystem, wszUserName, wszPassword);
  1608. _JumpIfError(hr, error, "CEPCreateApplicationPool");
  1609. hr=S_OK;
  1610. error:
  1611. if (NULL!=wszFullVirtualPath) {
  1612. LocalFree(wszFullVirtualPath);
  1613. }
  1614. if (NULL!=wszRelativeVirtualPath) {
  1615. LocalFree(wszRelativeVirtualPath);
  1616. }
  1617. if (NULL!=wszPhysicalPath) {
  1618. LocalFree(wszPhysicalPath);
  1619. }
  1620. if (NULL!=wszFullPhysicalPath)
  1621. {
  1622. LocalFree(wszFullPhysicalPath);
  1623. }
  1624. if (NULL!=hMetaKey) {
  1625. HRESULT hr2;
  1626. __try {
  1627. hr2=pIMeta->CloseKey(hMetaKey);
  1628. } _TrapException(hr2);
  1629. _TeardownError(hr, hr2, "CloseKey");
  1630. }
  1631. if (NULL!=hMetaRoot) {
  1632. HRESULT hr2;
  1633. __try {
  1634. hr2=pIMeta->CloseKey(hMetaRoot);
  1635. } _TrapException(hr2);
  1636. _TeardownError(hr, hr2, "CloseKey");
  1637. }
  1638. if (NULL!=pIIISAppAdmin) {
  1639. pIIISAppAdmin->Release();
  1640. }
  1641. if (NULL!=pIWam) {
  1642. pIWam->Release();
  1643. }
  1644. if (NULL!=pIMeta) {
  1645. pIMeta->Release();
  1646. }
  1647. return hr;
  1648. }
  1649. //--------------------------------------------------------------------
  1650. HRESULT CepStopService(IN DWORD dwServicePeriod, const WCHAR * wszServiceName, BOOL * pbWasRunning)
  1651. {
  1652. HRESULT hr;
  1653. SERVICE_STATUS ss;
  1654. unsigned int nAttempts;
  1655. // must be cleaned up
  1656. SC_HANDLE hSCManager=NULL;
  1657. SC_HANDLE hService=NULL;
  1658. // initialize out parameters
  1659. *pbWasRunning=FALSE;
  1660. // talk to the service manager
  1661. hSCManager=OpenSCManagerW(NULL/*machine*/, NULL/*db*/, SC_MANAGER_ALL_ACCESS);
  1662. if (NULL==hSCManager) {
  1663. hr=HRESULT_FROM_WIN32(GetLastError());
  1664. _JumpError(hr, error, "OpenSCManager");
  1665. }
  1666. // get to the service
  1667. hService=OpenServiceW(hSCManager, wszServiceName, SERVICE_ALL_ACCESS);
  1668. if (NULL==hService) {
  1669. hr=HRESULT_FROM_WIN32(GetLastError());
  1670. _JumpErrorStr(hr, error, "OpenService", wszServiceName);
  1671. }
  1672. // see if the service is running
  1673. if (FALSE==QueryServiceStatus(hService, &ss)) {
  1674. hr=HRESULT_FROM_WIN32(GetLastError());
  1675. _JumpErrorStr(hr, error, "QueryServiceStatus", wszServiceName);
  1676. }
  1677. if (SERVICE_STOPPED!=ss.dwCurrentState && SERVICE_STOP_PENDING!=ss.dwCurrentState) {
  1678. *pbWasRunning=TRUE;
  1679. }
  1680. // begin the service stopping loop
  1681. for (nAttempts=0; SERVICE_STOPPED!=ss.dwCurrentState && nAttempts<dwServicePeriod; nAttempts++) {
  1682. // service is running, must stop it.
  1683. if (SERVICE_STOP_PENDING!=ss.dwCurrentState) {
  1684. if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss)) {
  1685. hr=HRESULT_FROM_WIN32(GetLastError());
  1686. _JumpErrorStr(hr, error, "ControlService(Stop)", wszServiceName);
  1687. }
  1688. }
  1689. // wait a little while
  1690. Sleep(1000);
  1691. // see if the service is running
  1692. if (FALSE==QueryServiceStatus(hService, &ss)) {
  1693. hr=HRESULT_FROM_WIN32(GetLastError());
  1694. _JumpErrorStr(hr, error, "QueryServiceStatus", wszServiceName);
  1695. }
  1696. }
  1697. if (nAttempts>=dwServicePeriod) {
  1698. // it never stopped
  1699. hr=HRESULT_FROM_WIN32(ERROR_SERVICE_REQUEST_TIMEOUT);
  1700. _JumpErrorStr(hr, error, "Stopping service", wszServiceName);
  1701. }
  1702. hr=S_OK;
  1703. error:
  1704. if (NULL!=hService) {
  1705. CloseServiceHandle(hService);
  1706. }
  1707. if (NULL!=hSCManager) {
  1708. CloseServiceHandle(hSCManager);
  1709. }
  1710. return hr;
  1711. }
  1712. //--------------------------------------------------------------------
  1713. HRESULT CepStartService(const WCHAR * wszServiceName)
  1714. {
  1715. HRESULT hr;
  1716. SERVICE_STATUS ss;
  1717. // must be cleaned up
  1718. SC_HANDLE hSCManager=NULL;
  1719. SC_HANDLE hService=NULL;
  1720. // talk to the service manager
  1721. hSCManager=OpenSCManagerW(NULL/*machine*/, NULL/*db*/, SC_MANAGER_ALL_ACCESS);
  1722. if (NULL==hSCManager) {
  1723. hr=HRESULT_FROM_WIN32(GetLastError());
  1724. _JumpError(hr, error, "OpenSCManager");
  1725. }
  1726. // get to the service
  1727. hService=OpenServiceW(hSCManager, wszServiceName, SERVICE_ALL_ACCESS);
  1728. if (NULL==hService) {
  1729. hr=HRESULT_FROM_WIN32(GetLastError());
  1730. _JumpErrorStr(hr, error, "OpenService", wszServiceName);
  1731. }
  1732. // now, start the service.
  1733. if (FALSE==StartServiceW(hService, 0 /*num args*/, NULL /*args*/)) {
  1734. hr=HRESULT_FROM_WIN32(GetLastError());
  1735. _JumpError(hr, error, "OpenSCManager");
  1736. }
  1737. hr=S_OK;
  1738. error:
  1739. if (NULL!=hService) {
  1740. CloseServiceHandle(hService);
  1741. }
  1742. if (NULL!=hSCManager) {
  1743. CloseServiceHandle(hSCManager);
  1744. }
  1745. return hr;
  1746. }
  1747. //--------------------------------------------------------------------
  1748. BOOL IsGoodCaInstalled(void)
  1749. {
  1750. HRESULT hr;
  1751. DWORD dwError;
  1752. DWORD dwType;
  1753. DWORD dwDataSize;
  1754. DWORD dwSetupStatus;
  1755. BOOL bResult=FALSE;
  1756. DWORD dwCAType;
  1757. // must be cleaned up
  1758. HKEY hCurConfig=NULL;
  1759. // get the current configuration
  1760. hr=OpenCurrentCAConfig(&hCurConfig);
  1761. _JumpIfError(hr, error, "OpenCurrentCAConfig");
  1762. // get value SetupStatus
  1763. dwDataSize=sizeof(dwSetupStatus);
  1764. dwError=RegQueryValueExW(hCurConfig, wszREGSETUPSTATUS, NULL, &dwType, (BYTE *)&dwSetupStatus, &dwDataSize);
  1765. if (ERROR_SUCCESS!=dwError) {
  1766. hr=HRESULT_FROM_WIN32(dwError);
  1767. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGSETUPSTATUS);
  1768. }
  1769. _Verify(REG_DWORD==dwType, hr, error);
  1770. _Verify(sizeof(dwSetupStatus)==dwDataSize, hr, error);
  1771. // make sure we have all the needed components set up
  1772. _Verify(0!=(dwSetupStatus&SETUP_SERVER_FLAG), hr, error);
  1773. _Verify(0!=(dwSetupStatus&SETUP_CLIENT_FLAG), hr, error);
  1774. _Verify(0==(dwSetupStatus&SETUP_SUSPEND_FLAG), hr, error);
  1775. // Check the CA Type too
  1776. dwDataSize=sizeof(dwCAType);
  1777. dwError=RegQueryValueExW(hCurConfig, wszREGCATYPE, NULL, &dwType, (BYTE *)&dwCAType, &dwDataSize);
  1778. if (ERROR_SUCCESS!=dwError) {
  1779. hr=HRESULT_FROM_WIN32(dwError);
  1780. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGCATYPE);
  1781. }
  1782. _Verify(REG_DWORD==dwType, hr, error);
  1783. _Verify(sizeof(dwCAType)==dwDataSize, hr, error);
  1784. _Verify(dwCAType<=ENUM_UNKNOWN_CA, hr, error);
  1785. bResult=TRUE;
  1786. error:
  1787. if (NULL!=hCurConfig) {
  1788. RegCloseKey(hCurConfig);
  1789. }
  1790. return bResult;
  1791. }
  1792. //--------------------------------------------------------------------
  1793. BOOL IsServiceRunning(IN const WCHAR * wszServiceName)
  1794. {
  1795. HRESULT hr;
  1796. SERVICE_STATUS ss;
  1797. BOOL bResult=FALSE;
  1798. // must be cleaned up
  1799. SC_HANDLE hSCManager=NULL;
  1800. SC_HANDLE hService=NULL;
  1801. // talk to the service manager
  1802. hSCManager=OpenSCManagerW(NULL/*machine*/, NULL/*db*/, SC_MANAGER_ALL_ACCESS);
  1803. if (NULL==hSCManager) {
  1804. hr=HRESULT_FROM_WIN32(GetLastError());
  1805. _JumpError(hr, error, "OpenSCManager");
  1806. }
  1807. // get to the service
  1808. hService=OpenServiceW(hSCManager, wszServiceName, SERVICE_ALL_ACCESS);
  1809. if (NULL==hService) {
  1810. hr=HRESULT_FROM_WIN32(GetLastError());
  1811. _JumpErrorStr(hr, error, "OpenService", wszSERVICE_NAME);
  1812. }
  1813. // see if the service is running
  1814. if (FALSE==QueryServiceStatus(hService, &ss)) {
  1815. hr=HRESULT_FROM_WIN32(GetLastError());
  1816. _JumpErrorStr(hr, error, "QueryServiceStatus", wszSERVICE_NAME);
  1817. }
  1818. _Verify(SERVICE_RUNNING==ss.dwCurrentState, hr, error)
  1819. _Verify(0!=(SERVICE_ACCEPT_PAUSE_CONTINUE&ss.dwControlsAccepted), hr, error);
  1820. // looks like it is
  1821. bResult=TRUE;
  1822. error:
  1823. if (NULL!=hService) {
  1824. CloseServiceHandle(hService);
  1825. }
  1826. if (NULL!=hSCManager) {
  1827. CloseServiceHandle(hSCManager);
  1828. }
  1829. return bResult;
  1830. }
  1831. //--------------------------------------------------------------------
  1832. BOOL IsCaRunning(void)
  1833. {
  1834. return IsServiceRunning(wszSERVICE_NAME);
  1835. }
  1836. //--------------------------------------------------------------------
  1837. HRESULT EnrollForRACertificates(
  1838. IN const WCHAR * wszDistinguishedName,
  1839. IN const WCHAR * wszSignCSPName,
  1840. IN DWORD dwSignCSPType,
  1841. IN DWORD dwSignKeySize,
  1842. IN const WCHAR * wszEncryptCSPName,
  1843. IN DWORD dwEncryptCSPType,
  1844. IN DWORD dwEncryptKeySize,
  1845. IN SID *psidAccount)
  1846. {
  1847. HRESULT hr;
  1848. hr=EnrollForRACert(
  1849. wszDistinguishedName,
  1850. wszSignCSPName,
  1851. dwSignCSPType,
  1852. dwSignKeySize,
  1853. AT_SIGNATURE,
  1854. wszCERTTYPE_ENROLLMENT_AGENT_OFFLINE,
  1855. psidAccount);
  1856. _JumpIfError(hr, error, "EnrollForRACert(OfflineEnrollmentAgent)");
  1857. hr=EnrollForRACert(
  1858. wszDistinguishedName,
  1859. wszEncryptCSPName,
  1860. dwEncryptCSPType,
  1861. dwEncryptKeySize,
  1862. AT_KEYEXCHANGE,
  1863. wszCERTTYPE_CEP_ENCRYPTION,
  1864. psidAccount);
  1865. _JumpIfError(hr, error, "EnrollForRACert(CepEncryption)");
  1866. // all done
  1867. hr=S_OK;
  1868. error:
  1869. return hr;
  1870. }
  1871. //--------------------------------------------------------------------
  1872. HRESULT DoCertSrvRegChanges(IN BOOL bDisablePendingFirst)
  1873. {
  1874. HRESULT hr;
  1875. DWORD dwDataSize;
  1876. DWORD dwType;
  1877. DWORD dwError;
  1878. WCHAR * wszTravel;
  1879. DWORD dwNewDataSize;
  1880. DWORD dwRequestDisposition;
  1881. bool bSubjectTemplateAlreadyModified=false;
  1882. // must be cleaned up
  1883. HKEY hCaConfig=NULL;
  1884. WCHAR * mwszSubjectTemplate=NULL;
  1885. HKEY hPolicyModules=NULL;
  1886. HKEY hCurPolicy=NULL;
  1887. WCHAR * wszCurPolicy=NULL;
  1888. // get the current CA config key
  1889. hr=OpenCurrentCAConfig(&hCaConfig);
  1890. _JumpIfError(hr, error, "OpenCurrentCAConfig");
  1891. //
  1892. // add strings to the SubjectTemplate value
  1893. //
  1894. // get the size of the Multi_SZ
  1895. dwDataSize=0;
  1896. dwError=RegQueryValueExW(hCaConfig, wszREGSUBJECTTEMPLATE, NULL, &dwType, NULL, &dwDataSize);
  1897. if (ERROR_SUCCESS!=dwError) {
  1898. hr=HRESULT_FROM_WIN32(dwError);
  1899. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGSUBJECTTEMPLATE);
  1900. }
  1901. _Verify(REG_MULTI_SZ==dwType, hr, error);
  1902. // add exra space for the strings we want to add
  1903. dwDataSize+=(wcslen(wszPROPUNSTRUCTUREDNAME)+1)*sizeof(WCHAR);
  1904. dwDataSize+=(wcslen(wszPROPUNSTRUCTUREDADDRESS)+1)*sizeof(WCHAR);
  1905. dwDataSize+=(wcslen(wszPROPDEVICESERIALNUMBER)+1)*sizeof(WCHAR);
  1906. dwNewDataSize=dwDataSize;
  1907. mwszSubjectTemplate=(WCHAR *)LocalAlloc(LPTR, dwDataSize);
  1908. _JumpIfOutOfMemory(hr, error, mwszSubjectTemplate);
  1909. // get the Multi_SZ
  1910. dwError=RegQueryValueExW(hCaConfig, wszREGSUBJECTTEMPLATE, NULL, &dwType, (BYTE *)mwszSubjectTemplate, &dwDataSize);
  1911. if (ERROR_SUCCESS!=dwError) {
  1912. hr=HRESULT_FROM_WIN32(dwError);
  1913. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGSUBJECTTEMPLATE);
  1914. }
  1915. _Verify(REG_MULTI_SZ==dwType, hr, error);
  1916. // walk to the end
  1917. for (wszTravel=mwszSubjectTemplate; 0!=wcslen(wszTravel); wszTravel+=wcslen(wszTravel)+1) {
  1918. // while walking, make sure we haven't added these strings already
  1919. if (0==wcscmp(wszTravel, wszPROPUNSTRUCTUREDNAME)) {
  1920. bSubjectTemplateAlreadyModified=true;
  1921. break;
  1922. }
  1923. }
  1924. // we are now pointing at the last '\0' in the string, which we will overwrite
  1925. // did we do this already? If so, don't do it again.
  1926. if (false==bSubjectTemplateAlreadyModified) {
  1927. // add the strings
  1928. wcscpy(wszTravel, wszPROPUNSTRUCTUREDNAME);
  1929. wszTravel+=wcslen(wszTravel)+1;
  1930. wcscpy(wszTravel, wszPROPUNSTRUCTUREDADDRESS);
  1931. wszTravel+=wcslen(wszTravel)+1;
  1932. wcscpy(wszTravel, wszPROPDEVICESERIALNUMBER);
  1933. wszTravel+=wcslen(wszTravel)+1;
  1934. // add extra terminator
  1935. wszTravel[0]='\0';
  1936. // save the Multi_SZ
  1937. dwError=RegSetValueExW(hCaConfig, wszREGSUBJECTTEMPLATE, NULL, dwType, (BYTE *)mwszSubjectTemplate, dwNewDataSize);
  1938. if (ERROR_SUCCESS!=dwError) {
  1939. hr=HRESULT_FROM_WIN32(dwError);
  1940. _JumpErrorStr(hr, error, "RegSetValueExW", wszREGSUBJECTTEMPLATE);
  1941. }
  1942. }
  1943. //
  1944. // remove the Pending First flag from the current policy settings
  1945. //
  1946. if (FALSE!=bDisablePendingFirst) {
  1947. // open the current policy
  1948. dwError=RegOpenKeyExW(hCaConfig, wszREGKEYPOLICYMODULES, NULL, KEY_READ, &hPolicyModules);
  1949. if (ERROR_SUCCESS!=dwError) {
  1950. hr=HRESULT_FROM_WIN32(dwError);
  1951. _JumpErrorStr(hr, error, "RegOpenKeyExW", wszREGKEYPOLICYMODULES);
  1952. }
  1953. hr=GetRegString(hPolicyModules, wszREGACTIVE, &wszCurPolicy);
  1954. _JumpIfErrorStr(hr, error, "GetRegString", wszREGACTIVE);
  1955. dwError=RegOpenKeyExW(hPolicyModules, wszCurPolicy, NULL, KEY_ALL_ACCESS, &hCurPolicy);
  1956. if (ERROR_SUCCESS!=dwError) {
  1957. hr=HRESULT_FROM_WIN32(dwError);
  1958. _JumpErrorStr(hr, error, "RegOpenKeyExW", wszCurPolicy);
  1959. }
  1960. // read the value
  1961. dwDataSize=sizeof(dwRequestDisposition);
  1962. dwError=RegQueryValueExW(hCurPolicy, wszREGREQUESTDISPOSITION, NULL, &dwType, (BYTE *)&dwRequestDisposition, &dwDataSize);
  1963. if (ERROR_SUCCESS!=dwError) {
  1964. hr=HRESULT_FROM_WIN32(dwError);
  1965. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGREQUESTDISPOSITION);
  1966. }
  1967. _Verify(REG_DWORD==dwType, hr, error);
  1968. _Verify(sizeof(dwRequestDisposition)==dwDataSize, hr, error);
  1969. // clear the pending-first flag
  1970. dwRequestDisposition&=~REQDISP_PENDINGFIRST;
  1971. // save the vale
  1972. dwError=RegSetValueExW(hCurPolicy, wszREGREQUESTDISPOSITION, NULL, dwType, (BYTE *)&dwRequestDisposition, dwDataSize);
  1973. if (ERROR_SUCCESS!=dwError) {
  1974. hr=HRESULT_FROM_WIN32(dwError);
  1975. _JumpErrorStr(hr, error, "RegSetValueExW", wszREGREQUESTDISPOSITION);
  1976. }
  1977. }
  1978. // all done
  1979. hr=S_OK;
  1980. error:
  1981. if (NULL!=wszCurPolicy) {
  1982. LocalFree(wszCurPolicy);
  1983. }
  1984. if (NULL!=hCurPolicy) {
  1985. RegCloseKey(hCurPolicy);
  1986. }
  1987. if (NULL!=hPolicyModules) {
  1988. RegCloseKey(hPolicyModules);
  1989. }
  1990. if (NULL!=mwszSubjectTemplate) {
  1991. LocalFree(mwszSubjectTemplate);
  1992. }
  1993. if (NULL!=hCaConfig) {
  1994. RegCloseKey(hCaConfig);
  1995. }
  1996. return hr;
  1997. }
  1998. //--------------------------------------------------------------------
  1999. HRESULT GetCaType(OUT ENUM_CATYPES * pCAType)
  2000. {
  2001. HRESULT hr;
  2002. DWORD dwDataSize;
  2003. DWORD dwCAType;
  2004. DWORD dwType;
  2005. DWORD dwError;
  2006. // must be cleaned up
  2007. HKEY hCaConfig=NULL;
  2008. // init out params
  2009. *pCAType=ENUM_UNKNOWN_CA;
  2010. // get the current CA config key
  2011. hr=OpenCurrentCAConfig(&hCaConfig);
  2012. _JumpIfError(hr, error, "OpenCurrentCAConfig");
  2013. // read the CA Type
  2014. dwDataSize=sizeof(dwCAType);
  2015. dwError=RegQueryValueExW(hCaConfig, wszREGCATYPE, NULL, &dwType, (BYTE *)&dwCAType, &dwDataSize);
  2016. if (ERROR_SUCCESS!=dwError) {
  2017. hr=HRESULT_FROM_WIN32(dwError);
  2018. _JumpErrorStr(hr, error, "RegQueryValueExW", wszREGCATYPE);
  2019. }
  2020. _Verify(REG_DWORD==dwType, hr, error);
  2021. _Verify(sizeof(dwCAType)==dwDataSize, hr, error);
  2022. _Verify(dwCAType<=ENUM_UNKNOWN_CA, hr, error);
  2023. // all done
  2024. hr=S_OK;
  2025. *pCAType=(ENUM_CATYPES)dwCAType;
  2026. error:
  2027. if (NULL!=hCaConfig) {
  2028. RegCloseKey(hCaConfig);
  2029. }
  2030. return hr;
  2031. }
  2032. //--------------------------------------------------------------------
  2033. BOOL IsUserInAdminGroup(IN BOOL bEnterprise)
  2034. {
  2035. BOOL bIsMember=FALSE;
  2036. HRESULT hr;
  2037. SID_IDENTIFIER_AUTHORITY siaNtAuthority=SECURITY_NT_AUTHORITY;
  2038. // must be cleaned up
  2039. HANDLE hAccessToken=NULL;
  2040. HANDLE hDupToken=NULL;
  2041. SID * psidLocalAdmins=NULL;
  2042. SID * psidEntAdmins=NULL;
  2043. SID * psidRootDomAdmins=NULL;
  2044. // Get the access token for this process
  2045. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, &hAccessToken)) {
  2046. hr=HRESULT_FROM_WIN32(GetLastError());
  2047. _JumpError(hr, error, "OpenProcessToken");
  2048. }
  2049. // CheckTokenMembership must operate on impersonation token, so make one
  2050. if (!DuplicateToken(hAccessToken, SecurityIdentification, &hDupToken)) {
  2051. hr=HRESULT_FROM_WIN32(GetLastError());
  2052. _JumpError(hr, error, "DuplicateToken");
  2053. }
  2054. if (bEnterprise) {
  2055. // see if the user is a member of the [domain]\Enmterprised Administrators group
  2056. BOOL bIsEntAdmin=FALSE;
  2057. BOOL bIsRootDomAdmin=FALSE;
  2058. // get the Enterpise Admin SID
  2059. hr=GetEntAdminSid(&psidEntAdmins);
  2060. _JumpIfError(hr, error, "GetEntAdminSid");
  2061. // check for membership
  2062. if (!CheckTokenMembership(hDupToken, psidEntAdmins, &bIsEntAdmin)) {
  2063. hr=HRESULT_FROM_WIN32(GetLastError());
  2064. _JumpError(hr, error, "CheckTokenMembership");
  2065. }
  2066. // get the root Domain Admin SID
  2067. hr=GetRootDomAdminSid(&psidRootDomAdmins);
  2068. _JumpIfError(hr, error, "GetRootDomAdminSid");
  2069. // check for membership
  2070. if (!CheckTokenMembership(hDupToken, psidRootDomAdmins, &bIsRootDomAdmin)) {
  2071. hr=HRESULT_FROM_WIN32(GetLastError());
  2072. _JumpError(hr, error, "CheckTokenMembership");
  2073. }
  2074. // either one will do
  2075. bIsMember=(bIsEntAdmin || bIsRootDomAdmin);
  2076. } else {
  2077. // see if the user is a member of the BUILTIN\Administrators group
  2078. // get the well-known SID
  2079. if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
  2080. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  2081. 0, 0, 0, 0, 0, 0, (void **)&psidLocalAdmins))
  2082. {
  2083. hr=HRESULT_FROM_WIN32(GetLastError());
  2084. _JumpError(hr, error, "AllocateAndInitializeSid");
  2085. }
  2086. // check for membership
  2087. if (!CheckTokenMembership(hDupToken, psidLocalAdmins, &bIsMember)) {
  2088. hr=HRESULT_FROM_WIN32(GetLastError());
  2089. _JumpError(hr, error, "CheckTokenMembership");
  2090. }
  2091. }
  2092. error:
  2093. if (NULL!=hAccessToken) {
  2094. CloseHandle(hAccessToken);
  2095. }
  2096. if (NULL!=hDupToken) {
  2097. CloseHandle(hDupToken);
  2098. }
  2099. if (NULL!=psidLocalAdmins) {
  2100. FreeSid(psidLocalAdmins);
  2101. }
  2102. if (NULL!=psidEntAdmins) {
  2103. LocalFree(psidEntAdmins);
  2104. }
  2105. if (NULL!=psidRootDomAdmins) {
  2106. LocalFree(psidRootDomAdmins);
  2107. }
  2108. return bIsMember;
  2109. }
  2110. //--------------------------------------------------------------------
  2111. HRESULT DoCertSrvEnterpriseChanges(SID * psidAccount)
  2112. {
  2113. HRESULT hr;
  2114. DWORD dwFlags;
  2115. BOOL bSDChanged1;
  2116. BOOL bSDChanged2;
  2117. BOOL bSDChanged3;
  2118. BOOL bSDChanged4;
  2119. // must be cleaned up
  2120. HCERTTYPE hEAOTemplate=NULL;
  2121. HCERTTYPE hCETemplate=NULL;
  2122. HCERTTYPE hIIOTemplate=NULL;
  2123. PSECURITY_DESCRIPTOR pSD=NULL;
  2124. WCHAR * wszCAName=NULL;
  2125. HCAINFO hCA=NULL;
  2126. SID * psidEntAdmins=NULL;
  2127. SID * psidRootDomAdmins=NULL;
  2128. SID * psidThisComputer=NULL;
  2129. //
  2130. // first, make sure the CA will issue the cert templates we want
  2131. //
  2132. // get the sanitized CA name
  2133. hr=GetCADsName(&wszCAName);
  2134. _JumpIfError(hr, error, "GetCADsName");
  2135. // get the CA (in the DS)
  2136. hr=CAFindByName(wszCAName, NULL, 0, &hCA);
  2137. _JumpIfErrorStr(hr, error, "CAFindCaByName", wszCAName);
  2138. // check the flags to confirm it supports templates
  2139. hr=CAGetCAFlags(hCA, &dwFlags);
  2140. _JumpIfError(hr, error, "CAGetCAFlags");
  2141. _Verify(0==(dwFlags&CA_FLAG_NO_TEMPLATE_SUPPORT), hr, error);
  2142. // get the enrollment agent offline template
  2143. hr=CAFindCertTypeByName(wszCERTTYPE_ENROLLMENT_AGENT_OFFLINE, NULL, CT_ENUM_USER_TYPES, &hEAOTemplate);
  2144. _JumpIfErrorStr(hr, error, "CAFindCertTypeByName", wszCERTTYPE_ENROLLMENT_AGENT_OFFLINE);
  2145. // make sure that the CA will issue this template
  2146. hr=CAAddCACertificateType(hCA, hEAOTemplate);
  2147. _JumpIfErrorStr(hr, error, "CAAddCACertificateType", wszCERTTYPE_ENROLLMENT_AGENT_OFFLINE);
  2148. // get the CEP encryption template
  2149. hr=CAFindCertTypeByName(wszCERTTYPE_CEP_ENCRYPTION, NULL, CT_ENUM_MACHINE_TYPES, &hCETemplate);
  2150. _JumpIfErrorStr(hr, error, "CAFindCertTypeByName", wszCERTTYPE_CEP_ENCRYPTION);
  2151. // make sure that the CA will issue this template
  2152. hr=CAAddCACertificateType(hCA, hCETemplate);
  2153. _JumpIfErrorStr(hr, error, "CAAddCACertificateType", wszCERTTYPE_CEP_ENCRYPTION);
  2154. // get the IPSEC Intermediate offline template
  2155. hr=CAFindCertTypeByName(wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE, NULL, CT_ENUM_MACHINE_TYPES, &hIIOTemplate);
  2156. _JumpIfErrorStr(hr, error, "CAFindCertTypeByName", wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE);
  2157. // make sure that the CA will issue this template
  2158. hr=CAAddCACertificateType(hCA, hIIOTemplate);
  2159. _JumpIfErrorStr(hr, error, "CAAddCACertificateType", wszCERTTYPE_IPSEC_INTERMEDIATE_OFFLINE);
  2160. // make sure that all gets written.
  2161. hr=CAUpdateCA(hCA);
  2162. _JumpIfError(hr, error, "CAUpdateCA");
  2163. //
  2164. // now, check the ACLs
  2165. //
  2166. // get the Enterpise Admin SID
  2167. hr=GetEntAdminSid(&psidEntAdmins);
  2168. _JumpIfError(hr, error, "GetEntAdminSid");
  2169. // get the root Domain Admin SID
  2170. hr=GetRootDomAdminSid(&psidRootDomAdmins);
  2171. _JumpIfError(hr, error, "GetRootDomAdminSid");
  2172. // get this computer's SID
  2173. hr=GetThisComputerSid(&psidThisComputer);
  2174. _JumpIfError(hr, error, "GetThisComputerSid");
  2175. // enrollment agent offline template needs Enterprise Admins and root Domain Admins
  2176. hr=CACertTypeGetSecurity(hEAOTemplate, &pSD);
  2177. _JumpIfError(hr, error, "CACertTypeGetSecurity");
  2178. hr=ConfirmAccess(&pSD, psidEntAdmins, &bSDChanged1);
  2179. _JumpIfError(hr, error, "ConfirmAccess");
  2180. hr=ConfirmAccess(&pSD, psidRootDomAdmins, &bSDChanged2);
  2181. _JumpIfError(hr, error, "ConfirmAccess");
  2182. if (bSDChanged1 || bSDChanged2) {
  2183. hr=CACertTypeSetSecurity(hEAOTemplate, pSD);
  2184. _JumpIfError(hr, error, "CACertTypeSetSecurity");
  2185. hr=CAUpdateCertType(hEAOTemplate);
  2186. _JumpIfError(hr, error, "CAUpdateCertType");
  2187. }
  2188. LocalFree(pSD);
  2189. pSD=NULL;
  2190. // CEP encryption template needs Enterprise Admins and root Domain Admins
  2191. hr=CACertTypeGetSecurity(hCETemplate, &pSD);
  2192. _JumpIfError(hr, error, "CACertTypeGetSecurity");
  2193. hr=ConfirmAccess(&pSD, psidEntAdmins, &bSDChanged1);
  2194. _JumpIfError(hr, error, "ConfirmAccess");
  2195. hr=ConfirmAccess(&pSD, psidRootDomAdmins, &bSDChanged2);
  2196. _JumpIfError(hr, error, "ConfirmAccess");
  2197. if (bSDChanged1 || bSDChanged2) {
  2198. hr=CACertTypeSetSecurity(hCETemplate, pSD);
  2199. _JumpIfError(hr, error, "CACertTypeSetSecurity");
  2200. hr=CAUpdateCertType(hCETemplate);
  2201. _JumpIfError(hr, error, "CAUpdateCertType");
  2202. }
  2203. LocalFree(pSD);
  2204. pSD=NULL;
  2205. // IPSEC Intermediate offline template needs Enterprise Admins and root Domain Admins and the current machine
  2206. hr=CACertTypeGetSecurity(hIIOTemplate, &pSD);
  2207. _JumpIfError(hr, error, "CACertTypeGetSecurity");
  2208. hr=ConfirmAccess(&pSD, psidEntAdmins, &bSDChanged1);
  2209. _JumpIfError(hr, error, "ConfirmAccess");
  2210. hr=ConfirmAccess(&pSD, psidRootDomAdmins, &bSDChanged2);
  2211. _JumpIfError(hr, error, "ConfirmAccess");
  2212. hr=ConfirmAccess(&pSD, psidThisComputer, &bSDChanged3);
  2213. _JumpIfError(hr, error, "ConfirmAccess");
  2214. //if a service account if used, add the account to the template
  2215. if(psidAccount)
  2216. {
  2217. hr=ConfirmAccess(&pSD, psidAccount, &bSDChanged4);
  2218. _JumpIfError(hr, error, "ConfirmAccess");
  2219. }
  2220. else
  2221. {
  2222. bSDChanged4=FALSE;
  2223. }
  2224. if (bSDChanged1 || bSDChanged2 || bSDChanged3 || bSDChanged4) {
  2225. hr=CACertTypeSetSecurity(hIIOTemplate, pSD);
  2226. _JumpIfError(hr, error, "CACertTypeSetSecurity");
  2227. hr=CAUpdateCertType(hIIOTemplate);
  2228. _JumpIfError(hr, error, "CAUpdateCertType");
  2229. }
  2230. hr=S_OK;
  2231. error:
  2232. if (NULL!=psidThisComputer) {
  2233. LocalFree(psidThisComputer);
  2234. }
  2235. if (NULL!=psidEntAdmins) {
  2236. LocalFree(psidEntAdmins);
  2237. }
  2238. if (NULL!=psidRootDomAdmins) {
  2239. LocalFree(psidRootDomAdmins);
  2240. }
  2241. if (NULL!=pSD) {
  2242. LocalFree(pSD);
  2243. }
  2244. if (NULL!=hEAOTemplate) {
  2245. CACloseCertType(hEAOTemplate);
  2246. }
  2247. if (NULL!=hCETemplate) {
  2248. CACloseCertType(hCETemplate);
  2249. }
  2250. if (NULL!=hIIOTemplate) {
  2251. CACloseCertType(hIIOTemplate);
  2252. }
  2253. if (NULL!=wszCAName) {
  2254. LocalFree(wszCAName);
  2255. }
  2256. if (NULL!=hCA) {
  2257. CACloseCA(hCA);
  2258. }
  2259. return hr;
  2260. }