Source code of Windows XP (NT5)
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.

1266 lines
29 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: cainfop.cpp
  7. //
  8. // Contents:
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <certca.h>
  14. #include <lm.h>
  15. #include <cainfop.h>
  16. #include <cainfoc.h>
  17. #include <winldap.h>
  18. #include <ntlsa.h>
  19. #include <dsgetdc.h>
  20. #include <accctrl.h>
  21. #include "certacl.h"
  22. #include "oidmgr.h"
  23. #include "csldap.h"
  24. #define __dwFILE__ __dwFILE_CERTCLIB_CAINFOP_CPP__
  25. CRITICAL_SECTION g_csDomainSidCache;
  26. extern BOOL g_fInitDone;
  27. //we only keep one copy of the localSystem's sid
  28. PSID g_pLocalSid=NULL;
  29. #define DOMAIN_SID_CACHE_INC 10
  30. typedef struct _DOMAIN_SID_CACHE
  31. {
  32. LPWSTR wszDomain;
  33. PSID pSid;
  34. } DOMAIN_SID_CACHE, *PDOMAIN_SID_CACHE;
  35. PDOMAIN_SID_CACHE g_DomainSidCache = NULL;
  36. DWORD g_cDomainSidCache = 0;
  37. DWORD g_cMaxDomainSidCache = 0;
  38. LPWSTR g_pwszEnterpriseRoot = NULL;
  39. DWORD myGetEnterpriseDnsName(OUT LPWSTR *pwszDomain);
  40. HRESULT
  41. CAGetAuthoritativeDomainDn(
  42. IN LDAP* LdapHandle,
  43. OUT CERTSTR *DomainDn,
  44. OUT CERTSTR *ConfigDn
  45. )
  46. /*++
  47. Routine Description:
  48. This routine simply queries the operational attributes for the
  49. domaindn and configdn.
  50. The strings returned by this routine must be freed by the caller
  51. using RtlFreeHeap() using the process heap.
  52. Parameters:
  53. LdapHandle : a valid handle to an ldap session
  54. DomainDn : a pointer to a string to be allocated in this routine
  55. ConfigDn : a pointer to a string to be allocated in this routine
  56. Return Values:
  57. An error from the win32 error space.
  58. ERROR_SUCCESS and
  59. Other operation errors.
  60. --*/
  61. {
  62. HRESULT hr=E_FAIL;
  63. BSTR bstrDomainDN=NULL;
  64. BSTR bstrConfigDN=NULL;
  65. hr=myGetAuthoritativeDomainDn(LdapHandle, &bstrDomainDN, &bstrConfigDN);
  66. if(S_OK != hr)
  67. _JumpError(hr, error, "myGetAuthoritativeDomainDn");
  68. //convert BSTR to CERTSTR
  69. if(DomainDn)
  70. {
  71. (*DomainDn) = CertAllocString(bstrDomainDN);
  72. if(NULL == (*DomainDn))
  73. {
  74. hr=E_OUTOFMEMORY;
  75. _JumpError(hr, error, "CertAllocString");
  76. }
  77. }
  78. if(ConfigDn)
  79. {
  80. (*ConfigDn) = CertAllocString(bstrConfigDN);
  81. if(NULL == (*ConfigDn))
  82. {
  83. hr=E_OUTOFMEMORY;
  84. if(DomainDn)
  85. {
  86. if(*DomainDn)
  87. {
  88. CertFreeString(*DomainDn);
  89. *DomainDn=NULL;
  90. }
  91. }
  92. _JumpError(hr, error, "CertAllocString");
  93. }
  94. }
  95. hr=S_OK;
  96. error:
  97. if(bstrDomainDN)
  98. SysFreeString(bstrDomainDN);
  99. if(bstrConfigDN)
  100. SysFreeString(bstrConfigDN);
  101. return hr;
  102. }
  103. DWORD
  104. DNStoRFC1779Name(WCHAR *rfcDomain,
  105. ULONG *rfcDomainLength,
  106. LPCWSTR dnsDomain)
  107. /*++
  108. Routine Description:
  109. This routine takes the DNS-style name of a domain controller and
  110. contructs the corresponding RFC1779 style name, using the
  111. domainComponent prefix.
  112. Parameters:
  113. rfcDomain - this is the destination string
  114. rfcDomainLength - this is the length in wchars of rfcDomain
  115. dnsDomain - NULL-terminated dns name.
  116. Return Values:
  117. ERROR_SUCCESS if succesful;
  118. ERROR_INSUFFICIENT_BUFFER if there is not enough space in the dst string -
  119. rfcDomainLength will set to number of characters needed.
  120. --*/
  121. {
  122. DWORD WinError = ERROR_SUCCESS;
  123. WCHAR *NextToken;
  124. ULONG length = 1; // include the null character
  125. WCHAR Buffer[DNS_MAX_NAME_LENGTH+1];
  126. if (!rfcDomainLength || !dnsDomain) {
  127. return ERROR_INVALID_PARAMETER;
  128. }
  129. if (wcslen(dnsDomain) > DNS_MAX_NAME_LENGTH) {
  130. return ERROR_INVALID_PARAMETER;
  131. }
  132. RtlCopyMemory(Buffer, dnsDomain, (wcslen(dnsDomain)+1)*sizeof(WCHAR));
  133. if (rfcDomain && *rfcDomainLength > 0) {
  134. RtlZeroMemory(rfcDomain, *rfcDomainLength*sizeof(WCHAR));
  135. }
  136. //
  137. // Start contructing the string
  138. //
  139. NextToken = wcstok(Buffer, L".");
  140. if ( NextToken )
  141. {
  142. //
  143. // Append the intial DC=
  144. //
  145. length += 3;
  146. if ( length <= *rfcDomainLength && rfcDomain )
  147. {
  148. wcscpy(rfcDomain, L"DC=");
  149. }
  150. }
  151. while ( NextToken )
  152. {
  153. length += wcslen(NextToken);
  154. if (length <= *rfcDomainLength && rfcDomain)
  155. {
  156. wcscat(rfcDomain, NextToken);
  157. }
  158. NextToken = wcstok(NULL, L".");
  159. if ( NextToken )
  160. {
  161. length += 4;
  162. if (length <= *rfcDomainLength && rfcDomain)
  163. {
  164. wcscat(rfcDomain, L",DC=");
  165. }
  166. }
  167. }
  168. if ( length > *rfcDomainLength )
  169. {
  170. WinError = ERROR_INSUFFICIENT_BUFFER;
  171. }
  172. //
  173. // Return how much space was needed
  174. //
  175. *rfcDomainLength = length;
  176. return WinError;
  177. }
  178. VOID
  179. FreeSidCache()
  180. {
  181. if (NULL != g_DomainSidCache)
  182. {
  183. DWORD i;
  184. for (i = 0; i < g_cDomainSidCache; i++)
  185. {
  186. if (NULL != g_DomainSidCache[i].wszDomain)
  187. {
  188. LocalFree(g_DomainSidCache[i].wszDomain);
  189. }
  190. if (NULL != g_DomainSidCache[i].pSid)
  191. {
  192. LocalFree(g_DomainSidCache[i].pSid);
  193. }
  194. }
  195. LocalFree(g_DomainSidCache);
  196. g_DomainSidCache = NULL;
  197. }
  198. }
  199. DWORD
  200. myGetSidFromDomain(
  201. IN LPWSTR wszDomain,
  202. OUT PSID *ppDomainSid)
  203. {
  204. NTSTATUS dwStatus;
  205. DWORD dwErr = ERROR_SUCCESS;
  206. LSA_HANDLE hPolicy = NULL;
  207. LSA_UNICODE_STRING uszServer = {0};
  208. LSA_OBJECT_ATTRIBUTES oa;
  209. SECURITY_QUALITY_OF_SERVICE sqos;
  210. LSA_UNICODE_STRING uszDCName = {0}, *puszDCName = NULL;
  211. PPOLICY_DNS_DOMAIN_INFO pDomainInfo = NULL;
  212. PSID pSidOut = NULL;
  213. PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
  214. LPWSTR wszDomainControllerName = NULL;
  215. LPWSTR pwszDomain = wszDomain;
  216. if (!g_fInitDone)
  217. {
  218. return(HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED));
  219. }
  220. __try
  221. {
  222. EnterCriticalSection(&g_csDomainSidCache);
  223. if(pwszDomain == NULL)
  224. {
  225. dwErr = myGetEnterpriseDnsName(&pwszDomain);
  226. if(dwErr != ERROR_SUCCESS)
  227. {
  228. _LeaveError(dwErr, "myGetEnterpriseDnsName");
  229. }
  230. }
  231. if(g_DomainSidCache && g_cDomainSidCache > 0)
  232. {
  233. DWORD i;
  234. for(i=0; i < g_cDomainSidCache; i++)
  235. {
  236. if(lstrcmpi(g_DomainSidCache[i].wszDomain, pwszDomain) == 0)
  237. {
  238. pSidOut = (PSID)LocalAlloc(LMEM_FIXED, GetLengthSid(g_DomainSidCache[i].pSid));
  239. if(pSidOut == NULL)
  240. {
  241. dwErr = ERROR_OUTOFMEMORY;
  242. _LeaveError(dwErr, "LocalAlloc");
  243. }
  244. CopySid(GetLengthSid(g_DomainSidCache[i].pSid), pSidOut, g_DomainSidCache[i].pSid);
  245. *ppDomainSid = pSidOut;
  246. pSidOut = NULL;
  247. __leave;
  248. }
  249. }
  250. }
  251. sqos.Length = sizeof(sqos);
  252. sqos.ImpersonationLevel = SecurityImpersonation;
  253. sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  254. sqos.EffectiveOnly = FALSE;
  255. InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
  256. oa.SecurityQualityOfService = &sqos;
  257. dwErr = DsGetDcName(
  258. NULL,
  259. pwszDomain,
  260. NULL,
  261. NULL,
  262. DS_RETURN_DNS_NAME,
  263. &pDcInfo);
  264. if(dwErr != ERROR_SUCCESS)
  265. {
  266. _LeaveError(dwErr, "DsGetDcName");
  267. }
  268. if((pDcInfo == NULL) ||
  269. ((pDcInfo->Flags & DS_DNS_CONTROLLER_FLAG) == 0) ||
  270. (pDcInfo->DomainControllerName == NULL))
  271. {
  272. dwErr = ERROR_CANT_ACCESS_DOMAIN_INFO;
  273. _LeaveError(dwErr, "DsGetDcName");
  274. }
  275. wszDomainControllerName = pDcInfo->DomainControllerName;
  276. // skip past forward slashes (why are they there?)
  277. while(*wszDomainControllerName == L'\\')
  278. {
  279. wszDomainControllerName++;
  280. }
  281. if(!RtlCreateUnicodeString(&uszDCName, wszDomainControllerName))
  282. {
  283. dwErr = GetLastError();
  284. _LeaveError(dwErr, "RtlCreateUnicodeString");
  285. }
  286. puszDCName = &uszDCName;
  287. dwStatus = LsaOpenPolicy(puszDCName, &oa, POLICY_EXECUTE, &hPolicy);
  288. dwErr = LsaNtStatusToWinError(dwStatus);
  289. RtlFreeUnicodeString(&uszDCName);
  290. if(dwErr != ERROR_SUCCESS)
  291. {
  292. _LeaveError(dwErr, "LsaOpenPolicy");
  293. }
  294. dwStatus = LsaQueryInformationPolicy(hPolicy,
  295. PolicyDnsDomainInformation,
  296. (LPVOID *)&pDomainInfo);
  297. dwErr = LsaNtStatusToWinError(dwStatus);
  298. if(dwErr != ERROR_SUCCESS)
  299. {
  300. _LeaveError(dwErr, "LsaQueryInformationPolicy");
  301. }
  302. pSidOut = (PSID)LocalAlloc(LMEM_FIXED, GetLengthSid(pDomainInfo->Sid));
  303. if(pSidOut == NULL)
  304. {
  305. dwErr = ERROR_OUTOFMEMORY;
  306. _LeaveError(dwErr, "LocalAlloc");
  307. }
  308. CopySid(GetLengthSid(pDomainInfo->Sid), pSidOut, pDomainInfo->Sid);
  309. *ppDomainSid = pSidOut;
  310. pSidOut = NULL;
  311. // Add to the cache.
  312. if(g_cMaxDomainSidCache < g_cDomainSidCache+1)
  313. {
  314. // Grow the cache
  315. PDOMAIN_SID_CACHE pNewCache = NULL;
  316. DWORD cNewCacheSize = g_cMaxDomainSidCache+DOMAIN_SID_CACHE_INC;
  317. pNewCache = (PDOMAIN_SID_CACHE)LocalAlloc(LMEM_FIXED, sizeof(DOMAIN_SID_CACHE)*cNewCacheSize);
  318. if(pNewCache == NULL)
  319. {
  320. _LeaveError(dwErr, "LocalAlloc");
  321. }
  322. ZeroMemory(pNewCache, sizeof(DOMAIN_SID_CACHE)*cNewCacheSize);
  323. if(g_DomainSidCache)
  324. {
  325. if(g_cDomainSidCache)
  326. {
  327. CopyMemory(pNewCache, g_DomainSidCache, sizeof(DOMAIN_SID_CACHE)*g_cDomainSidCache);
  328. }
  329. LocalFree(g_DomainSidCache);
  330. }
  331. g_DomainSidCache = pNewCache;
  332. g_cMaxDomainSidCache = cNewCacheSize;
  333. }
  334. g_DomainSidCache[g_cDomainSidCache].pSid = (PSID)LocalAlloc(LMEM_FIXED, GetLengthSid(pDomainInfo->Sid));
  335. if(g_DomainSidCache[g_cDomainSidCache].pSid == NULL)
  336. {
  337. _LeaveError(dwErr, "LocalAlloc");
  338. }
  339. CopySid(GetLengthSid(pDomainInfo->Sid), g_DomainSidCache[g_cDomainSidCache].pSid, pDomainInfo->Sid);
  340. g_DomainSidCache[g_cDomainSidCache].wszDomain = (LPWSTR)LocalAlloc(LMEM_FIXED, sizeof(WCHAR)*(wcslen(pwszDomain)+1));
  341. if(g_DomainSidCache[g_cDomainSidCache].wszDomain == NULL)
  342. {
  343. LocalFree(g_DomainSidCache[g_cDomainSidCache].pSid);
  344. g_DomainSidCache[g_cDomainSidCache].pSid = NULL;
  345. _LeaveError(dwErr, "LocalAlloc");
  346. }
  347. wcscpy(g_DomainSidCache[g_cDomainSidCache].wszDomain, pwszDomain);
  348. g_cDomainSidCache++;
  349. }
  350. __except(dwErr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  351. {
  352. }
  353. LeaveCriticalSection(&g_csDomainSidCache);
  354. if (NULL != pwszDomain && wszDomain != pwszDomain)
  355. {
  356. LocalFree(pwszDomain);
  357. }
  358. if (NULL != pDcInfo)
  359. {
  360. NetApiBufferFree(pDcInfo);
  361. }
  362. if (NULL != pDomainInfo)
  363. {
  364. LsaFreeMemory(pDomainInfo);
  365. }
  366. if (NULL != hPolicy)
  367. {
  368. LsaClose(hPolicy);
  369. }
  370. return dwErr;
  371. }
  372. // CACleanup is called multiple times!
  373. VOID
  374. CACleanup()
  375. {
  376. if (NULL != g_pwszEnterpriseRoot)
  377. {
  378. LocalFree(g_pwszEnterpriseRoot);
  379. g_pwszEnterpriseRoot = NULL;
  380. }
  381. if (NULL != g_pLocalSid)
  382. {
  383. FreeSid(g_pLocalSid);
  384. g_pLocalSid = NULL;
  385. }
  386. if (NULL != g_pwszEnterpriseRootOID)
  387. {
  388. LocalFree(g_pwszEnterpriseRootOID);
  389. g_pwszEnterpriseRootOID = NULL;
  390. }
  391. FreeSidCache();
  392. }
  393. DWORD
  394. myGetEnterpriseDnsName(
  395. OUT WCHAR **ppwszDomain)
  396. {
  397. HRESULT hr;
  398. LSA_HANDLE hPolicy = NULL;
  399. POLICY_DNS_DOMAIN_INFO *pDomainInfo = NULL;
  400. if (NULL == g_pwszEnterpriseRoot)
  401. {
  402. LSA_OBJECT_ATTRIBUTES oa;
  403. SECURITY_QUALITY_OF_SERVICE sqos;
  404. NTSTATUS dwStatus;
  405. sqos.Length = sizeof(sqos);
  406. sqos.ImpersonationLevel = SecurityImpersonation;
  407. sqos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  408. sqos.EffectiveOnly = FALSE;
  409. InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
  410. oa.SecurityQualityOfService = &sqos;
  411. dwStatus = LsaOpenPolicy(
  412. NULL,
  413. &oa,
  414. POLICY_READ | POLICY_EXECUTE,
  415. &hPolicy);
  416. hr = LsaNtStatusToWinError(dwStatus);
  417. _JumpIfError(hr, error, "LsaOpenPolicy");
  418. dwStatus = LsaQueryInformationPolicy(
  419. hPolicy,
  420. PolicyDnsDomainInformation,
  421. (VOID **) &pDomainInfo);
  422. hr = LsaNtStatusToWinError(dwStatus);
  423. _JumpIfError(hr, error, "LsaNtStatusToWinError");
  424. if (0 >= pDomainInfo->DnsForestName.Length ||
  425. NULL == pDomainInfo->DnsForestName.Buffer)
  426. {
  427. hr = ERROR_CANT_ACCESS_DOMAIN_INFO;
  428. _JumpError(hr, error, "DomainInfo");
  429. }
  430. hr = myDupString(
  431. pDomainInfo->DnsForestName.Buffer,
  432. &g_pwszEnterpriseRoot);
  433. _JumpIfError(hr, error, "myDupString");
  434. }
  435. hr = myDupString(g_pwszEnterpriseRoot, ppwszDomain);
  436. _JumpIfError(hr, error, "myDupString");
  437. error:
  438. if (NULL != pDomainInfo)
  439. {
  440. LsaFreeMemory(pDomainInfo);
  441. }
  442. if (NULL != hPolicy)
  443. {
  444. LsaClose(hPolicy);
  445. }
  446. return(hr);
  447. }
  448. CCAProperty::CCAProperty(LPCWSTR wszName)
  449. {
  450. m_awszValues = NULL;
  451. m_pNext = NULL;
  452. m_wszName = CertAllocString(wszName);
  453. }
  454. CCAProperty::~CCAProperty()
  455. {
  456. _Cleanup();
  457. }
  458. HRESULT CCAProperty::_Cleanup()
  459. {
  460. // NOTE: this should only be called via
  461. // DeleteChain
  462. if(m_wszName)
  463. {
  464. CertFreeString(m_wszName);
  465. m_wszName = NULL;
  466. }
  467. if(m_awszValues)
  468. {
  469. LocalFree(m_awszValues);
  470. m_awszValues = NULL;
  471. }
  472. m_pNext = NULL;
  473. return S_OK;
  474. }
  475. HRESULT CCAProperty::Find(LPCWSTR wszName, CCAProperty **ppCAProp)
  476. {
  477. CCAProperty *pCurrent = this;
  478. if((wszName == NULL) || (ppCAProp == NULL))
  479. {
  480. return E_POINTER;
  481. }
  482. if(this == NULL)
  483. {
  484. return E_POINTER;
  485. }
  486. if((m_wszName != NULL) &&(lstrcmpi(wszName, m_wszName) == 0))
  487. {
  488. *ppCAProp = this;
  489. return S_OK;
  490. }
  491. if(m_pNext)
  492. {
  493. return m_pNext->Find(wszName, ppCAProp);
  494. }
  495. // Didn't find one
  496. *ppCAProp = NULL;
  497. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  498. }
  499. HRESULT CCAProperty::Append(CCAProperty **ppCAPropChain, CCAProperty *pNewProp)
  500. {
  501. CCAProperty *pCurrent;
  502. if((ppCAPropChain == NULL) || (pNewProp == NULL))
  503. {
  504. return E_POINTER;
  505. }
  506. if(*ppCAPropChain == NULL)
  507. {
  508. *ppCAPropChain = pNewProp;
  509. return S_OK;
  510. }
  511. pCurrent = *ppCAPropChain;
  512. while(pCurrent->m_pNext != NULL)
  513. {
  514. pCurrent = pCurrent->m_pNext;
  515. }
  516. pCurrent->m_pNext = pNewProp;
  517. return S_OK;
  518. }
  519. HRESULT CCAProperty::GetValue(LPWSTR **pawszProperties)
  520. {
  521. HRESULT hr;
  522. if(pawszProperties == NULL)
  523. {
  524. return E_POINTER;
  525. }
  526. *pawszProperties = m_awszValues;
  527. m_awszValues = NULL;
  528. hr = SetValue(*pawszProperties);
  529. if(hr != S_OK)
  530. {
  531. m_awszValues = *pawszProperties;
  532. *pawszProperties = NULL;
  533. }
  534. return hr;
  535. }
  536. HRESULT CCAProperty::SetValue(LPWSTR *awszProperties)
  537. {
  538. DWORD cbStringTotal = 0;
  539. DWORD cStrings=1;
  540. WCHAR **pwszAttr;
  541. WCHAR *wszCurString;
  542. if(m_awszValues)
  543. {
  544. LocalFree(m_awszValues);
  545. m_awszValues = NULL;
  546. }
  547. if(NULL == awszProperties)
  548. {
  549. return S_OK;
  550. }
  551. for(pwszAttr = awszProperties; *pwszAttr != NULL; pwszAttr++)
  552. {
  553. cStrings += 1;
  554. cbStringTotal += (wcslen(*pwszAttr) + 1)*sizeof(WCHAR);
  555. }
  556. m_awszValues = (WCHAR **)LocalAlloc(LMEM_FIXED, cStrings*sizeof(WCHAR *) + cbStringTotal);
  557. if(m_awszValues == NULL)
  558. {
  559. return E_OUTOFMEMORY;
  560. }
  561. wszCurString = (WCHAR *)(m_awszValues + cStrings);
  562. cStrings = 0;
  563. for(pwszAttr = awszProperties; *pwszAttr != NULL; pwszAttr++)
  564. {
  565. m_awszValues[cStrings] = wszCurString;
  566. wcscpy(wszCurString, *pwszAttr);
  567. wszCurString += wcslen(wszCurString) + 1;
  568. cStrings += 1;
  569. }
  570. m_awszValues[cStrings] = NULL;
  571. return S_OK;
  572. }
  573. HRESULT CCAProperty::DeleteChain(CCAProperty **ppCAProp)
  574. {
  575. if(ppCAProp == NULL)
  576. {
  577. return E_POINTER;
  578. }
  579. if(*ppCAProp == NULL)
  580. {
  581. return S_OK;
  582. }
  583. DeleteChain(&(*ppCAProp)->m_pNext);
  584. delete *ppCAProp;
  585. return S_OK;
  586. }
  587. HRESULT CCAProperty::LoadFromRegValue(HKEY hkReg, LPCWSTR wszValue)
  588. {
  589. DWORD err;
  590. DWORD dwType;
  591. DWORD dwSize;
  592. DWORD cbStringTotal = 0;
  593. WCHAR **pwszAttr;
  594. WCHAR *wszCurString;
  595. CERTSTR bstrRegValue;
  596. HRESULT hr = S_OK;
  597. WCHAR *wszValues = NULL;
  598. if(m_awszValues)
  599. {
  600. LocalFree(m_awszValues);
  601. m_awszValues = NULL;
  602. }
  603. if((hkReg == NULL ) || (wszValue == NULL))
  604. {
  605. return E_POINTER;
  606. }
  607. err = RegQueryValueEx(hkReg,
  608. wszValue,
  609. NULL,
  610. &dwType,
  611. NULL,
  612. &dwSize);
  613. if(ERROR_SUCCESS != err)
  614. {
  615. hr = myHError(err);
  616. goto error;
  617. }
  618. if(sizeof(WCHAR) != dwSize)
  619. {
  620. switch(dwType)
  621. {
  622. case REG_SZ:
  623. m_awszValues = (WCHAR **)LocalAlloc(LMEM_FIXED, 2*sizeof(WCHAR *) + dwSize);
  624. if(m_awszValues == NULL)
  625. {
  626. hr = E_OUTOFMEMORY;
  627. goto error;
  628. }
  629. err = RegQueryValueEx(hkReg,
  630. wszValue,
  631. NULL,
  632. &dwType,
  633. (PBYTE)(m_awszValues+2),
  634. &dwSize);
  635. if(ERROR_SUCCESS != err)
  636. {
  637. hr = myHError(err);
  638. goto error;
  639. }
  640. m_awszValues[0] = (WCHAR *)(m_awszValues+2);
  641. m_awszValues[1] = NULL;
  642. break;
  643. case REG_MULTI_SZ:
  644. {
  645. WCHAR *wszCur;
  646. DWORD cStrings = 1;
  647. wszValues = (WCHAR *)LocalAlloc(LMEM_FIXED, dwSize);
  648. if(wszValues == NULL)
  649. {
  650. hr = E_OUTOFMEMORY;
  651. goto error;
  652. }
  653. err = RegQueryValueEx(hkReg,
  654. wszValue,
  655. NULL,
  656. &dwType,
  657. (PBYTE)wszValues,
  658. &dwSize);
  659. if(ERROR_SUCCESS != err)
  660. {
  661. hr = myHError(err);
  662. goto error;
  663. }
  664. wszCur = wszValues;
  665. while(wcslen(wszCur) > 0)
  666. {
  667. cStrings++;
  668. wszCur += wcslen(wszCur)+1;
  669. }
  670. m_awszValues = (WCHAR **)LocalAlloc(LMEM_FIXED, cStrings*sizeof(WCHAR *) + dwSize);
  671. if(m_awszValues == NULL)
  672. {
  673. hr = E_OUTOFMEMORY;
  674. goto error;
  675. }
  676. CopyMemory((PBYTE)(m_awszValues + cStrings), wszValues, dwSize);
  677. wszCur = (WCHAR *)(m_awszValues + cStrings);
  678. cStrings = 0;
  679. while(wcslen(wszCur) > 0)
  680. {
  681. m_awszValues[cStrings] = wszCur;
  682. cStrings++;
  683. wszCur += wcslen(wszCur)+1;
  684. }
  685. m_awszValues[cStrings] = NULL;
  686. break;
  687. }
  688. default:
  689. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  690. goto error;
  691. }
  692. }
  693. error:
  694. if(wszValues)
  695. {
  696. LocalFree(wszValues);
  697. }
  698. return hr;
  699. }
  700. HRESULT CCAProperty::UpdateToRegValue(HKEY hkReg, LPCWSTR wszValue)
  701. {
  702. DWORD err;
  703. DWORD dwType;
  704. DWORD dwSize;
  705. DWORD cbStringTotal = 0;
  706. WCHAR **pwszAttr;
  707. WCHAR *wszCurString;
  708. CERTSTR bstrRegValue = NULL;
  709. HRESULT hr = S_OK;
  710. if((hkReg == NULL ) || (wszValue == NULL))
  711. {
  712. return E_POINTER;
  713. }
  714. if(m_awszValues == NULL)
  715. {
  716. bstrRegValue = CertAllocString(TEXT(""));
  717. if(bstrRegValue == NULL)
  718. {
  719. hr = E_OUTOFMEMORY;
  720. goto error;
  721. }
  722. }
  723. else
  724. {
  725. LPWSTR *pwszCur = m_awszValues;
  726. LPWSTR wszCopy = NULL;
  727. DWORD cValues = 0;
  728. while(*pwszCur)
  729. {
  730. cValues += wcslen(*pwszCur) + 1;
  731. pwszCur++;
  732. }
  733. cValues++;
  734. bstrRegValue = CertAllocStringLen(NULL, cValues);
  735. if(bstrRegValue == NULL)
  736. {
  737. hr = E_OUTOFMEMORY;
  738. goto error;
  739. }
  740. pwszCur = m_awszValues;
  741. wszCopy = bstrRegValue;
  742. while(*pwszCur)
  743. {
  744. CopyMemory(wszCopy, *pwszCur, sizeof(WCHAR)*(wcslen(*pwszCur)+1));
  745. wszCopy += (wcslen(*pwszCur)+1);
  746. pwszCur++;
  747. }
  748. *wszCopy = NULL;
  749. }
  750. err = RegSetValueEx(hkReg,
  751. wszValue,
  752. NULL,
  753. REG_MULTI_SZ,
  754. (PBYTE)bstrRegValue,
  755. CertStringByteLen(bstrRegValue));
  756. if(ERROR_SUCCESS != err )
  757. {
  758. hr = myHError(err);
  759. goto error;
  760. }
  761. error:
  762. if(bstrRegValue)
  763. {
  764. CertFreeString(bstrRegValue);
  765. }
  766. return hr;
  767. }
  768. HRESULT CertFreeString(CERTSTR cstrString)
  769. {
  770. WCHAR *pData = (WCHAR *)(((PBYTE)cstrString)-sizeof(UINT));
  771. if(cstrString == NULL)
  772. {
  773. return E_POINTER;
  774. }
  775. LocalFree(pData);
  776. return S_OK;
  777. }
  778. CERTSTR CertAllocString(LPCWSTR wszString)
  779. {
  780. if(wszString == NULL)
  781. {
  782. return NULL;
  783. }
  784. return CertAllocStringLen(wszString, wcslen(wszString)+1);
  785. }
  786. CERTSTR CertAllocStringLen(LPCWSTR wszString, UINT len)
  787. {
  788. CERTSTR szResult;
  789. szResult = CertAllocStringByteLen(NULL, len*sizeof(WCHAR));
  790. if (NULL != szResult && NULL != wszString)
  791. {
  792. CopyMemory(szResult, wszString, min(wcslen(wszString)+1, len)*sizeof(WCHAR));
  793. }
  794. return szResult;
  795. }
  796. CERTSTR CertAllocStringByteLen(LPCSTR szString, UINT len)
  797. {
  798. PBYTE pbResult;
  799. pbResult = (PBYTE)LocalAlloc(LMEM_FIXED, len + sizeof(UINT) + sizeof(WCHAR));
  800. if (NULL == pbResult)
  801. return NULL;
  802. *((UINT *)pbResult) = len;
  803. pbResult += sizeof(UINT);
  804. *((UNALIGNED WCHAR *)(pbResult+len)) = L'\0';
  805. if(szString)
  806. {
  807. CopyMemory(pbResult, szString, min(len, strlen(szString)+1));
  808. }
  809. return (CERTSTR)pbResult;
  810. }
  811. UINT CertStringLen(CERTSTR cstrString)
  812. {
  813. if(cstrString == NULL)
  814. {
  815. return 0;
  816. }
  817. return(*((UINT *)((PBYTE)cstrString - sizeof(UINT))))/sizeof(WCHAR);
  818. }
  819. UINT CertStringByteLen(CERTSTR cstrString)
  820. {
  821. if(cstrString == NULL)
  822. {
  823. return 0;
  824. }
  825. return(*((UINT *)((PBYTE)cstrString - sizeof(UINT))));
  826. }
  827. HRESULT CAAccessCheckp(HANDLE ClientToken, PSECURITY_DESCRIPTOR pSD)
  828. {
  829. return CAAccessCheckpEx(ClientToken, pSD, CERTTYPE_ACCESS_CHECK_ENROLL);
  830. }
  831. HRESULT CAAccessCheckpEx(HANDLE ClientToken, PSECURITY_DESCRIPTOR pSD, DWORD dwOption)
  832. {
  833. HRESULT hr = S_OK;
  834. HANDLE hClientToken = NULL;
  835. HANDLE hHandle = NULL;
  836. PRIVILEGE_SET ps;
  837. DWORD dwPSSize = sizeof(ps);
  838. GENERIC_MAPPING AccessMapping;
  839. BOOL fAccessAllowed = FALSE;
  840. DWORD grantAccess;
  841. PTOKEN_USER pUserInfo = NULL;
  842. DWORD cbUserInfo = 0;
  843. SID_IDENTIFIER_AUTHORITY IDAuthorityNT = SECURITY_NT_AUTHORITY;
  844. OBJECT_TYPE_LIST aObjectTypeList[] = {
  845. {
  846. ACCESS_OBJECT_GUID, // Level
  847. 0, // Sbz
  848. const_cast<GUID *>(&GUID_ENROLL)
  849. }
  850. };
  851. DWORD cObjectTypeList = sizeof(aObjectTypeList)/sizeof(aObjectTypeList[0]);
  852. OBJECT_TYPE_LIST aAutoEnrollList[] = {
  853. {
  854. ACCESS_OBJECT_GUID, // Level
  855. 0, // Sbz
  856. const_cast<GUID *>(&GUID_AUTOENROLL)
  857. }
  858. };
  859. DWORD cAutoEnrollList = sizeof(aAutoEnrollList)/sizeof(aAutoEnrollList[0]);
  860. if(pSD == NULL)
  861. {
  862. hr = E_ACCESSDENIED;
  863. goto error;
  864. }
  865. if(ClientToken == NULL)
  866. {
  867. hHandle = GetCurrentThread();
  868. if (NULL == hHandle)
  869. {
  870. hr = myHLastError();
  871. }
  872. else
  873. {
  874. if (!OpenThreadToken(hHandle,
  875. TOKEN_QUERY,
  876. TRUE, // open as self
  877. &hClientToken))
  878. {
  879. hr = myHLastError();
  880. CloseHandle(hHandle);
  881. hHandle = NULL;
  882. }
  883. }
  884. if(hr != S_OK)
  885. {
  886. hHandle = GetCurrentProcess();
  887. if (NULL == hHandle)
  888. {
  889. hr = myHLastError();
  890. }
  891. else
  892. {
  893. HANDLE hProcessToken = NULL;
  894. hr = S_OK;
  895. if (!OpenProcessToken(hHandle,
  896. TOKEN_DUPLICATE,
  897. &hProcessToken))
  898. {
  899. hr = myHLastError();
  900. CloseHandle(hHandle);
  901. hHandle = NULL;
  902. }
  903. else
  904. {
  905. if(!DuplicateToken(hProcessToken,
  906. SecurityImpersonation,
  907. &hClientToken))
  908. {
  909. hr = myHLastError();
  910. CloseHandle(hHandle);
  911. hHandle = NULL;
  912. }
  913. CloseHandle(hProcessToken);
  914. }
  915. }
  916. }
  917. }
  918. else
  919. {
  920. hClientToken = ClientToken;
  921. }
  922. // First, we check the special case. If the ClientToken
  923. // primary SID is for Local System, then we get the
  924. // real domain relative sid for this machine
  925. GetTokenInformation(hClientToken, TokenUser, NULL, 0, &cbUserInfo);
  926. if(cbUserInfo == 0)
  927. {
  928. hr = myHLastError();
  929. goto error;
  930. }
  931. pUserInfo = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, cbUserInfo);
  932. if(pUserInfo == NULL)
  933. {
  934. hr = E_OUTOFMEMORY;
  935. goto error;
  936. }
  937. if(!GetTokenInformation(hClientToken, TokenUser, pUserInfo, cbUserInfo, &cbUserInfo))
  938. {
  939. hr = myHLastError();
  940. goto error;
  941. }
  942. // Check it see if we're local-system
  943. if(0 == (CERTTYPE_ACCESS_CHECK_NO_MAPPING & dwOption))
  944. {
  945. if(NULL == g_pLocalSid)
  946. {
  947. if(!AllocateAndInitializeSid(&IDAuthorityNT, 1, SECURITY_LOCAL_SYSTEM_RID, 0,0,0,0,0,0,0, &g_pLocalSid))
  948. {
  949. hr = myHLastError();
  950. g_pLocalSid=NULL;
  951. goto error;
  952. }
  953. }
  954. if(EqualSid(g_pLocalSid, pUserInfo->User.Sid))
  955. {
  956. // This is local system.
  957. // Derive the real token
  958. if(hClientToken != ClientToken)
  959. {
  960. CloseHandle(hClientToken);
  961. }
  962. hClientToken = NULL;
  963. if(!myNetLogonUser(NULL, NULL, NULL, &hClientToken))
  964. {
  965. hr = myHLastError();
  966. goto error;
  967. }
  968. }
  969. }
  970. if(CERTTYPE_ACCESS_CHECK_ENROLL & dwOption)
  971. {
  972. if(!AccessCheckByType(
  973. pSD, // security descriptor
  974. NULL, // SID of object being checked
  975. hClientToken, // handle to client access token
  976. ACTRL_DS_CONTROL_ACCESS, // requested access rights
  977. aObjectTypeList, // array of object types
  978. cObjectTypeList, // number of object type elements
  979. &AccessMapping, // map generic to specific rights
  980. &ps, // receives privileges used
  981. &dwPSSize, // size of privilege-set buffer
  982. &grantAccess, // retrieves mask of granted rights
  983. &fAccessAllowed)) // retrieves results of access check);
  984. {
  985. hr = myHLastError();
  986. _JumpIfError(hr, error, "AccessCheckByType");
  987. }
  988. }
  989. else
  990. {
  991. if(0 == (CERTTYPE_ACCESS_CHECK_AUTO_ENROLL & dwOption))
  992. {
  993. hr=E_INVALIDARG;
  994. goto error;
  995. }
  996. if(!AccessCheckByType(
  997. pSD, // security descriptor
  998. NULL, // SID of object being checked
  999. hClientToken, // handle to client access token
  1000. ACTRL_DS_CONTROL_ACCESS, // requested access rights
  1001. aAutoEnrollList, // array of object types
  1002. cAutoEnrollList, // number of object type elements
  1003. &AccessMapping, // map generic to specific rights
  1004. &ps, // receives privileges used
  1005. &dwPSSize, // size of privilege-set buffer
  1006. &grantAccess, // retrieves mask of granted rights
  1007. &fAccessAllowed)) // retrieves results of access check);
  1008. {
  1009. hr = myHLastError();
  1010. _JumpIfError(hr, error, "AccessCheckByType");
  1011. }
  1012. }
  1013. if(fAccessAllowed)
  1014. {
  1015. hr = S_OK;
  1016. }
  1017. else
  1018. {
  1019. hr = myHLastError();
  1020. }
  1021. error:
  1022. if(pUserInfo)
  1023. {
  1024. LocalFree(pUserInfo);
  1025. }
  1026. if(hHandle)
  1027. {
  1028. CloseHandle(hHandle);
  1029. }
  1030. if(hClientToken != ClientToken)
  1031. {
  1032. if(hClientToken)
  1033. {
  1034. CloseHandle(hClientToken);
  1035. }
  1036. }
  1037. return hr;
  1038. }