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.

569 lines
13 KiB

  1. //****************************************************************************
  2. //
  3. // Copyright (C) 1999 Microsoft Corporation
  4. //
  5. // GROUPSFORUSER.CPP
  6. //
  7. //****************************************************************************
  8. // This is done in the sources file: WIN32_WIN32_WINNT=0x0400
  9. //#define _WIN32_WINNT 0x0400
  10. #include "precomp.h"
  11. #include <wbemcomn.h>
  12. #include "wmiauthz.h"
  13. #include "GroupsForUser.h"
  14. //
  15. // Store the error status of CWmiAuthzWrapper and CAdminSID class initialization.
  16. // They are set to ERROR_INVALID_ACCESS error status initially.
  17. //
  18. static DWORD g_dwWmiAuthzError = ERROR_INVALID_ACCESS;
  19. static DWORD g_dwAdminSIDError = ERROR_INVALID_ACCESS;
  20. //
  21. // Class definition of CWmiAuthzWrapper class.
  22. // This class wraps CWmiAuthz class:
  23. // - It creates an instance of CWmiAuthz class in its
  24. // constructor and deletes it in descrutor.
  25. // - Sets g_dwWmiAuthzError global in case of error otherwise
  26. // sets it to 0 ( ERROR_SUCCESS )
  27. //
  28. class CWmiAuthzWrapper
  29. {
  30. // Private member variables
  31. CWmiAuthz *m_pWmiAuthz;
  32. public:
  33. // Constructor
  34. CWmiAuthzWrapper( )
  35. {
  36. m_pWmiAuthz = new CWmiAuthz( NULL );
  37. if ( NULL == m_pWmiAuthz )
  38. {
  39. g_dwWmiAuthzError = ERROR_OUTOFMEMORY;
  40. }
  41. else
  42. {
  43. m_pWmiAuthz->AddRef( );
  44. g_dwWmiAuthzError = ERROR_SUCCESS;
  45. }
  46. }
  47. // Destructor
  48. ~CWmiAuthzWrapper( )
  49. {
  50. if ( m_pWmiAuthz )
  51. {
  52. m_pWmiAuthz->Release( );
  53. }
  54. }
  55. // Accessor method to CWmiClass instance
  56. CWmiAuthz * GetWmiAuthz( ) const
  57. {
  58. return m_pWmiAuthz;
  59. }
  60. };
  61. //
  62. // Class definition of CAdminSID class.
  63. // - Allocates Admin SID in its constructor and
  64. // frees it in destructor.
  65. // - Sets g_dwAdminSIDError global in case of error otherwise
  66. // sets it to 0 ( ERROR_SUCCESS )
  67. //
  68. class CAdminSID
  69. {
  70. PSID m_pSIDAdmin;
  71. public:
  72. // Constructor
  73. CAdminSID( )
  74. {
  75. //
  76. // Create a System Identifier for the Admin group.
  77. //
  78. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  79. if ( FALSE == AllocateAndInitializeSid ( &SystemSidAuthority,
  80. 2,
  81. SECURITY_BUILTIN_DOMAIN_RID,
  82. DOMAIN_ALIAS_RID_ADMINS,
  83. 0, 0, 0, 0, 0, 0,
  84. &m_pSIDAdmin ) )
  85. {
  86. g_dwAdminSIDError = GetLastError( );
  87. ERRORTRACE( ( LOG_ESS, "AllocateAndInitializeSid failed, error 0x%X\n", g_dwAdminSIDError ) );
  88. m_pSIDAdmin = NULL;
  89. }
  90. else
  91. {
  92. g_dwAdminSIDError = ERROR_SUCCESS;
  93. }
  94. }
  95. // Destructor
  96. ~CAdminSID( )
  97. {
  98. if ( m_pSIDAdmin )
  99. {
  100. FreeSid ( m_pSIDAdmin );
  101. }
  102. }
  103. // Accessor method to Admin SID
  104. PSID GetAdminSID( ) const
  105. {
  106. return m_pSIDAdmin;
  107. }
  108. };
  109. //
  110. // Static glabal declaration of CWmiAuthsWrapper class.
  111. //
  112. static CWmiAuthzWrapper g_wmiAuthzWrapper;
  113. //
  114. // Static glabal declaration of CAdminSID class.
  115. //
  116. static CAdminSID g_adminSID;
  117. //
  118. // Returns SD and DACL with a given Access Mask and SID
  119. //
  120. DWORD GetSDAndACLFromSID( DWORD dwAccessMask, PSID pSID,
  121. BYTE **ppNewDACL,
  122. BYTE **ppNewSD )
  123. {
  124. DWORD dwError = 0,
  125. dwDACLLength = sizeof ( ACL ) +
  126. sizeof ( ACCESS_ALLOWED_ACE ) -
  127. sizeof ( DWORD ) +
  128. GetLengthSid ( pSID );
  129. //
  130. // Get memory needed for new DACL
  131. //
  132. *ppNewDACL = new BYTE[ dwDACLLength ];
  133. if ( !*ppNewDACL )
  134. {
  135. *ppNewSD = NULL;
  136. return E_OUTOFMEMORY;
  137. }
  138. //
  139. // Get memory for new SD
  140. //
  141. *ppNewSD = new BYTE[ sizeof( SECURITY_DESCRIPTOR ) ];
  142. if ( !*ppNewSD )
  143. {
  144. delete[] *ppNewDACL;
  145. *ppNewDACL = NULL;
  146. return E_OUTOFMEMORY;
  147. }
  148. do
  149. {
  150. //
  151. // Initialize new SD
  152. //
  153. if ( FALSE == InitializeSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  154. SECURITY_DESCRIPTOR_REVISION ) )
  155. {
  156. dwError = GetLastError( );
  157. break;
  158. }
  159. //
  160. // Initialize new DACL
  161. //
  162. if ( FALSE == InitializeAcl ( ( PACL )*ppNewDACL,
  163. dwDACLLength,
  164. ACL_REVISION ) )
  165. {
  166. dwError = GetLastError( );
  167. break;
  168. }
  169. //
  170. // Get DACL using Access Mask and SID
  171. //
  172. if ( FALSE == AddAccessAllowedAce ( ( PACL )*ppNewDACL,
  173. ACL_REVISION,
  174. dwAccessMask,
  175. pSID ) )
  176. {
  177. dwError = GetLastError( );
  178. break;
  179. }
  180. //
  181. // Check if everything went OK
  182. //
  183. if ( FALSE == IsValidAcl ( ( PACL )*ppNewDACL ) )
  184. {
  185. dwError = GetLastError( );
  186. break;
  187. }
  188. //
  189. // Set DACL to the SD
  190. //
  191. if ( FALSE == SetSecurityDescriptorDacl ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  192. TRUE, ( PACL )*ppNewDACL,
  193. FALSE ) )
  194. {
  195. dwError = GetLastError( );
  196. break;
  197. }
  198. //
  199. // Set Group to the SD
  200. //
  201. if ( FALSE == SetSecurityDescriptorGroup ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  202. pSID,
  203. TRUE ) )
  204. {
  205. dwError = GetLastError( );
  206. break;
  207. }
  208. //
  209. // Set Owner to the SD
  210. //
  211. if ( FALSE == SetSecurityDescriptorOwner ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  212. pSID,
  213. TRUE ) )
  214. {
  215. dwError = GetLastError( );
  216. break;
  217. }
  218. //
  219. // Check if everything went OK
  220. //
  221. if ( FALSE == IsValidSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD ) )
  222. {
  223. dwError = GetLastError( );
  224. break;
  225. }
  226. }
  227. while( FALSE );
  228. //
  229. // Delete the stuff in case of error
  230. //
  231. if ( dwError )
  232. {
  233. delete[] *ppNewDACL;
  234. delete[] *ppNewSD;
  235. *ppNewDACL = NULL;
  236. *ppNewSD = NULL;
  237. }
  238. return dwError;
  239. }
  240. //
  241. // Returns SD with a given DACL
  242. //
  243. DWORD GetSDFromACL( PACL pNewDACL, BYTE **ppNewSD )
  244. {
  245. //
  246. // Return if error occured during initialization of Admin SID
  247. // in CAdminSID static global class declaration;
  248. //
  249. _DBG_ASSERT( !g_dwAdminSIDError );
  250. if ( g_dwAdminSIDError )
  251. {
  252. *ppNewSD = NULL;
  253. return g_dwAdminSIDError;
  254. }
  255. //
  256. // Get memory for new SD
  257. //
  258. *ppNewSD = new BYTE[ sizeof( SECURITY_DESCRIPTOR ) ];
  259. if ( !*ppNewSD )
  260. {
  261. return E_OUTOFMEMORY;
  262. }
  263. DWORD dwError = 0;
  264. do
  265. {
  266. //
  267. // Initialize new SD
  268. //
  269. if ( FALSE == InitializeSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  270. SECURITY_DESCRIPTOR_REVISION ) )
  271. {
  272. dwError = GetLastError( );
  273. break;
  274. }
  275. //
  276. // Set DACL to the SD
  277. //
  278. if ( FALSE == SetSecurityDescriptorDacl ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  279. TRUE, pNewDACL, FALSE ) )
  280. {
  281. dwError = GetLastError( );
  282. break;
  283. }
  284. //
  285. // Set Group to the SD with Admin SID
  286. //
  287. if ( FALSE == SetSecurityDescriptorGroup ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  288. g_adminSID.GetAdminSID( ),
  289. TRUE ) )
  290. {
  291. dwError = GetLastError( );
  292. break;
  293. }
  294. //
  295. // Set Owner to the SD
  296. //
  297. if ( FALSE == SetSecurityDescriptorOwner ( ( PSECURITY_DESCRIPTOR )*ppNewSD,
  298. g_adminSID.GetAdminSID( ),
  299. TRUE ) )
  300. {
  301. dwError = GetLastError( );
  302. break;
  303. }
  304. //
  305. // Check if everything went OK
  306. //
  307. if ( FALSE == IsValidSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD ) )
  308. {
  309. dwError = GetLastError( );
  310. break;
  311. }
  312. }
  313. while( FALSE );
  314. //
  315. // Delete the security descriptor in case of error
  316. //
  317. if ( dwError )
  318. {
  319. delete[] *ppNewSD;
  320. *ppNewSD = NULL;
  321. }
  322. return dwError;
  323. }
  324. //
  325. // Returns STATUS_SUCCESS if user is in group
  326. // STATUS_ACCESS_DENIED if not
  327. // some error code or other on error
  328. //
  329. NTSTATUS IsUserInGroup( PSID pSidUser, PSID pSidGroup )
  330. {
  331. _DBG_ASSERT( IsValidSid( pSidUser ) );
  332. _DBG_ASSERT( IsValidSid( pSidGroup ) );
  333. //
  334. // Return if error occured during creation of CWmiAuthz class
  335. // in static global CWmiAuthzWrapper class declaration.
  336. //
  337. _DBG_ASSERT( !g_dwWmiAuthzError );
  338. if ( g_dwWmiAuthzError )
  339. {
  340. return g_dwWmiAuthzError;
  341. }
  342. IWbemToken *pToken = NULL;
  343. HRESULT hr = g_wmiAuthzWrapper.GetWmiAuthz( )->GetToken( ( BYTE * )pSidUser, &pToken );
  344. if ( FAILED( hr ) )
  345. {
  346. return hr;
  347. }
  348. BYTE *pDACL = NULL;
  349. BYTE *pSD = NULL;
  350. DWORD dwAccess = 0;
  351. NTSTATUS stat = GetSDAndACLFromSID( STANDARD_RIGHTS_EXECUTE,
  352. pSidGroup,
  353. &pDACL,
  354. &pSD );
  355. if ( stat )
  356. {
  357. pToken->Release( );
  358. return stat;
  359. }
  360. hr = pToken->AccessCheck( STANDARD_RIGHTS_EXECUTE, pSD, &dwAccess );
  361. pToken->Release( );
  362. //
  363. // Delete allocated memory in GetSDAndACLFromSID
  364. //
  365. delete[] pSD;
  366. delete[] pDACL;
  367. if ( FAILED( hr ) )
  368. {
  369. return hr;
  370. }
  371. if ( STANDARD_RIGHTS_EXECUTE & dwAccess )
  372. {
  373. return STATUS_SUCCESS;
  374. }
  375. return STATUS_ACCESS_DENIED;
  376. }
  377. //
  378. // Returns STATUS_SUCCESS if user is in admin group
  379. // STATUS_ACCESS_DENIED if not
  380. // some error code or other on error
  381. //
  382. NTSTATUS IsUserAdministrator( PSID pSidUser )
  383. {
  384. _DBG_ASSERT( IsValidSid( pSidUser ) );
  385. //
  386. // Return if error occured during initialization of Admin SID
  387. // in CAdminSID static global class declaration;
  388. //
  389. _DBG_ASSERT( !g_dwAdminSIDError );
  390. if ( g_dwAdminSIDError )
  391. {
  392. return g_dwAdminSIDError;
  393. }
  394. //
  395. // Call IsUserInGroup with Administrators group SID
  396. //
  397. return IsUserInGroup( pSidUser, g_adminSID.GetAdminSID( ) );
  398. }
  399. //
  400. // Retireves access mask corresponding to permissions granted
  401. // by dacl to account denoted in pSid
  402. // only deals with the ACCESS_ALLOWED/DENIED type aces
  403. // including the ACCESS_ALLOWED/DENIED_OBJECT_ACEs
  404. // - will error out if it finds a SYSTEM_AUDIT or unrecognized type.
  405. //
  406. NTSTATUS GetAccessMask( PSID pSid, PACL pDacl, DWORD *pdwAccessMask )
  407. {
  408. if ( NULL == pDacl )
  409. {
  410. *pdwAccessMask = 0xFFFFFFFF;
  411. return STATUS_SUCCESS;
  412. }
  413. _DBG_ASSERT( IsValidSid( pSid ) );
  414. _DBG_ASSERT( IsValidAcl( pDacl ) );
  415. *pdwAccessMask = NULL;
  416. //
  417. // Return if error occured during creation of CWmiAuthz class
  418. // in static global CWmiAuthzWrapper class declaration.
  419. //
  420. _DBG_ASSERT( !g_dwWmiAuthzError );
  421. if ( g_dwWmiAuthzError )
  422. {
  423. return g_dwWmiAuthzError;
  424. }
  425. IWbemToken *pToken = NULL;
  426. HRESULT hr = g_wmiAuthzWrapper.GetWmiAuthz( )->GetToken( ( BYTE * )pSid, &pToken );
  427. if ( FAILED( hr ) )
  428. {
  429. return hr;
  430. }
  431. BYTE *pSD = NULL;
  432. NTSTATUS stat = GetSDFromACL( pDacl, &pSD );
  433. if ( stat )
  434. {
  435. pToken->Release( );
  436. return stat;
  437. }
  438. //
  439. // Requested DesiredAccessMask should be MAXIMUM_ALLOWED
  440. // to be able to retrieve all the accesses with replied
  441. // access mask
  442. //
  443. hr = pToken->AccessCheck( MAXIMUM_ALLOWED, pSD, pdwAccessMask );
  444. pToken->Release( );
  445. //
  446. // Delete allocated memory in GetSDFromACL
  447. //
  448. delete[] pSD;
  449. if ( FAILED( hr ) )
  450. {
  451. return hr;
  452. }
  453. return STATUS_SUCCESS;
  454. }