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.

1185 lines
35 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: ADUtils.cpp
  7. //
  8. // Contents: Classes CWString, CACLDiagComModule, ACE_SAMNAME, helper
  9. // methods
  10. //
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include "adutils.h"
  15. #include <util.h>
  16. #include <sddl.h>
  17. #include "dscmn.h"
  18. #include "SecDesc.h"
  19. void StripQuotes (wstring& str)
  20. {
  21. size_t qPos = str.find_first_of (L"\"", 0);
  22. if ( 0 == qPos )
  23. {
  24. str = str.substr (1);
  25. qPos = str.find_last_of (L"\"");
  26. if ( str.npos != qPos )
  27. str.replace (qPos, 1, 1, 0);
  28. }
  29. }
  30. wstring GetSystemMessage (DWORD dwErr)
  31. {
  32. wstring message;
  33. if ( E_ADS_BAD_PATHNAME == dwErr )
  34. {
  35. CWString msg;
  36. msg.LoadFromResource (IDS_ADS_BAD_PATHNAME);
  37. message = msg;
  38. }
  39. else
  40. {
  41. LPVOID pMsgBuf = 0;
  42. FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
  43. FORMAT_MESSAGE_FROM_SYSTEM,
  44. NULL,
  45. dwErr,
  46. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  47. (LPWSTR) &pMsgBuf, 0, NULL );
  48. message = (LPWSTR) pMsgBuf;
  49. // Free the buffer.
  50. if ( pMsgBuf )
  51. LocalFree (pMsgBuf);
  52. }
  53. return message;
  54. }
  55. /*
  56. // Attempt to locate a message in a given module. Return the message string
  57. // if found, the empty string if not.
  58. //
  59. // flags - FormatMessage flags to use
  60. //
  61. // module - module handle of message dll to look in, or 0 to use the system
  62. // message table.
  63. //
  64. // code - message code to look for
  65. String
  66. getMessageHelper(DWORD flags, HMODULE module, HRESULT code)
  67. {
  68. ASSERT(code);
  69. ASSERT(flags & FORMAT_MESSAGE_ALLOCATE_BUFFER);
  70. String message;
  71. TCHAR* sys_message = 0;
  72. DWORD result =
  73. ::FormatMessage(
  74. flags,
  75. module,
  76. static_cast<DWORD>(code),
  77. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  78. reinterpret_cast<LPTSTR>(&sys_message),
  79. 0,
  80. 0);
  81. if (result)
  82. {
  83. ASSERT(sys_message);
  84. if (sys_message)
  85. {
  86. message = sys_message;
  87. ASSERT(result == message.length());
  88. Win::LocalFree(sys_message);
  89. message.replace(TEXT("\r\n"), TEXT(" "));
  90. }
  91. }
  92. return message;
  93. }
  94. // Attempts to locate message strings for various facility codes in the
  95. // HRESULT
  96. String
  97. GetErrorMessage(HRESULT hr)
  98. {
  99. TRACE_FUNCTION2(GetErrorMessage, String::format("%1!08X!", hr));
  100. ASSERT(FAILED(hr));
  101. if (!FAILED(hr))
  102. {
  103. // no messages for success!
  104. return String();
  105. }
  106. HRESULT code = HRESULT_CODE(hr);
  107. if (code == -1)
  108. {
  109. return String::load(IDS_UNKNOWN_ERROR_CODE);
  110. }
  111. String message;
  112. // default is the system error message table
  113. HMODULE module = 0;
  114. DWORD flags =
  115. FORMAT_MESSAGE_ALLOCATE_BUFFER
  116. | FORMAT_MESSAGE_IGNORE_INSERTS
  117. | FORMAT_MESSAGE_FROM_SYSTEM;
  118. int facility = HRESULT_FACILITY(hr);
  119. switch (facility)
  120. {
  121. case FACILITY_WIN32: // 0x7
  122. {
  123. // included here:
  124. // lanman error codes (in it's own dll) see lmerr.h
  125. // dns
  126. // winsock
  127. // @@ use SafeDLL here?
  128. static HMODULE lm_err_res_dll = 0;
  129. if (code >= NERR_BASE && code <= MAX_NERR)
  130. {
  131. // use the net error message resource dll
  132. if (lm_err_res_dll == 0)
  133. {
  134. lm_err_res_dll =
  135. Win::LoadLibraryEx(
  136. TEXT("netmsg.dll"),
  137. LOAD_LIBRARY_AS_DATAFILE);
  138. }
  139. module = lm_err_res_dll;
  140. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  141. }
  142. break;
  143. }
  144. case 0x0:
  145. {
  146. if (code >= 0x5000 && code <= 0x50FF)
  147. {
  148. // It's an ADSI error. They put the facility code (5) in the
  149. // wrong place!
  150. // @@ use SafeDLL here?
  151. static HMODULE adsi_err_res_dll = 0;
  152. // use the net error message resource dll
  153. if (adsi_err_res_dll == 0)
  154. {
  155. adsi_err_res_dll =
  156. Win::LoadLibraryEx(
  157. TEXT("activeds.dll"),
  158. LOAD_LIBRARY_AS_DATAFILE);
  159. }
  160. module = adsi_err_res_dll;
  161. flags |= FORMAT_MESSAGE_FROM_HMODULE;
  162. // the message dll expects the entire error code
  163. code = hr;
  164. }
  165. break;
  166. }
  167. default:
  168. {
  169. // do nothing
  170. break;
  171. }
  172. }
  173. message = getMessageHelper(flags, module, code);
  174. if (message.empty())
  175. {
  176. message = String::load(IDS_UNKNOWN_ERROR_CODE);
  177. }
  178. return message;
  179. }
  180. */
  181. ///////////////////////////////////////////////////////////////////////
  182. // wstring helper methods
  183. HRESULT wstringFromGUID (wstring& str, REFGUID guid)
  184. {
  185. HRESULT hr = S_OK;
  186. const int BUF_LEN = 128;
  187. WCHAR awch[BUF_LEN];
  188. hr = StringFromGUID2(guid, awch, BUF_LEN);
  189. if ( SUCCEEDED (hr) )
  190. str = OLE2T(awch);
  191. return hr;
  192. }
  193. bool LoadFromResource(wstring& str, UINT uID)
  194. {
  195. int nBufferSize = 128;
  196. static const int nCountMax = 4;
  197. int nCount = 1;
  198. do
  199. {
  200. LPWSTR lpszBuffer = (LPWSTR)alloca(nCount*nBufferSize*sizeof(WCHAR));
  201. int iRet = ::LoadString(_Module.GetResourceInstance(), uID,
  202. lpszBuffer, nBufferSize);
  203. if (iRet == 0)
  204. {
  205. str = L"?";
  206. return false; // not found
  207. }
  208. if (iRet == nBufferSize-1) // truncation
  209. {
  210. if (nCount > nCountMax)
  211. {
  212. // too many reallocations
  213. str = lpszBuffer;
  214. return false; // truncation
  215. }
  216. // try to expand buffer
  217. nBufferSize *=2;
  218. nCount++;
  219. }
  220. else
  221. {
  222. // got it
  223. str = lpszBuffer;
  224. break;
  225. }
  226. }
  227. #pragma warning (disable : 4127)
  228. while (true);
  229. #pragma warning (default : 4127)
  230. return true;
  231. }
  232. bool FormatMessage(wstring& str, UINT nFormatID, ...)
  233. {
  234. bool bResult = false;
  235. // get format string from string table
  236. wstring strFormat;
  237. if ( LoadFromResource (strFormat, nFormatID) )
  238. {
  239. // format message into temporary buffer lpszTemp
  240. va_list argList;
  241. va_start(argList, nFormatID);
  242. PWSTR lpszTemp = 0;
  243. if (::FormatMessage (FORMAT_MESSAGE_FROM_STRING |
  244. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  245. strFormat.c_str (), 0, 0, (PWSTR)&lpszTemp, 0, &argList) == 0 ||
  246. lpszTemp == NULL)
  247. {
  248. return false;
  249. }
  250. // assign lpszTemp into the resulting string and free lpszTemp
  251. str = lpszTemp;
  252. bResult = true;
  253. LocalFree(lpszTemp);
  254. va_end(argList);
  255. }
  256. return bResult;
  257. }
  258. bool FormatMessage(wstring& str, LPCTSTR lpszFormat, ...)
  259. {
  260. bool bResult = false;
  261. // format message into temporary buffer lpszTemp
  262. va_list argList;
  263. va_start(argList, lpszFormat);
  264. LPTSTR lpszTemp;
  265. if ( ::FormatMessage (FORMAT_MESSAGE_FROM_STRING |
  266. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  267. lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
  268. lpszTemp == NULL)
  269. {
  270. return false; //AfxThrowMemoryException();
  271. }
  272. // assign lpszTemp into the resulting string and free the temporary
  273. str = lpszTemp;
  274. bResult = true;
  275. LocalFree(lpszTemp);
  276. va_end(argList);
  277. return bResult;
  278. }
  279. ///////////////////////////////////////////////////////////////////////////////
  280. // CACLDiagComModule
  281. CACLDiagComModule::CACLDiagComModule() :
  282. m_bDoSchema (false),
  283. m_bDoCheckDelegation (false),
  284. m_bDoGetEffective (false),
  285. m_bDoFixDelegation (false),
  286. m_pSecurityDescriptor (0),
  287. m_bTabDelimitedOutput (false),
  288. m_hPrivToken (0),
  289. m_bLogErrors (false)
  290. {
  291. DWORD dwPriv = SE_SECURITY_PRIVILEGE;
  292. m_hPrivToken = EnablePrivileges(&dwPriv, 1);
  293. }
  294. CACLDiagComModule::~CACLDiagComModule ()
  295. {
  296. if ( m_pSecurityDescriptor )
  297. {
  298. LocalFree (m_pSecurityDescriptor);
  299. m_pSecurityDescriptor = 0;
  300. }
  301. ReleasePrivileges(m_hPrivToken);
  302. }
  303. HRESULT CACLDiagComModule::GetClassFromGUID (
  304. REFGUID rightsGUID,
  305. wstring& strClassName,
  306. GUID_TYPE* pGuidType)
  307. {
  308. HRESULT hr = S_OK;
  309. CSchemaClassInfo* pInfo = 0;
  310. bool bFound = false;
  311. // Search for a class
  312. for (int nIndex = 0; nIndex < (int) m_classInfoArray.GetCount (); nIndex++)
  313. {
  314. pInfo = m_classInfoArray[nIndex];
  315. if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()),
  316. rightsGUID) )
  317. {
  318. PCWSTR pszDisplayName = pInfo->GetDisplayName ();
  319. strClassName = pszDisplayName ? pszDisplayName : L"";
  320. bFound = true;
  321. if ( pGuidType )
  322. *pGuidType = GUID_TYPE_CLASS;
  323. break;
  324. }
  325. }
  326. // Search for an attribute
  327. if ( !bFound )
  328. {
  329. for (int nIndex = 0; nIndex < (int) m_attrInfoArray.GetCount (); nIndex++)
  330. {
  331. pInfo = m_attrInfoArray[nIndex];
  332. if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()),
  333. rightsGUID) )
  334. {
  335. PCWSTR pszDisplayName = pInfo->GetDisplayName ();
  336. strClassName = pszDisplayName ? pszDisplayName : L"";
  337. bFound = true;
  338. if ( pGuidType )
  339. *pGuidType = GUID_TYPE_ATTRIBUTE;
  340. break;
  341. }
  342. }
  343. }
  344. // Search for a control
  345. if ( !bFound )
  346. {
  347. hr = GetControlDisplayName (rightsGUID, strClassName);
  348. if ( SUCCEEDED (hr) && strClassName.length () )
  349. {
  350. if ( pGuidType )
  351. *pGuidType = GUID_TYPE_CONTROL;
  352. }
  353. else
  354. {
  355. if ( pGuidType )
  356. *pGuidType = GUID_TYPE_UNKNOWN;
  357. strClassName = L"unknown";
  358. }
  359. }
  360. return hr;
  361. }
  362. HRESULT CACLDiagComModule::Init()
  363. {
  364. // Find out if logged-in users is an Administrator
  365. BOOL bIsUserAdministrator = FALSE;
  366. HRESULT hr = IsUserAdministrator (bIsUserAdministrator);
  367. if ( SUCCEEDED (hr) )
  368. {
  369. if ( bIsUserAdministrator )
  370. {
  371. wstring strObjectDN;
  372. LPCWSTR pszLDAP = L"LDAP://";
  373. size_t len = wcslen (pszLDAP);
  374. if ( m_strObjectDN.compare (0, len, pszLDAP) )
  375. {
  376. strObjectDN = pszLDAP;
  377. }
  378. strObjectDN += m_strObjectDN;
  379. hr = m_adsiObject.Bind (strObjectDN.c_str ());
  380. if ( SUCCEEDED (hr) )
  381. {
  382. // Get the class of strObjectDN
  383. // enumerate all classes in schema
  384. hr = m_adsiObject.QuerySchemaClasses (&m_classInfoArray, false);
  385. if ( SUCCEEDED (hr) )
  386. {
  387. /*
  388. #if DBG
  389. // Dump all the class info to the debug window
  390. _TRACE (0, L"\n----------------------------------------------------\n");
  391. _TRACE (0, L"-- Classes --\n\n");
  392. for (int nIndex = 0; nIndex < m_classInfoArray.GetCount (); nIndex++)
  393. {
  394. CSchemaClassInfo* pInfo = m_classInfoArray[nIndex];
  395. if ( pInfo )
  396. {
  397. _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (),
  398. pInfo->GetDisplayName ());
  399. }
  400. }
  401. _TRACE (0, L"\n----------------------------------------------------\n\n");
  402. #endif // DBG
  403. */
  404. // enumerate all attributes in schema
  405. hr = m_adsiObject.QuerySchemaClasses (&m_attrInfoArray,
  406. true);
  407. if ( SUCCEEDED (hr) )
  408. {
  409. /*
  410. #if DBG
  411. // Dump all the attributes info to the debug window
  412. _TRACE (0, L"\n----------------------------------------------------\n");
  413. _TRACE (0, L"-- Attributes --\n\n");
  414. for (int nIndex = 0; nIndex < m_attrInfoArray.GetCount (); nIndex++)
  415. {
  416. CSchemaClassInfo* pInfo = m_attrInfoArray[nIndex];
  417. if ( pInfo )
  418. {
  419. _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (),
  420. pInfo->GetDisplayName ());
  421. }
  422. }
  423. _TRACE (0, L"\n----------------------------------------------------\n\n");
  424. #endif // DBG
  425. */
  426. }
  427. wprintf (L"\n");
  428. }
  429. }
  430. else
  431. {
  432. wstring str;
  433. FormatMessage (str, IDS_INVALID_OBJECT, m_strObjectDN.c_str (),
  434. GetSystemMessage (hr).c_str ());
  435. wprintf (str.c_str ());
  436. }
  437. }
  438. else
  439. {
  440. wstring str;
  441. LoadFromResource (str, IDS_USER_MUST_BE_ADMINISTRATOR);
  442. wprintf (str.c_str ());
  443. }
  444. }
  445. else
  446. {
  447. wstring str;
  448. FormatMessage (str, IDS_COULD_NOT_VALIDATE_USER_CREDENTIALS,
  449. GetSystemMessage (hr).c_str ());
  450. wprintf (str.c_str ());
  451. }
  452. return hr;
  453. }
  454. HRESULT CACLDiagComModule::IsUserAdministrator (BOOL & bIsAdministrator)
  455. {
  456. bIsAdministrator = TRUE;
  457. return S_OK;
  458. /*
  459. _TRACE (1, L"Entering CACLDiagComModule::IsUserAdministrator\n");
  460. HRESULT hr = S_OK;
  461. DWORD dwErr = 0;
  462. bIsAdministrator = FALSE;
  463. if ( IsWindowsNT () )
  464. {
  465. DWORD dwInfoBufferSize = 0;
  466. PSID psidAdministrators;
  467. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  468. BOOL bResult = AllocateAndInitializeSid (&siaNtAuthority, 2,
  469. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  470. 0, 0, 0, 0, 0, 0, &psidAdministrators);
  471. if ( bResult )
  472. {
  473. bResult = CheckTokenMembership (0, psidAdministrators,
  474. &bIsAdministrator);
  475. ASSERT (bResult);
  476. if ( !bResult )
  477. {
  478. dwErr = GetLastError ();
  479. hr = HRESULT_FROM_WIN32 (dwErr);
  480. }
  481. FreeSid (psidAdministrators);
  482. }
  483. else
  484. {
  485. dwErr = GetLastError ();
  486. hr = HRESULT_FROM_WIN32 (dwErr);
  487. }
  488. }
  489. _TRACE (-1, L"Leaving CACLDiagComModule::IsUserAdministrator\n");
  490. return hr
  491. */
  492. }
  493. bool CACLDiagComModule::IsWindowsNT()
  494. {
  495. OSVERSIONINFO versionInfo;
  496. ::ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
  497. versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  498. BOOL bResult = ::GetVersionEx (&versionInfo);
  499. ASSERT (bResult);
  500. if ( bResult )
  501. {
  502. if ( VER_PLATFORM_WIN32_NT == versionInfo.dwPlatformId )
  503. bResult = TRUE;
  504. }
  505. return bResult ? true : false;
  506. }
  507. ///////////////////////////////////////////////////////////////////////////////
  508. // ACE_SAMNAME
  509. BOOL ACE_SAMNAME::operator==(const ACE_SAMNAME& rAceSAMName) const
  510. {
  511. // Neutralize INHERITED_ACE flag in Header.AceFlags
  512. // Consider equivalent if all the mask bits in 'this' are found in rAceSAMName
  513. BOOL bResult = FALSE;
  514. if ( (m_AceType == rAceSAMName.m_AceType) &&
  515. ( !this->m_SAMAccountName.compare (rAceSAMName.m_SAMAccountName)) )
  516. {
  517. switch (m_AceType)
  518. {
  519. case ACCESS_ALLOWED_ACE_TYPE:
  520. if ( m_pAllowedAce->Mask == rAceSAMName.m_pAllowedAce->Mask &&
  521. (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) ==
  522. (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) &&
  523. m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize )
  524. {
  525. bResult = TRUE;
  526. }
  527. break;
  528. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  529. if ( m_pAllowedObjectAce->Mask == rAceSAMName.m_pAllowedObjectAce->Mask &&
  530. (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  531. (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  532. m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize &&
  533. ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) )
  534. {
  535. bResult = TRUE;
  536. }
  537. break;
  538. case ACCESS_DENIED_ACE_TYPE:
  539. if ( m_pDeniedAce->Mask == rAceSAMName.m_pDeniedAce->Mask &&
  540. (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) ==
  541. (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) &&
  542. m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize )
  543. {
  544. bResult = TRUE;
  545. }
  546. break;
  547. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  548. if ( m_pDeniedObjectAce->Mask == rAceSAMName.m_pDeniedObjectAce->Mask &&
  549. (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  550. (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  551. m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize &&
  552. ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) )
  553. {
  554. bResult = TRUE;
  555. }
  556. break;
  557. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  558. if ( m_pSystemAuditObjectAce->Mask == rAceSAMName.m_pSystemAuditObjectAce->Mask &&
  559. (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  560. (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  561. m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize &&
  562. ::IsEqualGUID (m_pSystemAuditObjectAce->ObjectType, rAceSAMName.m_pSystemAuditObjectAce->ObjectType) )
  563. {
  564. bResult = TRUE;
  565. }
  566. break;
  567. case SYSTEM_AUDIT_ACE_TYPE:
  568. if ( m_pSystemAuditAce->Mask == rAceSAMName.m_pSystemAuditAce->Mask &&
  569. (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) ==
  570. (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) &&
  571. m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize )
  572. {
  573. bResult = TRUE;
  574. }
  575. break;
  576. default:
  577. break;
  578. }
  579. }
  580. return bResult;
  581. }
  582. BOOL ACE_SAMNAME::IsEquivalent (ACE_SAMNAME& rAceSAMName, ACCESS_MASK accessMask)
  583. {
  584. // Neutralize INHERITED_ACE flag in Header.AceFlags
  585. BOOL bResult = FALSE;
  586. if ( m_AceType == rAceSAMName.m_AceType )
  587. {
  588. switch (m_AceType)
  589. {
  590. case ACCESS_ALLOWED_ACE_TYPE:
  591. if ( (m_pAllowedAce->Mask & accessMask) ==
  592. (rAceSAMName.m_pAllowedAce->Mask & accessMask) &&
  593. m_pAllowedAce->SidStart == rAceSAMName.m_pAllowedAce->SidStart &&
  594. (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) ==
  595. (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) &&
  596. m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize )
  597. {
  598. bResult = TRUE;
  599. }
  600. break;
  601. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  602. if ( (m_pAllowedObjectAce->Mask & accessMask) ==
  603. (rAceSAMName.m_pAllowedObjectAce->Mask & accessMask) &&
  604. m_pAllowedObjectAce->SidStart == rAceSAMName.m_pAllowedObjectAce->SidStart &&
  605. (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  606. (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  607. m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize &&
  608. ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) )
  609. {
  610. bResult = TRUE;
  611. }
  612. break;
  613. case ACCESS_DENIED_ACE_TYPE:
  614. if ( (m_pDeniedAce->Mask & accessMask) ==
  615. (rAceSAMName.m_pDeniedAce->Mask & accessMask) &&
  616. m_pDeniedAce->SidStart == rAceSAMName.m_pDeniedAce->SidStart &&
  617. (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) ==
  618. (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) &&
  619. m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize )
  620. {
  621. bResult = TRUE;
  622. }
  623. break;
  624. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  625. if ( (m_pDeniedObjectAce->Mask & accessMask) ==
  626. (rAceSAMName.m_pDeniedObjectAce->Mask & accessMask) &&
  627. m_pDeniedObjectAce->SidStart == rAceSAMName.m_pDeniedObjectAce->SidStart &&
  628. (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  629. (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  630. m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize &&
  631. ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) )
  632. {
  633. bResult = TRUE;
  634. }
  635. break;
  636. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  637. if ( (m_pSystemAuditObjectAce->Mask & accessMask) ==
  638. (rAceSAMName.m_pSystemAuditObjectAce->Mask & accessMask) &&
  639. m_pSystemAuditObjectAce->SidStart == rAceSAMName.m_pSystemAuditObjectAce->SidStart &&
  640. (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  641. (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  642. m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize )
  643. {
  644. bResult = TRUE;
  645. }
  646. break;
  647. case SYSTEM_AUDIT_ACE_TYPE:
  648. if ( (m_pSystemAuditAce->Mask & accessMask) ==
  649. (rAceSAMName.m_pSystemAuditAce->Mask & accessMask) &&
  650. m_pSystemAuditAce->SidStart == rAceSAMName.m_pSystemAuditAce->SidStart &&
  651. (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) ==
  652. (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) &&
  653. m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize )
  654. {
  655. bResult = TRUE;
  656. }
  657. break;
  658. default:
  659. break;
  660. }
  661. }
  662. return bResult;
  663. }
  664. bool ACE_SAMNAME::IsInherited() const
  665. {
  666. return (m_pAllowedAce->Header.AceFlags & INHERITED_ACE) ? true : false;
  667. }
  668. void ACE_SAMNAME::DebugOut() const
  669. {
  670. #if DBG == 1
  671. wstring strGuidResult;
  672. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  673. _TRACE (0, L"\n");
  674. _TRACE (0, L"Principal Name: %s\n", m_SAMAccountName.c_str ());
  675. switch (m_AceType)
  676. {
  677. case ACCESS_ALLOWED_ACE_TYPE:
  678. _TRACE (0, L"AceType: ACCESS_ALLOWED_ACE_TYPE\n");
  679. _TRACE (0, L"Mask: 0x%x\n", m_pAllowedAce->Mask);
  680. _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedAce->Header.AceFlags);
  681. _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedAce->Header.AceSize);
  682. break;
  683. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  684. _TRACE (0, L"AceType: ACCESS_ALLOWED_OBJECT_ACE_TYPE\n");
  685. _TRACE (0, L"Mask: 0x%x\n", m_pAllowedObjectAce->Mask);
  686. _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedObjectAce->Header.AceFlags);
  687. _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedObjectAce->Header.AceSize);
  688. _Module.GetClassFromGUID (m_pAllowedObjectAce->ObjectType, strGuidResult, &guidType);
  689. break;
  690. case ACCESS_DENIED_ACE_TYPE:
  691. _TRACE (0, L"AceType: ACCESS_DENIED_ACE_TYPE\n");
  692. _TRACE (0, L"Mask: 0x%x\n", m_pDeniedAce->Mask);
  693. _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedAce->Header.AceFlags);
  694. _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedAce->Header.AceSize);
  695. break;
  696. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  697. _TRACE (0, L"AceType: ACCESS_DENIED_OBJECT_ACE_TYPE\n");
  698. _TRACE (0, L"Mask: 0x%x\n", m_pDeniedObjectAce->Mask);
  699. _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedObjectAce->Header.AceFlags);
  700. _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedObjectAce->Header.AceSize);
  701. _Module.GetClassFromGUID (m_pDeniedObjectAce->ObjectType, strGuidResult, &guidType);
  702. break;
  703. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  704. _TRACE (0, L"AceType: SYSTEM_AUDIT_OBJECT_ACE_TYPE\n");
  705. _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditObjectAce->Mask);
  706. _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditObjectAce->Header.AceFlags);
  707. _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditObjectAce->Header.AceSize);
  708. _Module.GetClassFromGUID (m_pSystemAuditObjectAce->ObjectType, strGuidResult, &guidType);
  709. break;
  710. case SYSTEM_AUDIT_ACE_TYPE:
  711. _TRACE (0, L"AceType: SYSTEM_AUDIT_ACE_TYPE\n");
  712. _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditAce->Mask);
  713. _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditAce->Header.AceFlags);
  714. _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditAce->Header.AceSize);
  715. break;
  716. }
  717. if ( IsObjectAceType (m_pAllowedAce) )
  718. {
  719. wstring strGuidType;
  720. switch (guidType)
  721. {
  722. case GUID_TYPE_CLASS:
  723. strGuidType = L"GUID_TYPE_CLASS";
  724. break;
  725. case GUID_TYPE_ATTRIBUTE:
  726. strGuidType = L"GUID_TYPE_ATTRIBUTE";
  727. break;
  728. case GUID_TYPE_CONTROL:
  729. strGuidType = L"GUID_TYPE_CONTROL";
  730. break;
  731. default:
  732. #pragma warning (disable : 4127)
  733. ASSERT (0);
  734. #pragma warning (default : 4127)
  735. // fall through
  736. case GUID_TYPE_UNKNOWN:
  737. strGuidType = L"GUID_TYPE_UNKNOWN";
  738. break;
  739. }
  740. _TRACE (0, L"ObjectType type: %s\n", strGuidType.c_str ());
  741. _TRACE (0, L"ObjectType value: %s\n", strGuidResult.c_str ());
  742. }
  743. _TRACE (0, L"\n");
  744. #endif
  745. }
  746. ///////////////////////////////////////////////////////////////////////////////
  747. HRESULT
  748. SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
  749. {
  750. HRESULT hr = E_INVALIDARG;
  751. if (punk)
  752. {
  753. IADsObjectOptions *pOptions;
  754. hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
  755. if (SUCCEEDED(hr))
  756. {
  757. VARIANT var;
  758. V_VT(&var) = VT_I4;
  759. V_I4(&var) = si;
  760. hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
  761. pOptions->Release();
  762. }
  763. }
  764. return hr;
  765. }
  766. ///////////////////////////////////////////////////////////////////////////////
  767. /*******************************************************************
  768. NAME: EnablePrivileges
  769. SYNOPSIS: Enables the given privileges in the current token
  770. ENTRY: pdwPrivileges - list of privileges to enable
  771. RETURNS: On success, the previous thread handle (if present) or NULL
  772. On failure, INVALID_HANDLE_VALUE
  773. NOTES: The returned handle should be passed to ReleasePrivileges
  774. to ensure proper cleanup. Otherwise, if not NULL or
  775. INVALID_HANDLE_VALUE it should be closed with CloseHandle.
  776. HISTORY:
  777. JeffreyS 08-Oct-1996 Created
  778. ********************************************************************/
  779. HANDLE EnablePrivileges(PDWORD pdwPrivileges, ULONG cPrivileges)
  780. {
  781. BOOL fResult;
  782. HANDLE hToken;
  783. HANDLE hOriginalThreadToken;
  784. PTOKEN_PRIVILEGES ptp;
  785. ULONG nBufferSize;
  786. if (!pdwPrivileges || !cPrivileges)
  787. return INVALID_HANDLE_VALUE;
  788. // Note that TOKEN_PRIVILEGES includes a single LUID_AND_ATTRIBUTES
  789. nBufferSize = sizeof(TOKEN_PRIVILEGES) + (cPrivileges - 1) *
  790. sizeof(LUID_AND_ATTRIBUTES);
  791. ptp = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, nBufferSize);
  792. if (!ptp)
  793. return INVALID_HANDLE_VALUE;
  794. //
  795. // Initialize the Privileges Structure
  796. //
  797. ptp->PrivilegeCount = cPrivileges;
  798. for (ULONG i = 0; i < cPrivileges; i++)
  799. {
  800. //ptp->Privileges[i].Luid = RtlConvertUlongToLuid(*pdwPrivileges++);
  801. ptp->Privileges[i].Luid.LowPart = *pdwPrivileges++;
  802. ptp->Privileges[i].Luid.HighPart = 0;
  803. ptp->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
  804. }
  805. //
  806. // Open the Token
  807. //
  808. hToken = hOriginalThreadToken = INVALID_HANDLE_VALUE;
  809. fResult = OpenThreadToken (GetCurrentThread (), TOKEN_DUPLICATE, FALSE,
  810. &hToken);
  811. if (fResult)
  812. hOriginalThreadToken = hToken; // Remember the thread token
  813. else
  814. fResult = OpenProcessToken (GetCurrentProcess(), TOKEN_DUPLICATE,
  815. &hToken);
  816. if (fResult)
  817. {
  818. HANDLE hNewToken;
  819. //
  820. // Duplicate that Token
  821. //
  822. fResult = DuplicateTokenEx(hToken,
  823. TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  824. NULL, // PSECURITY_ATTRIBUTES
  825. SecurityImpersonation, // SECURITY_IMPERSONATION_LEVEL
  826. TokenImpersonation, // TokenType
  827. &hNewToken); // Duplicate token
  828. if (fResult)
  829. {
  830. //
  831. // Add new privileges
  832. //
  833. fResult = AdjustTokenPrivileges(hNewToken, // TokenHandle
  834. FALSE, // DisableAllPrivileges
  835. ptp, // NewState
  836. 0, // BufferLength
  837. NULL, // PreviousState
  838. NULL); // ReturnLength
  839. if (fResult)
  840. {
  841. //
  842. // Begin impersonating with the new token
  843. //
  844. fResult = SetThreadToken(NULL, hNewToken);
  845. }
  846. CloseHandle(hNewToken);
  847. }
  848. }
  849. // If something failed, don't return a token
  850. if (!fResult)
  851. hOriginalThreadToken = INVALID_HANDLE_VALUE;
  852. // Close the original token if we aren't returning it
  853. if (hOriginalThreadToken == INVALID_HANDLE_VALUE &&
  854. hToken != INVALID_HANDLE_VALUE)
  855. {
  856. CloseHandle(hToken);
  857. }
  858. // If we succeeded, but there was no original thread token,
  859. // return NULL to indicate we need to do SetThreadToken(NULL, NULL)
  860. // to release privs.
  861. if (fResult && hOriginalThreadToken == INVALID_HANDLE_VALUE)
  862. hOriginalThreadToken = NULL;
  863. LocalFree(ptp);
  864. return hOriginalThreadToken;
  865. }
  866. /*******************************************************************
  867. NAME: ReleasePrivileges
  868. SYNOPSIS: Resets privileges to the state prior to the corresponding
  869. EnablePrivileges call.
  870. ENTRY: hToken - result of call to EnablePrivileges
  871. RETURNS: nothing
  872. HISTORY:
  873. JeffreyS 08-Oct-1996 Created
  874. ********************************************************************/
  875. void ReleasePrivileges(HANDLE hToken)
  876. {
  877. if (INVALID_HANDLE_VALUE != hToken)
  878. {
  879. SetThreadToken(NULL, hToken);
  880. if (hToken)
  881. CloseHandle(hToken);
  882. }
  883. }
  884. VOID LocalFreeStringW(LPWSTR* ppString)
  885. {
  886. if ( ppString && *ppString )
  887. {
  888. LocalFree((HLOCAL)*ppString);
  889. *ppString = NULL;
  890. }
  891. }
  892. ///////////////////////////////////////////////////////////////////////////////
  893. //
  894. // Method: GetNameFromSid ()
  895. //
  896. // Purpose: Get the name of the object represented by this Sid
  897. //
  898. // Inputs: pSid - SID of the object whose name we wish to retrieve
  899. //
  900. // Outputs: strPrincipalName - name of the object in NameUserPrincipal
  901. // pstrFQDN - (optional) name of the object as Fully Qualified DN
  902. //
  903. HRESULT GetNameFromSid (
  904. PSID pSid,
  905. wstring& strPrincipalName,
  906. wstring* pstrFQDN,
  907. SID_NAME_USE& sne)
  908. {
  909. ASSERT (IsValidSid (pSid));
  910. if ( !IsValidSid (pSid) )
  911. return E_INVALIDARG;
  912. WCHAR szName[MAX_PATH];
  913. WCHAR szDomain[MAX_PATH];
  914. DWORD cchName = MAX_PATH-1;
  915. DWORD cchDomain = MAX_PATH-1;
  916. HRESULT hr = S_OK;
  917. if ( LookupAccountSid (NULL, pSid,
  918. szName, &cchName, szDomain,
  919. &cchDomain, &sne) )
  920. {
  921. wstring strSamCompatibleName (szDomain);
  922. strSamCompatibleName += L"\\";
  923. strSamCompatibleName += szName;
  924. // Get Principal Name
  925. {
  926. PWSTR pszTranslatedName = 0;
  927. hr = CrackName(const_cast<PWSTR> (strSamCompatibleName.c_str ()),
  928. &pszTranslatedName,
  929. GET_OBJ_UPN, //GET_OBJ_NT4_NAME,
  930. 0);
  931. if ( SUCCEEDED (hr) )
  932. {
  933. strPrincipalName = pszTranslatedName;
  934. LocalFreeStringW(&pszTranslatedName);
  935. }
  936. else
  937. {
  938. strPrincipalName = strSamCompatibleName;
  939. }
  940. }
  941. // Get fully qualified DN
  942. if ( pstrFQDN )
  943. {
  944. PWSTR pszTranslatedName = 0;
  945. hr = CrackName(const_cast<PWSTR> (strSamCompatibleName.c_str ()),
  946. &pszTranslatedName,
  947. GET_OBJ_1779_DN,
  948. 0);
  949. if ( SUCCEEDED (hr) )
  950. {
  951. *pstrFQDN = pszTranslatedName;
  952. LocalFreeStringW(&pszTranslatedName);
  953. }
  954. else
  955. {
  956. *pstrFQDN = strSamCompatibleName;
  957. }
  958. }
  959. }
  960. else
  961. {
  962. DWORD dwErr = GetLastError ();
  963. _TRACE (0, L"LookupAccountSid failed: 0x%x\n", dwErr);
  964. if ( ERROR_NONE_MAPPED == dwErr )
  965. {
  966. PWSTR pszStringSid = 0;
  967. if ( ::ConvertSidToStringSid (pSid, &pszStringSid) )
  968. {
  969. strPrincipalName = pszStringSid;
  970. if ( pstrFQDN )
  971. *pstrFQDN = pszStringSid;
  972. ::LocalFree (pszStringSid);
  973. }
  974. else
  975. hr = E_OUTOFMEMORY;
  976. }
  977. else
  978. hr = HRESULT_FROM_WIN32 (dwErr);
  979. }
  980. return hr;
  981. }
  982. #define MAX_BUF_SIZE 4096
  983. CHAR AnsiBuf[MAX_BUF_SIZE*3]; /* worst case is DBCS, which */
  984. /* needs more than *2 */
  985. TCHAR ConBuf [MAX_BUF_SIZE];
  986. int FileIsConsole(HANDLE fh)
  987. {
  988. unsigned htype ;
  989. htype = GetFileType(fh);
  990. htype &= ~FILE_TYPE_REMOTE;
  991. return htype == FILE_TYPE_CHAR;
  992. }
  993. int MyWriteConsole(int fOutOrErr)
  994. {
  995. DWORD cch = (DWORD) _tcslen(ConBuf);
  996. HANDLE hOut;
  997. if (fOutOrErr == 1)
  998. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  999. else
  1000. hOut = GetStdHandle(STD_ERROR_HANDLE);
  1001. if (FileIsConsole(hOut))
  1002. WriteConsole(hOut, ConBuf, cch, &cch, NULL);
  1003. else {
  1004. cch = WideCharToMultiByte(CP_OEMCP, 0,
  1005. ConBuf, (int) cch,
  1006. AnsiBuf, MAX_BUF_SIZE*3,
  1007. NULL, NULL);
  1008. WriteFile(hOut, AnsiBuf, cch, &cch, NULL);
  1009. }
  1010. return (int) cch;
  1011. }
  1012. int MyWprintf( const wchar_t *fmt, ... )
  1013. {
  1014. va_list args;
  1015. va_start( args, fmt );
  1016. _vsnwprintf( ConBuf, MAX_BUF_SIZE, fmt, args );
  1017. va_end( args );
  1018. return MyWriteConsole(1);
  1019. }