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.

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