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.

455 lines
12 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. Abstract:
  5. History:
  6. --*/
  7. #include "precomp.h"
  8. #include <assert.h>
  9. #include <wbemcli.h>
  10. #include <wbemutil.h>
  11. #include <arrtempl.h>
  12. #include <statsync.h>
  13. #include "rpcrecv.h"
  14. #include "rpcmsg.h"
  15. #include "rpchdr.h"
  16. #include "rpcctx.h"
  17. extern HRESULT RpcResToWmiRes( RPC_STATUS stat, HRESULT hrDefault );
  18. //
  19. // this implementation maintains a single RPC receiver per process. The
  20. // interface, however, implies that there could be multiple receivers. This
  21. // means that we must ensure that only one instance of this interface is
  22. // serviced at any one time. We do this by maintaining an owner variable that
  23. // contains the instance that owns the RPC receiver. Once Open() is called
  24. // on an instance, it assumes ownership of the global RPC receiver, closing
  25. // any existing RPC receiver. If Close() is called on an instance that
  26. // does not own the Receiver, then we do nothing.
  27. //
  28. CStaticCritSec g_csOpenClose;
  29. IWmiMessageSendReceive* g_pRcv = NULL;
  30. PSECURITY_DESCRIPTOR g_pSD = NULL;
  31. CMsgRpcReceiver* g_pLastOwner = NULL;
  32. RPC_STATUS RPC_ENTRY RpcAuthCallback( RPC_IF_HANDLE Interface, void *Context )
  33. {
  34. RPC_STATUS stat;
  35. _DBG_ASSERT( g_pSD != NULL );
  36. stat = RpcImpersonateClient( Context );
  37. if ( stat == RPC_S_OK )
  38. {
  39. HANDLE hToken;
  40. if( OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken ) )
  41. {
  42. GENERIC_MAPPING map;
  43. ZeroMemory( &map, sizeof(GENERIC_MAPPING) );
  44. PRIVILEGE_SET ps;
  45. DWORD dwPrivLength = sizeof(ps);
  46. BOOL bStatus;
  47. DWORD dwGranted;
  48. if ( ::AccessCheck( g_pSD,
  49. hToken,
  50. 1,
  51. &map,
  52. &ps,
  53. &dwPrivLength,
  54. &dwGranted,
  55. &bStatus ) )
  56. {
  57. stat = bStatus ? RPC_S_OK : RPC_S_ACCESS_DENIED;
  58. }
  59. else
  60. {
  61. stat = RPC_S_ACCESS_DENIED;
  62. }
  63. CloseHandle( hToken );
  64. }
  65. else
  66. {
  67. stat = RPC_S_ACCESS_DENIED;
  68. }
  69. RpcRevertToSelf();
  70. }
  71. return stat;
  72. }
  73. long RcvrSendReceive( RPC_BINDING_HANDLE hClient,
  74. PBYTE pData,
  75. ULONG cData,
  76. PBYTE pAuxData,
  77. ULONG cAuxData )
  78. {
  79. HRESULT hr;
  80. ENTER_API_CALL
  81. CBuffer HdrStrm( pAuxData, cAuxData, FALSE );
  82. CMsgRpcHdr Hdr;
  83. hr = Hdr.Unpersist( HdrStrm );
  84. if ( FAILED(hr) )
  85. {
  86. return hr;
  87. }
  88. PBYTE pUserAuxData = HdrStrm.GetRawData() + HdrStrm.GetIndex();
  89. CMsgRpcRcvrCtx Ctx( &Hdr, hClient );
  90. hr = g_pRcv->SendReceive( pData,
  91. cData,
  92. pUserAuxData,
  93. Hdr.GetAuxDataLength(),
  94. 0,
  95. &Ctx );
  96. EXIT_API_CALL
  97. return hr;
  98. }
  99. HRESULT CreateAuthOnlySecurityDescriptor( PSECURITY_DESCRIPTOR* ppSD )
  100. {
  101. HRESULT hr;
  102. //
  103. // obtain the sid from the process token to use for owner and
  104. // group fields of SD.
  105. //
  106. HANDLE hProcessToken;
  107. if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hProcessToken ))
  108. {
  109. return HRESULT_FROM_WIN32( GetLastError() );
  110. }
  111. CCloseMe cm( hProcessToken );
  112. DWORD dwSize;
  113. GetTokenInformation( hProcessToken, TokenOwner, NULL, 0, &dwSize );
  114. if ( GetLastError() != ERROR_MORE_DATA &&
  115. GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  116. {
  117. return HRESULT_FROM_WIN32( GetLastError() );
  118. }
  119. TOKEN_OWNER* pOwner = (TOKEN_OWNER*) new BYTE[dwSize];
  120. if ( pOwner == NULL )
  121. {
  122. return WBEM_E_OUT_OF_MEMORY;
  123. }
  124. CVectorDeleteMe<BYTE> vdm( (BYTE*)pOwner );
  125. if ( !GetTokenInformation( hProcessToken,
  126. TokenOwner,
  127. (BYTE*)pOwner,
  128. dwSize,
  129. &dwSize ) )
  130. {
  131. return HRESULT_FROM_WIN32( GetLastError() );
  132. }
  133. //
  134. // create a DACL that allows only authenticated users access.
  135. //
  136. SID AuthenticatedUsers;
  137. SID_IDENTIFIER_AUTHORITY idAuth = SECURITY_NT_AUTHORITY;
  138. InitializeSid( &AuthenticatedUsers, &idAuth, 1 );
  139. PDWORD pdwSubAuth = GetSidSubAuthority( &AuthenticatedUsers, 0 );
  140. *pdwSubAuth = SECURITY_AUTHENTICATED_USER_RID;
  141. _DBG_ASSERT( IsValidSid( &AuthenticatedUsers ) );
  142. dwSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - 4 +
  143. GetLengthSid(&AuthenticatedUsers);
  144. PACL pAuthOnlyAcl = (PACL) new BYTE[dwSize];
  145. if ( pAuthOnlyAcl == NULL )
  146. {
  147. return WBEM_E_OUT_OF_MEMORY;
  148. }
  149. CVectorDeleteMe<BYTE> vdm2( (BYTE*)pAuthOnlyAcl );
  150. InitializeAcl( pAuthOnlyAcl, dwSize, ACL_REVISION );
  151. AddAccessAllowedAce( pAuthOnlyAcl, ACL_REVISION, 1, &AuthenticatedUsers );
  152. //
  153. // create and initialize SD
  154. //
  155. SECURITY_DESCRIPTOR AuthOnlySD;
  156. InitializeSecurityDescriptor( &AuthOnlySD, SECURITY_DESCRIPTOR_REVISION );
  157. SetSecurityDescriptorOwner( &AuthOnlySD, pOwner->Owner, TRUE );
  158. SetSecurityDescriptorGroup( &AuthOnlySD, pOwner->Owner, TRUE );
  159. SetSecurityDescriptorDacl( &AuthOnlySD, TRUE, pAuthOnlyAcl, FALSE );
  160. dwSize = 0;
  161. MakeSelfRelativeSD( &AuthOnlySD, NULL, &dwSize );
  162. if ( GetLastError() != ERROR_MORE_DATA &&
  163. GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  164. {
  165. return HRESULT_FROM_WIN32( GetLastError() );
  166. }
  167. *ppSD = new BYTE[dwSize];
  168. if ( *ppSD == NULL )
  169. {
  170. return WBEM_E_OUT_OF_MEMORY;
  171. }
  172. if ( !MakeSelfRelativeSD( &AuthOnlySD, *ppSD, &dwSize ) )
  173. {
  174. delete [] *ppSD;
  175. *ppSD = NULL;
  176. return HRESULT_FROM_WIN32( GetLastError() );
  177. }
  178. return WBEM_S_NO_ERROR;
  179. }
  180. //
  181. // for now only one rpc receiver can be registered for the process. later
  182. // make the global state be the instance state for CMsgRpcReceiver.
  183. //
  184. STDMETHODIMP CMsgRpcReceiver::Open( LPCWSTR wszBinding,
  185. DWORD dwFlags,
  186. WMIMSG_RCVR_AUTH_INFOP pAuthInfo,
  187. IWmiMessageSendReceive* pRcv )
  188. {
  189. HRESULT hr;
  190. RPC_STATUS stat;
  191. CInCritSec ics( &g_csOpenClose );
  192. g_pLastOwner = this;
  193. hr = Close();
  194. if ( FAILED(hr) )
  195. {
  196. return hr;
  197. }
  198. //
  199. // first parse the binding string.
  200. //
  201. LPWSTR wszProtSeq, wszEndpoint;
  202. stat = RpcStringBindingParse( (LPWSTR)wszBinding,
  203. NULL,
  204. &wszProtSeq,
  205. NULL,
  206. &wszEndpoint,
  207. NULL );
  208. if ( stat != RPC_S_OK )
  209. {
  210. return RpcResToWmiRes( stat, S_OK );
  211. }
  212. //
  213. // init the protocol sequence
  214. //
  215. if ( *wszEndpoint == '\0' )
  216. {
  217. stat = RpcServerUseProtseq( wszProtSeq,
  218. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  219. NULL );
  220. if ( stat == RPC_S_OK )
  221. {
  222. RPC_BINDING_VECTOR* pBindingVector;
  223. stat = RpcServerInqBindings( &pBindingVector );
  224. if ( stat == RPC_S_OK )
  225. {
  226. stat = RpcEpRegisterNoReplace(
  227. RcvrIWmiMessageRemoteSendReceive_v1_0_s_ifspec,
  228. pBindingVector,
  229. NULL,
  230. NULL );
  231. RpcBindingVectorFree( &pBindingVector );
  232. }
  233. }
  234. }
  235. else
  236. {
  237. stat = RpcServerUseProtseqEp( wszProtSeq,
  238. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  239. wszEndpoint,
  240. NULL );
  241. }
  242. RpcStringFree( &wszProtSeq );
  243. RpcStringFree( &wszEndpoint );
  244. if ( stat != RPC_S_OK )
  245. {
  246. return RpcResToWmiRes( stat, S_OK );
  247. }
  248. //
  249. // enable negotiate authentication service ( negotiates between NTLM
  250. // and kerberos )
  251. //
  252. if ( pAuthInfo != NULL )
  253. {
  254. for( int i=0; i < pAuthInfo->cwszPrincipal; i++ )
  255. {
  256. stat = RpcServerRegisterAuthInfo(
  257. (LPWSTR)pAuthInfo->awszPrincipal[i],
  258. RPC_C_AUTHN_GSS_NEGOTIATE,
  259. NULL,
  260. NULL );
  261. if ( stat != RPC_S_OK )
  262. {
  263. return RpcResToWmiRes( stat, S_OK );
  264. }
  265. }
  266. }
  267. else
  268. {
  269. LPWSTR wszPrincipal;
  270. stat = RpcServerInqDefaultPrincName( RPC_C_AUTHN_GSS_NEGOTIATE,
  271. &wszPrincipal );
  272. if ( stat != RPC_S_OK )
  273. {
  274. return RpcResToWmiRes( stat, S_OK );
  275. }
  276. stat = RpcServerRegisterAuthInfo( wszPrincipal,
  277. RPC_C_AUTHN_GSS_NEGOTIATE,
  278. NULL,
  279. NULL );
  280. RpcStringFree( &wszPrincipal );
  281. if ( stat != RPC_S_OK )
  282. {
  283. return RpcResToWmiRes( stat, S_OK );
  284. }
  285. }
  286. RPC_IF_CALLBACK_FN* pAuthCallback = NULL;
  287. if ( dwFlags & WMIMSG_FLAG_RCVR_SECURE_ONLY )
  288. {
  289. PSECURITY_DESCRIPTOR pAuthOnlySD;
  290. hr = CreateAuthOnlySecurityDescriptor( &pAuthOnlySD );
  291. if ( FAILED(hr) )
  292. {
  293. return hr;
  294. }
  295. _DBG_ASSERT( g_pSD == NULL );
  296. g_pSD = pAuthOnlySD;
  297. pAuthCallback = RpcAuthCallback;
  298. }
  299. //
  300. // g_pRcv must be set before registering the interface, since a call
  301. // could arrive on that interface before returning from the register.
  302. // The call requires that g_pRcv be set.
  303. //
  304. _DBG_ASSERT( g_pRcv == NULL );
  305. pRcv->AddRef();
  306. g_pRcv = pRcv;
  307. //
  308. // register the interface
  309. //
  310. DWORD dwRpcFlags = RPC_IF_AUTOLISTEN;
  311. stat = RpcServerRegisterIfEx(
  312. RcvrIWmiMessageRemoteSendReceive_v1_0_s_ifspec,
  313. NULL,
  314. NULL,
  315. dwRpcFlags,
  316. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  317. pAuthCallback );
  318. if ( stat != RPC_S_OK )
  319. {
  320. return RpcResToWmiRes( stat, S_OK );
  321. }
  322. return WBEM_S_NO_ERROR;
  323. }
  324. STDMETHODIMP CMsgRpcReceiver::Close()
  325. {
  326. CInCritSec ics(&g_csOpenClose);
  327. if ( g_pLastOwner != this )
  328. return S_FALSE;
  329. RPC_STATUS stat;
  330. stat = RpcServerUnregisterIf(
  331. RcvrIWmiMessageRemoteSendReceive_v1_0_s_ifspec,
  332. NULL,
  333. 1 );
  334. RPC_BINDING_VECTOR* pBindingVector;
  335. stat = RpcServerInqBindings( &pBindingVector );
  336. if ( stat == RPC_S_OK )
  337. {
  338. stat = RpcEpUnregister(
  339. RcvrIWmiMessageRemoteSendReceive_v1_0_s_ifspec,
  340. pBindingVector,
  341. NULL );
  342. RpcBindingVectorFree( &pBindingVector );
  343. }
  344. if ( g_pRcv != NULL )
  345. {
  346. g_pRcv->Release();
  347. g_pRcv = NULL;
  348. }
  349. if ( g_pSD != NULL )
  350. {
  351. delete [] g_pSD;
  352. g_pSD = NULL;
  353. }
  354. return WBEM_S_NO_ERROR;
  355. }