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.

1258 lines
40 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999-2002.
  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. bool bRVal = false;
  199. bool bDone = true;
  200. do
  201. {
  202. LPWSTR lpszBuffer = new WCHAR[nBufferSize];
  203. if ( lpszBuffer )
  204. {
  205. int iRet = ::LoadString(_Module.GetResourceInstance(), uID,
  206. lpszBuffer, nBufferSize);
  207. if (iRet == 0)
  208. {
  209. str = L"?";
  210. bDone = true; // not found
  211. }
  212. if (iRet == nBufferSize-1) // truncation
  213. {
  214. if (nCount > nCountMax)
  215. {
  216. // too many reallocations
  217. str = lpszBuffer;
  218. bRVal = false; // truncation
  219. }
  220. // try to expand buffer
  221. nBufferSize *=2;
  222. nCount++;
  223. }
  224. else
  225. {
  226. // got it
  227. str = lpszBuffer;
  228. bRVal = true;
  229. bDone = true;
  230. }
  231. delete [] lpszBuffer;
  232. if ( bDone )
  233. break;
  234. }
  235. else
  236. break;
  237. }
  238. #pragma warning (disable : 4127)
  239. while (true);
  240. #pragma warning (default : 4127)
  241. return bRVal;
  242. }
  243. bool FormatMessage(wstring& str, UINT nFormatID, ...)
  244. {
  245. bool bResult = false;
  246. // get format string from string table
  247. wstring strFormat;
  248. if ( LoadFromResource (strFormat, nFormatID) )
  249. {
  250. // format message into temporary buffer lpszTemp
  251. va_list argList;
  252. va_start(argList, nFormatID);
  253. PWSTR lpszTemp = 0;
  254. if (::FormatMessage (FORMAT_MESSAGE_FROM_STRING |
  255. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  256. strFormat.c_str (), 0, 0, (PWSTR)&lpszTemp, 0, &argList) == 0 ||
  257. lpszTemp == NULL)
  258. {
  259. return false;
  260. }
  261. // assign lpszTemp into the resulting string and free lpszTemp
  262. str = lpszTemp;
  263. bResult = true;
  264. LocalFree(lpszTemp);
  265. va_end(argList);
  266. }
  267. return bResult;
  268. }
  269. bool FormatMessage(wstring& str, LPCTSTR lpszFormat, ...)
  270. {
  271. bool bResult = false;
  272. // format message into temporary buffer lpszTemp
  273. va_list argList;
  274. va_start(argList, lpszFormat);
  275. LPTSTR lpszTemp;
  276. if ( ::FormatMessage (FORMAT_MESSAGE_FROM_STRING |
  277. FORMAT_MESSAGE_ALLOCATE_BUFFER,
  278. lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
  279. lpszTemp == NULL)
  280. {
  281. return false; //AfxThrowMemoryException();
  282. }
  283. // assign lpszTemp into the resulting string and free the temporary
  284. str = lpszTemp;
  285. bResult = true;
  286. LocalFree(lpszTemp);
  287. va_end(argList);
  288. return bResult;
  289. }
  290. ///////////////////////////////////////////////////////////////////////////////
  291. // CACLDiagComModule
  292. CACLDiagComModule::CACLDiagComModule() :
  293. m_bDoSchema (false),
  294. m_bDoCheckDelegation (false),
  295. m_bDoGetEffective (false),
  296. m_bDoFixDelegation (false),
  297. m_pSecurityDescriptor (0),
  298. m_bTabDelimitedOutput (false),
  299. m_hPrivToken (0),
  300. m_bLogErrors (false)
  301. {
  302. DWORD dwPriv = SE_SECURITY_PRIVILEGE;
  303. m_hPrivToken = EnablePrivileges(&dwPriv, 1);
  304. }
  305. CACLDiagComModule::~CACLDiagComModule ()
  306. {
  307. if ( m_pSecurityDescriptor )
  308. {
  309. LocalFree (m_pSecurityDescriptor);
  310. m_pSecurityDescriptor = 0;
  311. }
  312. ReleasePrivileges(m_hPrivToken);
  313. }
  314. HRESULT CACLDiagComModule::GetClassFromGUID (
  315. REFGUID rightsGUID,
  316. wstring& strClassName,
  317. GUID_TYPE* pGuidType)
  318. {
  319. HRESULT hr = S_OK;
  320. CSchemaClassInfo* pInfo = 0;
  321. bool bFound = false;
  322. // Search for a class
  323. for (int nIndex = 0; nIndex < (int) m_classInfoArray.GetCount (); nIndex++)
  324. {
  325. pInfo = m_classInfoArray[nIndex];
  326. if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()),
  327. rightsGUID) )
  328. {
  329. PCWSTR pszDisplayName = pInfo->GetDisplayName ();
  330. strClassName = pszDisplayName ? pszDisplayName : L"";
  331. bFound = true;
  332. if ( pGuidType )
  333. *pGuidType = GUID_TYPE_CLASS;
  334. break;
  335. }
  336. }
  337. // Search for an attribute
  338. if ( !bFound )
  339. {
  340. for (int nIndex = 0; nIndex < (int) m_attrInfoArray.GetCount (); nIndex++)
  341. {
  342. pInfo = m_attrInfoArray[nIndex];
  343. if ( pInfo && IsEqualGUID (*(pInfo->GetSchemaGUID ()),
  344. rightsGUID) )
  345. {
  346. PCWSTR pszDisplayName = pInfo->GetDisplayName ();
  347. strClassName = pszDisplayName ? pszDisplayName : L"";
  348. bFound = true;
  349. if ( pGuidType )
  350. *pGuidType = GUID_TYPE_ATTRIBUTE;
  351. break;
  352. }
  353. }
  354. }
  355. // Search for a control
  356. if ( !bFound )
  357. {
  358. hr = GetControlDisplayName (rightsGUID, strClassName);
  359. if ( SUCCEEDED (hr) && strClassName.length () )
  360. {
  361. if ( pGuidType )
  362. *pGuidType = GUID_TYPE_CONTROL;
  363. }
  364. else
  365. {
  366. if ( pGuidType )
  367. *pGuidType = GUID_TYPE_UNKNOWN;
  368. strClassName = L"unknown";
  369. }
  370. }
  371. return hr;
  372. }
  373. HRESULT CACLDiagComModule::Init()
  374. {
  375. // Find out if logged-in users is an Administrator
  376. BOOL bIsUserAdministrator = FALSE;
  377. HRESULT hr = IsUserAdministrator (bIsUserAdministrator);
  378. if ( SUCCEEDED (hr) )
  379. {
  380. if ( bIsUserAdministrator )
  381. {
  382. wstring strObjectDN;
  383. LPCWSTR pszLDAP = L"LDAP://";
  384. size_t len = wcslen (pszLDAP);
  385. if ( m_strObjectDN.compare (0, len, pszLDAP) )
  386. {
  387. strObjectDN = pszLDAP;
  388. }
  389. strObjectDN += m_strObjectDN;
  390. hr = m_adsiObject.Bind (strObjectDN.c_str ());
  391. if ( SUCCEEDED (hr) )
  392. {
  393. // Get the class of strObjectDN
  394. // enumerate all classes in schema
  395. hr = m_adsiObject.QuerySchemaClasses (&m_classInfoArray, false);
  396. if ( SUCCEEDED (hr) )
  397. {
  398. /*
  399. #if DBG
  400. // Dump all the class info to the debug window
  401. _TRACE (0, L"\n----------------------------------------------------\n");
  402. _TRACE (0, L"-- Classes --\n\n");
  403. for (int nIndex = 0; nIndex < m_classInfoArray.GetCount (); nIndex++)
  404. {
  405. CSchemaClassInfo* pInfo = m_classInfoArray[nIndex];
  406. if ( pInfo )
  407. {
  408. _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (),
  409. pInfo->GetDisplayName ());
  410. }
  411. }
  412. _TRACE (0, L"\n----------------------------------------------------\n\n");
  413. #endif // DBG
  414. */
  415. // enumerate all attributes in schema
  416. hr = m_adsiObject.QuerySchemaClasses (&m_attrInfoArray,
  417. true);
  418. if ( SUCCEEDED (hr) )
  419. {
  420. /*
  421. #if DBG
  422. // Dump all the attributes info to the debug window
  423. _TRACE (0, L"\n----------------------------------------------------\n");
  424. _TRACE (0, L"-- Attributes --\n\n");
  425. for (int nIndex = 0; nIndex < m_attrInfoArray.GetCount (); nIndex++)
  426. {
  427. CSchemaClassInfo* pInfo = m_attrInfoArray[nIndex];
  428. if ( pInfo )
  429. {
  430. _TRACE (0, L"\t%d\t%s\t%s\n", nIndex, pInfo->GetSchemaIDGUID (),
  431. pInfo->GetDisplayName ());
  432. }
  433. }
  434. _TRACE (0, L"\n----------------------------------------------------\n\n");
  435. #endif // DBG
  436. */
  437. }
  438. wprintf (L"\n");
  439. }
  440. }
  441. else
  442. {
  443. wstring str;
  444. FormatMessage (str, IDS_INVALID_OBJECT, m_strObjectDN.c_str (),
  445. GetSystemMessage (hr).c_str ());
  446. MyWprintf (str.c_str ());
  447. }
  448. }
  449. else
  450. {
  451. wstring str;
  452. LoadFromResource (str, IDS_USER_MUST_BE_ADMINISTRATOR);
  453. MyWprintf (str.c_str ());
  454. }
  455. }
  456. else
  457. {
  458. wstring str;
  459. FormatMessage (str, IDS_COULD_NOT_VALIDATE_USER_CREDENTIALS,
  460. GetSystemMessage (hr).c_str ());
  461. MyWprintf (str.c_str ());
  462. }
  463. return hr;
  464. }
  465. HRESULT CACLDiagComModule::IsUserAdministrator (BOOL & bIsAdministrator)
  466. {
  467. bIsAdministrator = TRUE;
  468. return S_OK;
  469. /*
  470. _TRACE (1, L"Entering CACLDiagComModule::IsUserAdministrator\n");
  471. HRESULT hr = S_OK;
  472. DWORD dwErr = 0;
  473. bIsAdministrator = FALSE;
  474. if ( IsWindowsNT () )
  475. {
  476. DWORD dwInfoBufferSize = 0;
  477. PSID psidAdministrators;
  478. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  479. BOOL bResult = AllocateAndInitializeSid (&siaNtAuthority, 2,
  480. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  481. 0, 0, 0, 0, 0, 0, &psidAdministrators);
  482. if ( bResult )
  483. {
  484. bResult = CheckTokenMembership (0, psidAdministrators,
  485. &bIsAdministrator);
  486. ASSERT (bResult);
  487. if ( !bResult )
  488. {
  489. dwErr = GetLastError ();
  490. hr = HRESULT_FROM_WIN32 (dwErr);
  491. }
  492. FreeSid (psidAdministrators);
  493. }
  494. else
  495. {
  496. dwErr = GetLastError ();
  497. hr = HRESULT_FROM_WIN32 (dwErr);
  498. }
  499. }
  500. _TRACE (-1, L"Leaving CACLDiagComModule::IsUserAdministrator\n");
  501. return hr
  502. */
  503. }
  504. bool CACLDiagComModule::IsWindowsNT()
  505. {
  506. OSVERSIONINFO versionInfo;
  507. ::ZeroMemory (&versionInfo, sizeof (OSVERSIONINFO));
  508. versionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  509. BOOL bResult = ::GetVersionEx (&versionInfo);
  510. ASSERT (bResult);
  511. if ( bResult )
  512. {
  513. if ( VER_PLATFORM_WIN32_NT == versionInfo.dwPlatformId )
  514. bResult = TRUE;
  515. }
  516. return bResult ? true : false;
  517. }
  518. ///////////////////////////////////////////////////////////////////////////////
  519. // ACE_SAMNAME
  520. BOOL ACE_SAMNAME::operator==(const ACE_SAMNAME& rAceSAMName) const
  521. {
  522. // Neutralize INHERITED_ACE flag in Header.AceFlags
  523. // Consider equivalent if all the mask bits in 'this' are found in rAceSAMName
  524. BOOL bResult = FALSE;
  525. if ( (m_AceType == rAceSAMName.m_AceType) &&
  526. ( !this->m_SAMAccountName.compare (rAceSAMName.m_SAMAccountName)) )
  527. {
  528. switch (m_AceType)
  529. {
  530. case ACCESS_ALLOWED_ACE_TYPE:
  531. if ( m_pAllowedAce->Mask == rAceSAMName.m_pAllowedAce->Mask &&
  532. (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) ==
  533. (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) &&
  534. m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize )
  535. {
  536. bResult = TRUE;
  537. }
  538. break;
  539. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  540. if ( m_pAllowedObjectAce->Mask == rAceSAMName.m_pAllowedObjectAce->Mask &&
  541. (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  542. (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  543. m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize &&
  544. ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) )
  545. {
  546. bResult = TRUE;
  547. }
  548. break;
  549. case ACCESS_DENIED_ACE_TYPE:
  550. if ( m_pDeniedAce->Mask == rAceSAMName.m_pDeniedAce->Mask &&
  551. (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) ==
  552. (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) &&
  553. m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize )
  554. {
  555. bResult = TRUE;
  556. }
  557. break;
  558. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  559. if ( m_pDeniedObjectAce->Mask == rAceSAMName.m_pDeniedObjectAce->Mask &&
  560. (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  561. (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  562. m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize &&
  563. ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) )
  564. {
  565. bResult = TRUE;
  566. }
  567. break;
  568. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  569. if ( m_pSystemAuditObjectAce->Mask == rAceSAMName.m_pSystemAuditObjectAce->Mask &&
  570. (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  571. (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  572. m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize &&
  573. ::IsEqualGUID (m_pSystemAuditObjectAce->ObjectType, rAceSAMName.m_pSystemAuditObjectAce->ObjectType) )
  574. {
  575. bResult = TRUE;
  576. }
  577. break;
  578. case SYSTEM_AUDIT_ACE_TYPE:
  579. if ( m_pSystemAuditAce->Mask == rAceSAMName.m_pSystemAuditAce->Mask &&
  580. (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) ==
  581. (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) &&
  582. m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize )
  583. {
  584. bResult = TRUE;
  585. }
  586. break;
  587. default:
  588. break;
  589. }
  590. }
  591. return bResult;
  592. }
  593. BOOL ACE_SAMNAME::IsEquivalent (ACE_SAMNAME& rAceSAMName, ACCESS_MASK accessMask)
  594. {
  595. // Neutralize INHERITED_ACE flag in Header.AceFlags
  596. BOOL bResult = FALSE;
  597. if ( m_AceType == rAceSAMName.m_AceType )
  598. {
  599. switch (m_AceType)
  600. {
  601. case ACCESS_ALLOWED_ACE_TYPE:
  602. if ( (m_pAllowedAce->Mask & accessMask) ==
  603. (rAceSAMName.m_pAllowedAce->Mask & accessMask) &&
  604. m_pAllowedAce->SidStart == rAceSAMName.m_pAllowedAce->SidStart &&
  605. (m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) ==
  606. (rAceSAMName.m_pAllowedAce->Header.AceFlags | INHERITED_ACE ) &&
  607. m_pAllowedAce->Header.AceSize == rAceSAMName.m_pAllowedAce->Header.AceSize )
  608. {
  609. bResult = TRUE;
  610. }
  611. break;
  612. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  613. if ( (m_pAllowedObjectAce->Mask & accessMask) ==
  614. (rAceSAMName.m_pAllowedObjectAce->Mask & accessMask) &&
  615. m_pAllowedObjectAce->SidStart == rAceSAMName.m_pAllowedObjectAce->SidStart &&
  616. (m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  617. (rAceSAMName.m_pAllowedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  618. m_pAllowedObjectAce->Header.AceSize == rAceSAMName.m_pAllowedObjectAce->Header.AceSize &&
  619. ::IsEqualGUID (m_pAllowedObjectAce->ObjectType, rAceSAMName.m_pAllowedObjectAce->ObjectType) )
  620. {
  621. bResult = TRUE;
  622. }
  623. break;
  624. case ACCESS_DENIED_ACE_TYPE:
  625. if ( (m_pDeniedAce->Mask & accessMask) ==
  626. (rAceSAMName.m_pDeniedAce->Mask & accessMask) &&
  627. m_pDeniedAce->SidStart == rAceSAMName.m_pDeniedAce->SidStart &&
  628. (m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) ==
  629. (rAceSAMName.m_pDeniedAce->Header.AceFlags | INHERITED_ACE ) &&
  630. m_pDeniedAce->Header.AceSize == rAceSAMName.m_pDeniedAce->Header.AceSize )
  631. {
  632. bResult = TRUE;
  633. }
  634. break;
  635. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  636. if ( (m_pDeniedObjectAce->Mask & accessMask) ==
  637. (rAceSAMName.m_pDeniedObjectAce->Mask & accessMask) &&
  638. m_pDeniedObjectAce->SidStart == rAceSAMName.m_pDeniedObjectAce->SidStart &&
  639. (m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  640. (rAceSAMName.m_pDeniedObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  641. m_pDeniedObjectAce->Header.AceSize == rAceSAMName.m_pDeniedObjectAce->Header.AceSize &&
  642. ::IsEqualGUID (m_pDeniedObjectAce->ObjectType, rAceSAMName.m_pDeniedObjectAce->ObjectType) )
  643. {
  644. bResult = TRUE;
  645. }
  646. break;
  647. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  648. if ( (m_pSystemAuditObjectAce->Mask & accessMask) ==
  649. (rAceSAMName.m_pSystemAuditObjectAce->Mask & accessMask) &&
  650. m_pSystemAuditObjectAce->SidStart == rAceSAMName.m_pSystemAuditObjectAce->SidStart &&
  651. (m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) ==
  652. (rAceSAMName.m_pSystemAuditObjectAce->Header.AceFlags | INHERITED_ACE ) &&
  653. m_pSystemAuditObjectAce->Header.AceSize == rAceSAMName.m_pSystemAuditObjectAce->Header.AceSize )
  654. {
  655. bResult = TRUE;
  656. }
  657. break;
  658. case SYSTEM_AUDIT_ACE_TYPE:
  659. if ( (m_pSystemAuditAce->Mask & accessMask) ==
  660. (rAceSAMName.m_pSystemAuditAce->Mask & accessMask) &&
  661. m_pSystemAuditAce->SidStart == rAceSAMName.m_pSystemAuditAce->SidStart &&
  662. (m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) ==
  663. (rAceSAMName.m_pSystemAuditAce->Header.AceFlags | INHERITED_ACE ) &&
  664. m_pSystemAuditAce->Header.AceSize == rAceSAMName.m_pSystemAuditAce->Header.AceSize )
  665. {
  666. bResult = TRUE;
  667. }
  668. break;
  669. default:
  670. break;
  671. }
  672. }
  673. return bResult;
  674. }
  675. bool ACE_SAMNAME::IsInherited() const
  676. {
  677. return (m_pAllowedAce->Header.AceFlags & INHERITED_ACE) ? true : false;
  678. }
  679. void ACE_SAMNAME::DebugOut() const
  680. {
  681. #if DBG == 1
  682. wstring strGuidResult;
  683. GUID_TYPE guidType = GUID_TYPE_UNKNOWN;
  684. _TRACE (0, L"\n");
  685. _TRACE (0, L"Principal Name: %s\n", m_SAMAccountName.c_str ());
  686. switch (m_AceType)
  687. {
  688. case ACCESS_ALLOWED_ACE_TYPE:
  689. _TRACE (0, L"AceType: ACCESS_ALLOWED_ACE_TYPE\n");
  690. _TRACE (0, L"Mask: 0x%x\n", m_pAllowedAce->Mask);
  691. _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedAce->Header.AceFlags);
  692. _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedAce->Header.AceSize);
  693. break;
  694. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  695. _TRACE (0, L"AceType: ACCESS_ALLOWED_OBJECT_ACE_TYPE\n");
  696. _TRACE (0, L"Mask: 0x%x\n", m_pAllowedObjectAce->Mask);
  697. _TRACE (0, L"AceFlags: 0x%x\n", m_pAllowedObjectAce->Header.AceFlags);
  698. _TRACE (0, L"AceSize: %d bytes\n", m_pAllowedObjectAce->Header.AceSize);
  699. _Module.GetClassFromGUID (m_pAllowedObjectAce->ObjectType, strGuidResult, &guidType);
  700. break;
  701. case ACCESS_DENIED_ACE_TYPE:
  702. _TRACE (0, L"AceType: ACCESS_DENIED_ACE_TYPE\n");
  703. _TRACE (0, L"Mask: 0x%x\n", m_pDeniedAce->Mask);
  704. _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedAce->Header.AceFlags);
  705. _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedAce->Header.AceSize);
  706. break;
  707. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  708. _TRACE (0, L"AceType: ACCESS_DENIED_OBJECT_ACE_TYPE\n");
  709. _TRACE (0, L"Mask: 0x%x\n", m_pDeniedObjectAce->Mask);
  710. _TRACE (0, L"AceFlags: 0x%x\n", m_pDeniedObjectAce->Header.AceFlags);
  711. _TRACE (0, L"AceSize: %d bytes\n", m_pDeniedObjectAce->Header.AceSize);
  712. _Module.GetClassFromGUID (m_pDeniedObjectAce->ObjectType, strGuidResult, &guidType);
  713. break;
  714. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  715. _TRACE (0, L"AceType: SYSTEM_AUDIT_OBJECT_ACE_TYPE\n");
  716. _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditObjectAce->Mask);
  717. _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditObjectAce->Header.AceFlags);
  718. _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditObjectAce->Header.AceSize);
  719. _Module.GetClassFromGUID (m_pSystemAuditObjectAce->ObjectType, strGuidResult, &guidType);
  720. break;
  721. case SYSTEM_AUDIT_ACE_TYPE:
  722. _TRACE (0, L"AceType: SYSTEM_AUDIT_ACE_TYPE\n");
  723. _TRACE (0, L"Mask: 0x%x\n", m_pSystemAuditAce->Mask);
  724. _TRACE (0, L"AceFlags: 0x%x\n", m_pSystemAuditAce->Header.AceFlags);
  725. _TRACE (0, L"AceSize: %d bytes\n", m_pSystemAuditAce->Header.AceSize);
  726. break;
  727. }
  728. if ( IsObjectAceType (m_pAllowedAce) )
  729. {
  730. wstring strGuidType;
  731. switch (guidType)
  732. {
  733. case GUID_TYPE_CLASS:
  734. strGuidType = L"GUID_TYPE_CLASS";
  735. break;
  736. case GUID_TYPE_ATTRIBUTE:
  737. strGuidType = L"GUID_TYPE_ATTRIBUTE";
  738. break;
  739. case GUID_TYPE_CONTROL:
  740. strGuidType = L"GUID_TYPE_CONTROL";
  741. break;
  742. default:
  743. #pragma warning (disable : 4127)
  744. ASSERT (0);
  745. #pragma warning (default : 4127)
  746. // fall through
  747. case GUID_TYPE_UNKNOWN:
  748. strGuidType = L"GUID_TYPE_UNKNOWN";
  749. break;
  750. }
  751. _TRACE (0, L"ObjectType type: %s\n", strGuidType.c_str ());
  752. _TRACE (0, L"ObjectType value: %s\n", strGuidResult.c_str ());
  753. }
  754. _TRACE (0, L"\n");
  755. #endif
  756. }
  757. ///////////////////////////////////////////////////////////////////////////////
  758. HRESULT
  759. SetSecurityInfoMask(LPUNKNOWN punk, SECURITY_INFORMATION si)
  760. {
  761. HRESULT hr = E_INVALIDARG;
  762. if (punk)
  763. {
  764. IADsObjectOptions *pOptions;
  765. hr = punk->QueryInterface(IID_IADsObjectOptions, (void**)&pOptions);
  766. if (SUCCEEDED(hr))
  767. {
  768. VARIANT var;
  769. V_VT(&var) = VT_I4;
  770. V_I4(&var) = si;
  771. hr = pOptions->SetOption(ADS_OPTION_SECURITY_MASK, var);
  772. pOptions->Release();
  773. }
  774. }
  775. return hr;
  776. }
  777. ///////////////////////////////////////////////////////////////////////////////
  778. /*******************************************************************
  779. NAME: EnablePrivileges
  780. SYNOPSIS: Enables the given privileges in the current token
  781. ENTRY: pdwPrivileges - list of privileges to enable
  782. RETURNS: On success, the previous thread handle (if present) or NULL
  783. On failure, INVALID_HANDLE_VALUE
  784. NOTES: The returned handle should be passed to ReleasePrivileges
  785. to ensure proper cleanup. Otherwise, if not NULL or
  786. INVALID_HANDLE_VALUE it should be closed with CloseHandle.
  787. HISTORY:
  788. JeffreyS 08-Oct-1996 Created
  789. ********************************************************************/
  790. HANDLE EnablePrivileges(PDWORD pdwPrivileges, ULONG cPrivileges)
  791. {
  792. BOOL fResult;
  793. HANDLE hToken;
  794. HANDLE hOriginalThreadToken;
  795. PTOKEN_PRIVILEGES ptp;
  796. ULONG nBufferSize;
  797. if (!pdwPrivileges || !cPrivileges)
  798. return INVALID_HANDLE_VALUE;
  799. // Note that TOKEN_PRIVILEGES includes a single LUID_AND_ATTRIBUTES
  800. nBufferSize = sizeof(TOKEN_PRIVILEGES) + (cPrivileges - 1) *
  801. sizeof(LUID_AND_ATTRIBUTES);
  802. ptp = (PTOKEN_PRIVILEGES)LocalAlloc(LPTR, nBufferSize);
  803. if (!ptp)
  804. return INVALID_HANDLE_VALUE;
  805. //
  806. // Initialize the Privileges Structure
  807. //
  808. ptp->PrivilegeCount = cPrivileges;
  809. for (ULONG i = 0; i < cPrivileges; i++)
  810. {
  811. //ptp->Privileges[i].Luid = RtlConvertUlongToLuid(*pdwPrivileges++);
  812. ptp->Privileges[i].Luid.LowPart = *pdwPrivileges++;
  813. ptp->Privileges[i].Luid.HighPart = 0;
  814. ptp->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
  815. }
  816. //
  817. // Open the Token
  818. //
  819. hToken = hOriginalThreadToken = INVALID_HANDLE_VALUE;
  820. fResult = OpenThreadToken (GetCurrentThread (), TOKEN_DUPLICATE, FALSE,
  821. &hToken);
  822. if (fResult)
  823. hOriginalThreadToken = hToken; // Remember the thread token
  824. else
  825. fResult = OpenProcessToken (GetCurrentProcess(), TOKEN_DUPLICATE,
  826. &hToken);
  827. if (fResult)
  828. {
  829. HANDLE hNewToken;
  830. //
  831. // Duplicate that Token
  832. //
  833. fResult = DuplicateTokenEx(hToken,
  834. TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  835. NULL, // PSECURITY_ATTRIBUTES
  836. SecurityImpersonation, // SECURITY_IMPERSONATION_LEVEL
  837. TokenImpersonation, // TokenType
  838. &hNewToken); // Duplicate token
  839. if (fResult)
  840. {
  841. //
  842. // Add new privileges
  843. //
  844. fResult = AdjustTokenPrivileges(hNewToken, // TokenHandle
  845. FALSE, // DisableAllPrivileges
  846. ptp, // NewState
  847. 0, // BufferLength
  848. NULL, // PreviousState
  849. NULL); // ReturnLength
  850. if (fResult)
  851. {
  852. //
  853. // Begin impersonating with the new token
  854. //
  855. fResult = SetThreadToken(NULL, hNewToken);
  856. }
  857. CloseHandle(hNewToken);
  858. }
  859. }
  860. // If something failed, don't return a token
  861. if (!fResult)
  862. hOriginalThreadToken = INVALID_HANDLE_VALUE;
  863. // Close the original token if we aren't returning it
  864. if (hOriginalThreadToken == INVALID_HANDLE_VALUE &&
  865. hToken != INVALID_HANDLE_VALUE)
  866. {
  867. CloseHandle(hToken);
  868. }
  869. // If we succeeded, but there was no original thread token,
  870. // return NULL to indicate we need to do SetThreadToken(NULL, NULL)
  871. // to release privs.
  872. if (fResult && hOriginalThreadToken == INVALID_HANDLE_VALUE)
  873. hOriginalThreadToken = NULL;
  874. LocalFree(ptp);
  875. return hOriginalThreadToken;
  876. }
  877. /*******************************************************************
  878. NAME: ReleasePrivileges
  879. SYNOPSIS: Resets privileges to the state prior to the corresponding
  880. EnablePrivileges call.
  881. ENTRY: hToken - result of call to EnablePrivileges
  882. RETURNS: nothing
  883. HISTORY:
  884. JeffreyS 08-Oct-1996 Created
  885. ********************************************************************/
  886. BOOL ReleasePrivileges(HANDLE hToken)
  887. {
  888. BOOL bRVal = FALSE;
  889. if (INVALID_HANDLE_VALUE != hToken)
  890. {
  891. bRVal = SetThreadToken(NULL, hToken);
  892. if (hToken)
  893. CloseHandle(hToken);
  894. }
  895. return bRVal;
  896. }
  897. VOID LocalFreeStringW(LPWSTR* ppString)
  898. {
  899. if ( ppString && *ppString )
  900. {
  901. LocalFree((HLOCAL)*ppString);
  902. *ppString = NULL;
  903. }
  904. }
  905. ///////////////////////////////////////////////////////////////////////////////
  906. //
  907. // Method: GetNameFromSid ()
  908. //
  909. // Purpose: Get the name of the object represented by this Sid
  910. //
  911. // Inputs: pSid - SID of the object whose name we wish to retrieve
  912. //
  913. // Outputs: strPrincipalName - name of the object in NameUserPrincipal
  914. // pstrFQDN - (optional) name of the object as Fully Qualified DN
  915. //
  916. HRESULT GetNameFromSid (
  917. PSID pSid,
  918. wstring& strPrincipalName,
  919. wstring* pstrFQDN,
  920. SID_NAME_USE& sne)
  921. {
  922. ASSERT (IsValidSid (pSid));
  923. if ( !IsValidSid (pSid) )
  924. return E_INVALIDARG;
  925. PWSTR pwszName = 0;
  926. DWORD cchName = 0;
  927. PWSTR pwszDomain = 0;
  928. DWORD cchDomain = 0;
  929. HRESULT hr = S_OK;
  930. BOOL bRVal = ::LookupAccountSid (NULL, // name of local or remote computer
  931. pSid, // security identifier
  932. pwszName, // account name buffer
  933. &cchName, // size of account name buffer, in characters
  934. pwszDomain, // domain name
  935. &cchDomain, // size of domain name buffer, in characters
  936. &sne); // SID type
  937. if ( FALSE == bRVal )
  938. {
  939. DWORD dwErr = GetLastError ();
  940. if ( ERROR_INSUFFICIENT_BUFFER == dwErr )
  941. {
  942. ASSERT (0 != cchDomain && 0 != cchName);
  943. if ( 0 == cchDomain || 0 == cchName )
  944. return E_UNEXPECTED;
  945. pwszName = new WCHAR[cchName];
  946. if ( pwszName )
  947. {
  948. pwszDomain = new WCHAR[cchDomain];
  949. if ( pwszDomain )
  950. {
  951. if ( ::LookupAccountSid (NULL, // name of local or remote computer
  952. pSid, // security identifier
  953. pwszName, // account name buffer
  954. &cchName, // size of account name buffer
  955. pwszDomain, // domain name
  956. &cchDomain, // size of domain name buffer
  957. &sne) ) // SID type
  958. {
  959. wstring strSamCompatibleName (pwszDomain);
  960. strSamCompatibleName += L"\\";
  961. strSamCompatibleName += pwszName;
  962. // Get Principal Name
  963. {
  964. PWSTR pszTranslatedName = 0;
  965. if ( SUCCEEDED (CrackName(const_cast<PWSTR> (strSamCompatibleName.c_str ()),
  966. &pszTranslatedName,
  967. GET_OBJ_UPN, //GET_OBJ_NT4_NAME,
  968. 0)) )
  969. {
  970. strPrincipalName = pszTranslatedName;
  971. LocalFreeStringW(&pszTranslatedName);
  972. }
  973. else
  974. {
  975. strPrincipalName = strSamCompatibleName;
  976. }
  977. }
  978. // Get fully qualified DN
  979. if ( pstrFQDN )
  980. {
  981. PWSTR pszTranslatedName = 0;
  982. if ( SUCCEEDED (CrackName(const_cast<PWSTR> (strSamCompatibleName.c_str ()),
  983. &pszTranslatedName,
  984. GET_OBJ_1779_DN,
  985. 0)) )
  986. {
  987. *pstrFQDN = pszTranslatedName;
  988. LocalFreeStringW(&pszTranslatedName);
  989. }
  990. else
  991. {
  992. *pstrFQDN = strSamCompatibleName;
  993. }
  994. }
  995. }
  996. else
  997. {
  998. dwErr = GetLastError ();
  999. _TRACE (0, L"LookupAccountSid failed: 0x%x\n", dwErr);
  1000. if ( ERROR_NONE_MAPPED == dwErr )
  1001. {
  1002. PWSTR pszStringSid = 0;
  1003. if ( ::ConvertSidToStringSid (pSid, &pszStringSid) )
  1004. {
  1005. strPrincipalName = pszStringSid;
  1006. if ( pstrFQDN )
  1007. *pstrFQDN = pszStringSid;
  1008. ::LocalFree (pszStringSid);
  1009. }
  1010. else
  1011. hr = E_OUTOFMEMORY;
  1012. }
  1013. else
  1014. hr = HRESULT_FROM_WIN32 (dwErr);
  1015. }
  1016. delete [] pwszDomain;
  1017. }
  1018. else
  1019. hr = E_OUTOFMEMORY;
  1020. delete [] pwszName;
  1021. }
  1022. else
  1023. hr = E_OUTOFMEMORY;
  1024. }
  1025. else
  1026. {
  1027. dwErr = GetLastError ();
  1028. _TRACE (0, L"LookupAccountSid failed: 0x%x\n", dwErr);
  1029. if ( ERROR_NONE_MAPPED == dwErr )
  1030. {
  1031. PWSTR pszStringSid = 0;
  1032. if ( ::ConvertSidToStringSid (pSid, &pszStringSid) )
  1033. {
  1034. strPrincipalName = pszStringSid;
  1035. if ( pstrFQDN )
  1036. *pstrFQDN = pszStringSid;
  1037. ::LocalFree (pszStringSid);
  1038. }
  1039. else
  1040. hr = E_OUTOFMEMORY;
  1041. }
  1042. else
  1043. hr = HRESULT_FROM_WIN32 (dwErr);
  1044. }
  1045. }
  1046. else
  1047. {
  1048. // Huh? How can this API return TRUE with null buffers?
  1049. hr = E_UNEXPECTED;
  1050. }
  1051. return hr;
  1052. }
  1053. #define MAX_BUF_SIZE 4096
  1054. CHAR AnsiBuf[MAX_BUF_SIZE*3]; /* worst case is DBCS, which */
  1055. /* needs more than *2 */
  1056. WCHAR ConBuf [MAX_BUF_SIZE];
  1057. int FileIsConsole(HANDLE fh)
  1058. {
  1059. unsigned htype ;
  1060. htype = GetFileType(fh);
  1061. htype &= ~FILE_TYPE_REMOTE;
  1062. return htype == FILE_TYPE_CHAR;
  1063. }
  1064. int MyWriteConsole()
  1065. {
  1066. DWORD cch = (DWORD) wcslen(ConBuf);
  1067. HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  1068. if (FileIsConsole(hOut))
  1069. WriteConsole(hOut, ConBuf, cch, &cch, NULL);
  1070. else
  1071. {
  1072. cch = WideCharToMultiByte(CP_OEMCP, 0,
  1073. ConBuf, (int) cch,
  1074. AnsiBuf, MAX_BUF_SIZE*3,
  1075. NULL, NULL);
  1076. WriteFile(hOut, AnsiBuf, cch, &cch, NULL);
  1077. }
  1078. return (int) cch;
  1079. }
  1080. int MyWprintf( const wchar_t *fmt, ... )
  1081. {
  1082. va_list args;
  1083. va_start( args, fmt );
  1084. ::ZeroMemory (ConBuf, sizeof (ConBuf));
  1085. _vsnwprintf( ConBuf, MAX_BUF_SIZE-1, fmt, args );
  1086. va_end( args );
  1087. return MyWriteConsole ();
  1088. }