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.

441 lines
12 KiB

  1. #include "precomp.h"
  2. #include "wmiauthz.h"
  3. /**************************************************************************
  4. Win32 Authz prototypes
  5. ***************************************************************************/
  6. typedef BOOL (WINAPI*PAuthzAccessCheck)(
  7. IN DWORD Flags,
  8. IN AUTHZ_CLIENT_CONTEXT_HANDLE AuthzClientContext,
  9. IN PAUTHZ_ACCESS_REQUEST pRequest,
  10. IN AUTHZ_AUDIT_EVENT_HANDLE AuditInfo OPTIONAL,
  11. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  12. IN PSECURITY_DESCRIPTOR *OptionalSecurityDescriptorArray OPTIONAL,
  13. IN DWORD OptionalSecurityDescriptorCount,
  14. IN OUT PAUTHZ_ACCESS_REPLY pReply,
  15. OUT PAUTHZ_ACCESS_CHECK_RESULTS_HANDLE pAuthzHandle OPTIONAL );
  16. typedef BOOL (WINAPI*PAuthzInitializeResourceManager)(
  17. IN DWORD AuthzFlags,
  18. IN PFN_AUTHZ_DYNAMIC_ACCESS_CHECK pfnAccessCheck OPTIONAL,
  19. IN PFN_AUTHZ_COMPUTE_DYNAMIC_GROUPS pfnComputeDynamicGroups OPTIONAL,
  20. IN PFN_AUTHZ_FREE_DYNAMIC_GROUPS pfnFreeDynamicGroups OPTIONAL,
  21. IN PCWSTR szResourceManagerName,
  22. OUT PAUTHZ_RESOURCE_MANAGER_HANDLE pAuthzResourceManager
  23. );
  24. typedef BOOL (WINAPI*PAuthzInitializeContextFromSid)(
  25. IN DWORD Flags,
  26. IN PSID UserSid,
  27. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  28. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  29. IN LUID Identifier,
  30. IN PVOID DynamicGroupArgs OPTIONAL,
  31. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  32. );
  33. typedef BOOL (WINAPI*PAuthzInitializeContextFromToken)(
  34. IN HANDLE TokenHandle,
  35. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  36. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  37. IN LUID Identifier,
  38. IN DWORD Flags,
  39. IN PVOID DynamicGroupArgs OPTIONAL,
  40. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  41. );
  42. typedef BOOL (WINAPI*PAuthzFreeContext)( AUTHZ_CLIENT_CONTEXT_HANDLE );
  43. typedef BOOL (WINAPI*PAuthzFreeResourceManager)( AUTHZ_RESOURCE_MANAGER_HANDLE );
  44. BOOL WINAPI ComputeDynamicGroups(
  45. IN AUTHZ_CLIENT_CONTEXT_HANDLE hAuthzClientContext,
  46. IN PVOID Args,
  47. OUT PSID_AND_ATTRIBUTES *pSidAttrArray,
  48. OUT PDWORD pSidCount,
  49. OUT PSID_AND_ATTRIBUTES *pRestrictedSidAttrArray,
  50. OUT PDWORD pRestrictedSidCount
  51. )
  52. {
  53. BOOL bRet;
  54. *pRestrictedSidAttrArray = NULL;
  55. *pRestrictedSidCount = 0;
  56. //
  57. // if sid is not local system, then don't need to do anything.
  58. //
  59. *pSidAttrArray = NULL;
  60. *pSidCount = 0;
  61. if ( !*(BOOL*)(Args) )
  62. {
  63. bRet = TRUE;
  64. }
  65. else
  66. {
  67. //
  68. // need to add authenticated users and everyone groups.
  69. //
  70. PSID_AND_ATTRIBUTES psa = new SID_AND_ATTRIBUTES[2];
  71. if ( psa != NULL )
  72. {
  73. ZeroMemory( psa, sizeof(SID_AND_ATTRIBUTES)*2 );
  74. SID_IDENTIFIER_AUTHORITY wid = SECURITY_WORLD_SID_AUTHORITY;
  75. SID_IDENTIFIER_AUTHORITY ntid = SECURITY_NT_AUTHORITY;
  76. if ( bRet = AllocateAndInitializeSid( &wid,
  77. 1,
  78. SECURITY_WORLD_RID,
  79. 0,0,0,0,0,0,0,
  80. &psa[0].Sid ) )
  81. {
  82. if ( bRet = AllocateAndInitializeSid( &ntid,
  83. 1,
  84. SECURITY_AUTHENTICATED_USER_RID,
  85. 0,0,0,0,0,0,0,
  86. &psa[1].Sid ) )
  87. {
  88. *pSidCount = 2;
  89. *pSidAttrArray = psa;
  90. }
  91. else
  92. {
  93. FreeSid( &psa[0].Sid );
  94. delete [] psa;
  95. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  96. }
  97. }
  98. else
  99. {
  100. delete [] psa;
  101. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  102. }
  103. }
  104. else
  105. {
  106. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  107. bRet = FALSE;
  108. }
  109. }
  110. return bRet;
  111. }
  112. void WINAPI FreeDynamicGroups( PSID_AND_ATTRIBUTES psa )
  113. {
  114. if ( psa != NULL )
  115. {
  116. FreeSid( psa[0].Sid );
  117. FreeSid( psa[1].Sid );
  118. delete [] psa;
  119. }
  120. }
  121. /**************************************************************************
  122. CWmiAuthzApi
  123. ***************************************************************************/
  124. #define FUNCMEMBER(FUNC) P ## FUNC m_fp ## FUNC;
  125. class CWmiAuthzApi
  126. {
  127. HMODULE m_hMod;
  128. public:
  129. FUNCMEMBER(AuthzInitializeContextFromToken)
  130. FUNCMEMBER(AuthzInitializeContextFromSid)
  131. FUNCMEMBER(AuthzInitializeResourceManager)
  132. FUNCMEMBER(AuthzAccessCheck)
  133. FUNCMEMBER(AuthzFreeContext)
  134. FUNCMEMBER(AuthzFreeResourceManager)
  135. CWmiAuthzApi() { ZeroMemory( this, sizeof(CWmiAuthzApi) ); }
  136. ~CWmiAuthzApi() { if ( m_hMod != NULL ) FreeLibrary( m_hMod ); }
  137. HRESULT Initialize();
  138. };
  139. #define SETFUNC(FUNC) \
  140. m_fp ## FUNC = (P ## FUNC) GetProcAddress( m_hMod, #FUNC ); \
  141. if ( m_fp ## FUNC == NULL ) return WBEM_E_NOT_SUPPORTED;
  142. HRESULT CWmiAuthzApi::Initialize()
  143. {
  144. m_hMod = LoadLibrary( TEXT("authz") );
  145. if ( m_hMod == NULL )
  146. {
  147. return WBEM_E_NOT_SUPPORTED;
  148. }
  149. SETFUNC(AuthzInitializeContextFromToken)
  150. SETFUNC(AuthzInitializeResourceManager)
  151. SETFUNC(AuthzInitializeContextFromSid)
  152. SETFUNC(AuthzInitializeContextFromToken)
  153. SETFUNC(AuthzAccessCheck)
  154. SETFUNC(AuthzFreeContext)
  155. SETFUNC(AuthzFreeResourceManager)
  156. return WBEM_S_NO_ERROR;
  157. };
  158. /**************************************************************************
  159. CWmiAuthz
  160. ***************************************************************************/
  161. #define CALLFUNC(API,FUNC) (*API->m_fp ## FUNC)
  162. CWmiAuthz::CWmiAuthz( CLifeControl* pControl )
  163. : CUnkBase<IWbemTokenCache,&IID_IWbemTokenCache>( pControl ),
  164. m_hResMgr(NULL), m_pApi(NULL), m_pAdministratorsSid(NULL),
  165. m_pLocalSystemSid(NULL)
  166. {
  167. }
  168. HRESULT CWmiAuthz::EnsureInitialized()
  169. {
  170. HRESULT hr;
  171. CInCritSec ics( &m_cs );
  172. if ( m_hResMgr != NULL )
  173. {
  174. return WBEM_S_NO_ERROR;
  175. }
  176. //
  177. // try to create the API object.
  178. //
  179. if ( m_pApi == NULL )
  180. {
  181. m_pApi = new CWmiAuthzApi;
  182. if ( m_pApi == NULL )
  183. {
  184. return WBEM_E_OUT_OF_MEMORY;
  185. }
  186. hr = m_pApi->Initialize();
  187. if ( FAILED(hr) )
  188. {
  189. delete m_pApi;
  190. m_pApi = NULL;
  191. return hr;
  192. }
  193. }
  194. //
  195. // initialize the authz res mgr.
  196. //
  197. if ( !CALLFUNC(m_pApi,AuthzInitializeResourceManager)
  198. ( AUTHZ_RM_FLAG_NO_AUDIT,
  199. NULL,
  200. ComputeDynamicGroups,
  201. FreeDynamicGroups,
  202. NULL,
  203. &m_hResMgr ) )
  204. {
  205. return HRESULT_FROM_WIN32( GetLastError() );
  206. }
  207. //
  208. // allocate and initialize well known sids for authz special casing.
  209. //
  210. SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
  211. if ( !AllocateAndInitializeSid( &id,
  212. 2,
  213. SECURITY_BUILTIN_DOMAIN_RID,
  214. DOMAIN_ALIAS_RID_ADMINS,
  215. 0,0,0,0,0,0,
  216. &m_pAdministratorsSid) )
  217. {
  218. return HRESULT_FROM_WIN32( GetLastError() );
  219. }
  220. if ( !AllocateAndInitializeSid( &id,
  221. 1,
  222. SECURITY_LOCAL_SYSTEM_RID,
  223. 0,0,0,0,0,0,0,
  224. &m_pLocalSystemSid) )
  225. {
  226. return HRESULT_FROM_WIN32( GetLastError() );
  227. }
  228. return WBEM_S_NO_ERROR;
  229. }
  230. STDMETHODIMP CWmiAuthz::Shutdown()
  231. {
  232. return WBEM_S_NO_ERROR;
  233. }
  234. CWmiAuthz::~CWmiAuthz()
  235. {
  236. if ( m_hResMgr != NULL )
  237. {
  238. CALLFUNC(m_pApi,AuthzFreeResourceManager)( m_hResMgr );
  239. }
  240. if ( m_pApi != NULL )
  241. {
  242. delete m_pApi;
  243. }
  244. if ( m_pAdministratorsSid != NULL )
  245. {
  246. FreeSid( m_pAdministratorsSid );
  247. }
  248. if ( m_pLocalSystemSid != NULL )
  249. {
  250. FreeSid( m_pLocalSystemSid );
  251. }
  252. }
  253. STDMETHODIMP CWmiAuthz::GetToken( const BYTE* pSid, IWbemToken** ppToken )
  254. {
  255. HRESULT hr;
  256. *ppToken = NULL;
  257. hr = EnsureInitialized();
  258. if ( SUCCEEDED( hr ) )
  259. {
  260. AUTHZ_CLIENT_CONTEXT_HANDLE hCtx = NULL;
  261. LUID luid;
  262. ZeroMemory( &luid, sizeof(LUID) );
  263. DWORD dwFlags = 0;
  264. BOOL bLocalSystem = FALSE;
  265. if ( EqualSid( PSID(pSid), m_pAdministratorsSid ) )
  266. {
  267. //
  268. // this is a group sid, so specify this in the flags so
  269. // authz can handle it properly.
  270. //
  271. dwFlags = AUTHZ_SKIP_TOKEN_GROUPS;
  272. }
  273. else if ( EqualSid( PSID(pSid), m_pLocalSystemSid ) )
  274. {
  275. //
  276. // authz doesn't handle local system so have to workaround
  277. // by disabling authz's group computation and do it ourselves.
  278. //
  279. bLocalSystem = TRUE;
  280. dwFlags = AUTHZ_SKIP_TOKEN_GROUPS;
  281. }
  282. if ( !CALLFUNC(m_pApi,AuthzInitializeContextFromSid)( dwFlags,
  283. PSID(pSid),
  284. m_hResMgr,
  285. NULL,
  286. luid,
  287. &bLocalSystem,
  288. &hCtx ) )
  289. {
  290. return HRESULT_FROM_WIN32( GetLastError() );
  291. }
  292. *ppToken = new CWmiAuthzToken( this, hCtx );
  293. if ( *ppToken == NULL )
  294. {
  295. CALLFUNC(m_pApi,AuthzFreeContext)(hCtx);
  296. return WBEM_E_OUT_OF_MEMORY;
  297. }
  298. (*ppToken)->AddRef();
  299. return WBEM_S_NO_ERROR;
  300. }
  301. return hr;
  302. }
  303. /***************************************************************************
  304. CWmiAuthzToken
  305. ****************************************************************************/
  306. CWmiAuthzToken::CWmiAuthzToken( CWmiAuthz* pOwner, AUTHZ_CLIENT_CONTEXT_HANDLE hCtx )
  307. : CUnkBase<IWbemToken,&IID_IWbemToken>(NULL), m_hCtx(hCtx), m_pOwner(pOwner)
  308. {
  309. //
  310. // we want to keep the owner alive, in case the caller has released theirs
  311. //
  312. m_pOwner->AddRef();
  313. }
  314. CWmiAuthzToken::~CWmiAuthzToken()
  315. {
  316. CWmiAuthzApi* pApi = m_pOwner->GetApi();
  317. CALLFUNC(pApi,AuthzFreeContext)(m_hCtx);
  318. m_pOwner->Release();
  319. }
  320. STDMETHODIMP CWmiAuthzToken::AccessCheck( DWORD dwDesiredAccess,
  321. const BYTE* pSD,
  322. DWORD* pdwGrantedAccess )
  323. {
  324. HRESULT hr;
  325. AUTHZ_ACCESS_REQUEST AccessReq;
  326. ZeroMemory( &AccessReq, sizeof(AUTHZ_ACCESS_REQUEST) );
  327. AccessReq.DesiredAccess = dwDesiredAccess;
  328. AUTHZ_ACCESS_REPLY AccessRep;
  329. DWORD dwError;
  330. ZeroMemory( &AccessRep, sizeof(AUTHZ_ACCESS_REPLY) );
  331. AccessRep.GrantedAccessMask = pdwGrantedAccess;
  332. AccessRep.ResultListLength = 1;
  333. AccessRep.Error = &dwError;
  334. AccessRep.SaclEvaluationResults = NULL;
  335. CWmiAuthzApi* pApi = m_pOwner->GetApi();
  336. if ( !CALLFUNC(pApi,AuthzAccessCheck)( 0,
  337. m_hCtx,
  338. &AccessReq,
  339. NULL,
  340. PSECURITY_DESCRIPTOR(pSD),
  341. NULL,
  342. NULL,
  343. &AccessRep,
  344. NULL ) )
  345. {
  346. return HRESULT_FROM_WIN32( GetLastError() );
  347. }
  348. return WBEM_S_NO_ERROR;
  349. }