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.

765 lines
20 KiB

  1. #include "precomp.h"
  2. #include <sspi.h>
  3. #include <secext.h>
  4. #include <ntdsapi.h>
  5. #include <stdio.h>
  6. #include <buffer.h>
  7. #include <winntsec.h>
  8. #include <callsec.h>
  9. #include <wbemint.h>
  10. #include <wbemutil.h>
  11. #include <arrtempl.h>
  12. #include "fevprov.h"
  13. #include "fwdhdr.h"
  14. static LPWSTR g_wszEventClass = L"MSFT_ForwardedEvent";
  15. static LPWSTR g_wszEventProp = L"Event";
  16. static LPWSTR g_wszMachineProp = L"Machine";
  17. static LPWSTR g_wszConsumerProp = L"Consumer";
  18. static LPWSTR g_wszNamespaceProp = L"Namespace";
  19. static LPWSTR g_wszAuthenticatedProp = L"Authenticated";
  20. static LPWSTR g_wszAccountProp = L"Account";
  21. static LPWSTR g_wszSDProp = L"SECURITY_DESCRIPTOR";
  22. static LPWSTR g_wszTimeProp = L"Time";
  23. // {0F3162C5-7B5A-469f-955C-79603B7EB5A6}
  24. static const GUID g_guidQueueType =
  25. { 0xf3162c5, 0x7b5a, 0x469f, {0x95, 0x5c, 0x79, 0x60, 0x3b, 0x7e, 0xb5, 0xa6}};
  26. LPCWSTR g_awszQueueNames[] = { L".\\private$\\WMIFwdGuaranteed",
  27. L".\\private$\\WMIFwdExpress",
  28. L".\\private$\\WMIFwdGuaranteedAuth",
  29. L".\\private$\\WMIFwdExpressAuth",
  30. L".\\WMIFwdGuaranteedEncrypt",
  31. L".\\WMIFwdExpressEncrypt" };
  32. BOOL g_adwQueueQos[] = { WMIMSG_FLAG_QOS_GUARANTEED,
  33. WMIMSG_FLAG_QOS_EXPRESS,
  34. WMIMSG_FLAG_QOS_GUARANTEED,
  35. WMIMSG_FLAG_QOS_EXPRESS,
  36. WMIMSG_FLAG_QOS_GUARANTEED,
  37. WMIMSG_FLAG_QOS_EXPRESS };
  38. BOOL g_abQueueAuth[] = { FALSE, FALSE, TRUE, TRUE, TRUE, TRUE };
  39. extern BOOL AllowUnauthenticatedEvents();
  40. /**************************************************************************
  41. CFwdEventProv
  42. ***************************************************************************/
  43. CFwdEventProv::CFwdEventProv( CLifeControl* pCtl, IUnknown* pUnk )
  44. : CUnk( pCtl, pUnk ), m_XErrorSink( this ), m_XSendReceive( this ),
  45. m_XProv( this ), m_XQuery( this ), m_XInit( this ),
  46. m_lMachineProp(-1), m_lConsumerProp(-1), m_lNamespaceProp(-1),
  47. m_lAuthProp(-1), m_lAccountProp(-1), m_lTimeProp(-1), m_lSDProp(-1)
  48. {
  49. }
  50. CFwdEventProv::~CFwdEventProv()
  51. {
  52. }
  53. void* CFwdEventProv::GetInterface( REFIID riid )
  54. {
  55. if ( riid == IID_IWbemEventProvider )
  56. {
  57. return &m_XProv;
  58. }
  59. else if ( riid == IID_IWbemProviderInit )
  60. {
  61. return &m_XInit;
  62. }
  63. else if ( riid == IID_IWmiMessageTraceSink )
  64. {
  65. return &m_XErrorSink;
  66. }
  67. else if ( riid == IID_IWmiMessageSendReceive )
  68. {
  69. return &m_XSendReceive;
  70. }
  71. else if ( riid == IID_IWbemEventProviderQuerySink )
  72. {
  73. return &m_XQuery;
  74. }
  75. return NULL;
  76. }
  77. HRESULT CFwdEventProv::Init( IWbemServices* pSvc,
  78. IWbemProviderInitSink* pInitSink )
  79. {
  80. ENTER_API_CALL
  81. HRESULT hr;
  82. m_pSvc = pSvc;
  83. hr = pSvc->GetObject( g_wszEventClass,
  84. 0,
  85. NULL,
  86. &m_pEventClass,
  87. NULL );
  88. if ( FAILED(hr) )
  89. {
  90. return hr;
  91. }
  92. //
  93. // get handles for all the properties in the event .
  94. //
  95. CWbemPtr<_IWmiObject> pWmiEventClass;
  96. hr = m_pEventClass->QueryInterface( IID__IWmiObject,
  97. (void**)&pWmiEventClass );
  98. if ( FAILED(hr) )
  99. {
  100. return hr;
  101. }
  102. hr = pWmiEventClass->GetPropertyHandleEx( g_wszMachineProp,
  103. 0,
  104. NULL,
  105. &m_lMachineProp );
  106. if ( FAILED(hr) )
  107. {
  108. return hr;
  109. }
  110. hr = pWmiEventClass->GetPropertyHandleEx( g_wszConsumerProp,
  111. 0,
  112. NULL,
  113. &m_lConsumerProp );
  114. if ( FAILED(hr) )
  115. {
  116. return hr;
  117. }
  118. hr = pWmiEventClass->GetPropertyHandleEx( g_wszNamespaceProp,
  119. 0,
  120. NULL,
  121. &m_lNamespaceProp );
  122. if ( FAILED(hr) )
  123. {
  124. return hr;
  125. }
  126. hr = pWmiEventClass->GetPropertyHandleEx( g_wszAuthenticatedProp,
  127. 0,
  128. NULL,
  129. &m_lAuthProp );
  130. if ( FAILED(hr) )
  131. {
  132. return hr;
  133. }
  134. hr = pWmiEventClass->GetPropertyHandleEx( g_wszSDProp,
  135. 0,
  136. NULL,
  137. &m_lSDProp );
  138. if ( FAILED(hr) )
  139. {
  140. return hr;
  141. }
  142. hr = pWmiEventClass->GetPropertyHandleEx( g_wszAccountProp,
  143. 0,
  144. NULL,
  145. &m_lAccountProp );
  146. if ( FAILED(hr) )
  147. {
  148. return hr;
  149. }
  150. hr = pWmiEventClass->GetPropertyHandleEx( g_wszTimeProp,
  151. 0,
  152. NULL,
  153. &m_lTimeProp );
  154. if ( FAILED(hr) )
  155. {
  156. return hr;
  157. }
  158. hr = CoCreateInstance( CLSID_WmiSmartObjectUnmarshal,
  159. NULL,
  160. CLSCTX_INPROC,
  161. IID_IWmiObjectMarshal,
  162. (void**)&m_pMrsh );
  163. if ( FAILED(hr) )
  164. {
  165. return hr;
  166. }
  167. return pInitSink->SetStatus( WBEM_S_INITIALIZED, 0 );
  168. EXIT_API_CALL
  169. }
  170. HRESULT CFwdEventProv::InitializeEvent( IWbemClassObject* pOriginalEvent,
  171. IWmiMessageReceiverContext* pRecvCtx,
  172. LPCWSTR wszConsumer,
  173. LPCWSTR wszNamespace,
  174. PBYTE pSD,
  175. ULONG cSD,
  176. IWbemClassObject* pEvent )
  177. {
  178. HRESULT hr;
  179. VARIANT var;
  180. CWbemPtr<_IWmiObject> pWmiEvent;
  181. hr = pEvent->QueryInterface( IID__IWmiObject, (void**)&pWmiEvent );
  182. if ( FAILED(hr) )
  183. {
  184. return hr;
  185. }
  186. SYSTEMTIME st;
  187. BYTE achBuff[256];
  188. CBuffer Buff( achBuff, 256, FALSE );
  189. WCHAR* pwchBuff = (WCHAR*)Buff.GetRawData();
  190. ULONG cBuff = Buff.GetSize() / 2;
  191. //
  192. // Time Sent
  193. //
  194. hr = pRecvCtx->GetTimeSent( &st );
  195. if ( FAILED(hr) )
  196. {
  197. return hr;
  198. }
  199. StringCchPrintfW( pwchBuff,
  200. cBuff,
  201. L"%04.4d%02.2d%02.2d%02.2d%02.2d%02.2d.%06.6d+000",
  202. st.wYear, st.wMonth, st.wDay, st.wHour,
  203. st.wMinute, st.wSecond, 0 );
  204. hr = pWmiEvent->WritePropertyValue( m_lTimeProp,
  205. (wcslen(pwchBuff)+1)*2,
  206. Buff.GetRawData() );
  207. if ( FAILED(hr) )
  208. {
  209. return hr;
  210. }
  211. //
  212. // Sending Machine
  213. //
  214. pwchBuff = (WCHAR*)Buff.GetRawData();
  215. cBuff = Buff.GetSize() / 2;
  216. hr = pRecvCtx->GetSendingMachine( pwchBuff, cBuff, &cBuff );
  217. if ( hr == WBEM_S_FALSE )
  218. {
  219. hr = Buff.SetSize( cBuff*2 ); // note: size for wchars
  220. if ( FAILED(hr) )
  221. {
  222. return hr;
  223. }
  224. pwchBuff = (WCHAR*)Buff.GetRawData();
  225. cBuff = Buff.GetSize() / 2;
  226. hr = pRecvCtx->GetSendingMachine( pwchBuff, cBuff, &cBuff );
  227. }
  228. if ( SUCCEEDED(hr) && cBuff > 0 )
  229. {
  230. hr = pWmiEvent->WritePropertyValue( m_lMachineProp,
  231. cBuff*2,
  232. Buff.GetRawData() );
  233. }
  234. //
  235. // Sender Authenticated
  236. //
  237. hr = pRecvCtx->IsSenderAuthenticated();
  238. if ( FAILED(hr) )
  239. {
  240. return hr;
  241. }
  242. hr = pWmiEvent->WriteDWORD( m_lAuthProp, hr == S_OK ? 1 : 0 );
  243. if ( FAILED(hr) )
  244. {
  245. return hr;
  246. }
  247. //
  248. // Sender Identity
  249. //
  250. ULONG cSid;
  251. hr = pRecvCtx->GetSenderId( Buff.GetRawData(), Buff.GetSize(), &cSid );
  252. if ( hr == WBEM_S_FALSE )
  253. {
  254. hr = Buff.SetSize( cSid );
  255. if ( FAILED(hr) )
  256. {
  257. return hr;
  258. }
  259. hr = pRecvCtx->GetSenderId( Buff.GetRawData(), Buff.GetSize(), &cSid );
  260. }
  261. if ( SUCCEEDED(hr) && cSid > 0 )
  262. {
  263. hr = pWmiEvent->SetArrayPropRangeByHandle( m_lAccountProp,
  264. WMIARRAY_FLAG_ALLELEMENTS,
  265. 0,
  266. cSid,
  267. cSid,
  268. Buff.GetRawData() );
  269. }
  270. //
  271. // Original Event
  272. //
  273. V_VT(&var) = VT_UNKNOWN;
  274. V_UNKNOWN(&var) = pOriginalEvent;
  275. hr = pEvent->Put( g_wszEventProp, 0, &var, NULL );
  276. if ( FAILED(hr) )
  277. {
  278. return hr;
  279. }
  280. //
  281. // Sending Consumer Name
  282. //
  283. if ( wszConsumer != NULL )
  284. {
  285. hr = pWmiEvent->WritePropertyValue( m_lConsumerProp,
  286. (wcslen(wszConsumer)+1)*2,
  287. PBYTE(wszConsumer) );
  288. if ( FAILED(hr) )
  289. {
  290. return hr;
  291. }
  292. }
  293. //
  294. // Sending Consumer Namespace
  295. //
  296. if ( wszNamespace != NULL )
  297. {
  298. hr = pWmiEvent->WritePropertyValue( m_lNamespaceProp,
  299. (wcslen(wszNamespace)+1)*2,
  300. PBYTE(wszNamespace) );
  301. if ( FAILED(hr) )
  302. {
  303. return hr;
  304. }
  305. }
  306. //
  307. // set the security descriptor on the event if specified.
  308. //
  309. if ( cSD > 0 )
  310. {
  311. hr = pWmiEvent->SetArrayPropRangeByHandle( m_lSDProp,
  312. WMIARRAY_FLAG_ALLELEMENTS,
  313. 0,
  314. cSD,
  315. cSD,
  316. pSD );
  317. if ( FAILED(hr) )
  318. {
  319. return hr;
  320. }
  321. }
  322. return WBEM_S_NO_ERROR;
  323. }
  324. HRESULT CFwdEventProv::ProvideEvents( IWbemObjectSink* pSink, long lFlags )
  325. {
  326. ENTER_API_CALL
  327. m_pEventSink = pSink;
  328. //
  329. // we were waiting to obtain the sink before starting up the
  330. // receivers.
  331. //
  332. DEBUGTRACE((LOG_ESS,"FEVPROV: Begin Initializing.\n"));
  333. BOOL bAllowUnauth = AllowUnauthenticatedEvents();
  334. HRESULT hr;
  335. #ifdef __WHISTLER_UNCUT
  336. hr = InitializeQueues( bAllowUnauth );
  337. if ( FAILED(hr) )
  338. {
  339. return hr;
  340. }
  341. #endif
  342. hr = InitializeReceivers( bAllowUnauth );
  343. DEBUGTRACE((LOG_ESS,"FEVPROV: End Initializing.\n"));
  344. return hr;
  345. EXIT_API_CALL
  346. }
  347. HRESULT CFwdEventProv::InitializeQueues( BOOL bAllowUnauth )
  348. {
  349. HRESULT hr;
  350. DWORD dwQuota = 0xffffffff;
  351. PSECURITY_DESCRIPTOR pSecDesc = NULL;
  352. CWbemPtr<IWmiMessageQueueManager> pQueueMgr;
  353. hr = CoCreateInstance( CLSID_WmiMessageQueueManager,
  354. NULL,
  355. CLSCTX_INPROC,
  356. IID_IWmiMessageQueueManager,
  357. (void**)&pQueueMgr );
  358. if ( FAILED(hr) )
  359. {
  360. return hr;
  361. }
  362. for( int i=0 ; i < sizeof(g_adwQueueQos)/sizeof(DWORD); i++ )
  363. {
  364. if ( g_abQueueAuth[i] || (!g_abQueueAuth[i] && bAllowUnauth) )
  365. {
  366. hr = pQueueMgr->Create( g_awszQueueNames[i],
  367. g_guidQueueType,
  368. g_abQueueAuth[i],
  369. g_adwQueueQos[i],
  370. dwQuota,
  371. pSecDesc );
  372. if ( FAILED(hr) && hr != WBEM_E_ALREADY_EXISTS )
  373. {
  374. ERRORTRACE((LOG_ESS,"FEVPROV: Could not create/open queue %S, "
  375. "HR=0x%x\n", g_awszQueueNames[i], hr ));
  376. }
  377. }
  378. else
  379. {
  380. //
  381. // since we're not going to allow unauthenticated queues, make
  382. // sure that we delete any existing ones so that there's not an
  383. // open unauthenticated entry point on the machine. There will
  384. // only be a queue actually there to clean up if we're
  385. // transitioning from unauthenticated allowed to not allowed.
  386. //
  387. pQueueMgr->Destroy( g_awszQueueNames[i] );
  388. }
  389. }
  390. return WBEM_S_NO_ERROR;
  391. }
  392. HRESULT CFwdEventProv::InitializeReceivers( BOOL bAllowUnauth )
  393. {
  394. HRESULT hr;
  395. DWORD dwFlags = 0;
  396. if ( !bAllowUnauth )
  397. {
  398. dwFlags |= WMIMSG_FLAG_RCVR_SECURE_ONLY;
  399. }
  400. //
  401. // Initialize Sync DCOM Receiver.
  402. //
  403. hr = CoCreateInstance( CLSID_WmiMessageRpcReceiver,
  404. NULL,
  405. CLSCTX_INPROC,
  406. IID_IWmiMessageReceiver,
  407. (void**)&m_pDcomRcvr );
  408. if ( FAILED(hr) )
  409. {
  410. return hr;
  411. }
  412. hr = m_pDcomRcvr->Open(
  413. L"7879E40D-9FB5-450a-8A6D-00C89F349FCE@ncacn_ip_tcp:",
  414. WMIMSG_FLAG_QOS_SYNCHRONOUS | dwFlags,
  415. NULL,
  416. &m_XSendReceive );
  417. if ( FAILED(hr) )
  418. {
  419. ERRORTRACE((LOG_ESS,"FEVPROV: Could not open dcom rcvr, "
  420. "HR=0x%x\n", hr ));
  421. return hr;
  422. }
  423. #ifdef __WHISTLER_UNCUT
  424. for( int i=0; i < sizeof(g_adwQueueQos)/sizeof(DWORD); i++ )
  425. {
  426. if ( g_abQueueAuth[i] || (!g_abQueueAuth[i] && bAllowUnauth) )
  427. {
  428. hr = CoCreateInstance( CLSID_WmiMessageMsmqReceiver,
  429. NULL,
  430. CLSCTX_INPROC,
  431. IID_IWmiMessageReceiver,
  432. (void**)&m_apQueueRcvr[i] );
  433. if ( FAILED(hr) )
  434. {
  435. return hr;
  436. }
  437. hr = m_apQueueRcvr[i]->Open( g_awszQueueNames[i],
  438. g_adwQueueQos[i] | dwFlags,
  439. NULL,
  440. &m_XSendReceive );
  441. if ( FAILED(hr) )
  442. {
  443. ERRORTRACE((LOG_ESS,"FEVPROV: Could not open rcvr for queue %S"
  444. ", HR=0x%x\n", g_awszQueueNames[i], hr ));
  445. }
  446. }
  447. }
  448. #endif
  449. return WBEM_S_NO_ERROR;
  450. }
  451. HRESULT CFwdEventProv::NewQuery( DWORD dwId, LPWSTR wszQuery )
  452. {
  453. return WBEM_S_NO_ERROR;
  454. }
  455. HRESULT CFwdEventProv::CancelQuery( DWORD dwId )
  456. {
  457. return WBEM_S_NO_ERROR;
  458. }
  459. HRESULT CFwdEventProv::Receive( PBYTE pData,
  460. ULONG cData,
  461. PBYTE pAuxData,
  462. ULONG cAuxData,
  463. DWORD dwStatus,
  464. IUnknown* pCtx )
  465. {
  466. ENTER_API_CALL
  467. HRESULT hr;
  468. CBuffer DataStrm( pData, cData, FALSE );
  469. CBuffer HdrStrm( pAuxData, cAuxData, FALSE );
  470. //
  471. // read and verify msg hdr - don't do much with it though - it mostly
  472. // contains info for nack event prov.
  473. //
  474. CFwdMsgHeader FwdHdr;
  475. hr = FwdHdr.Unpersist( HdrStrm );
  476. if ( FAILED(hr) )
  477. {
  478. return hr;
  479. }
  480. //
  481. // read objects and generate event.
  482. //
  483. #define MAXEVENTS 256
  484. IWbemClassObject* apEvents[MAXEVENTS];
  485. DWORD i=0;
  486. hr = S_OK;
  487. CWbemPtr<IWmiMessageReceiverContext> pRecvCtx;
  488. if ( pCtx == NULL || pCtx->QueryInterface( IID_IWmiMessageReceiverContext,
  489. (void**)&pRecvCtx ) != S_OK )
  490. {
  491. return WBEM_E_CRITICAL_ERROR;
  492. }
  493. //
  494. // if possible, convert our recv ctx to com context so that ess can
  495. // impersonate the sender if necessary.
  496. //
  497. IWbemCallSecurity* pSec = NULL;
  498. hr = pRecvCtx->ImpersonateSender();
  499. if ( SUCCEEDED(hr) )
  500. {
  501. pSec = CWbemCallSecurity::CreateInst(); // ref is 1 on create.
  502. if ( pSec == NULL )
  503. {
  504. pRecvCtx->RevertToSelf();
  505. return WBEM_E_OUT_OF_MEMORY;
  506. }
  507. hr = pSec->CloneThreadContext( FALSE );
  508. pRecvCtx->RevertToSelf();
  509. IUnknown* pUnkSec = NULL;
  510. if ( SUCCEEDED(hr) )
  511. {
  512. hr = CoSwitchCallContext( pSec, &pUnkSec );
  513. }
  514. if ( FAILED(hr) )
  515. {
  516. pSec->Release();
  517. return hr;
  518. }
  519. _DBG_ASSERT( pUnkSec == NULL );
  520. }
  521. else if ( pRecvCtx->IsSenderAuthenticated() == S_FALSE )
  522. {
  523. //
  524. // it is expected that ImpersonateClient will fail if
  525. // the sender is not authenticated.
  526. //
  527. hr = WBEM_S_NO_ERROR;
  528. }
  529. else
  530. {
  531. //
  532. // something else wrong here.
  533. //
  534. return WMIMSG_E_AUTHFAILURE;
  535. }
  536. const PSECURITY_DESCRIPTOR pSD = FwdHdr.GetTargetSD();
  537. ULONG cSD = FwdHdr.GetTargetSDLength();
  538. ULONG iData = DataStrm.GetIndex();
  539. while( i < FwdHdr.GetNumObjects() && SUCCEEDED(hr) )
  540. {
  541. for( DWORD j=0; j < MAXEVENTS && j+i < FwdHdr.GetNumObjects(); j++ )
  542. {
  543. ULONG cUsed;
  544. CWbemPtr<IWbemClassObject> pOriginalEvent;
  545. hr = m_pMrsh->Unpack( cData-iData,
  546. pData+iData,
  547. 0,
  548. &pOriginalEvent,
  549. &cUsed );
  550. if ( FAILED(hr) )
  551. {
  552. break;
  553. }
  554. iData += cUsed;
  555. CWbemPtr<IWbemClassObject> pEvent;
  556. hr = m_pEventClass->SpawnInstance( NULL, &pEvent );
  557. if ( FAILED(hr) )
  558. {
  559. break;
  560. }
  561. hr = InitializeEvent( pOriginalEvent,
  562. pRecvCtx,
  563. FwdHdr.GetConsumer(),
  564. FwdHdr.GetNamespace(),
  565. PBYTE(pSD),
  566. cSD,
  567. pEvent );
  568. if ( FAILED(hr) )
  569. {
  570. break;
  571. }
  572. pEvent->AddRef();
  573. apEvents[j] = pEvent;
  574. }
  575. i += j;
  576. if ( SUCCEEDED(hr) )
  577. {
  578. hr = m_pEventSink->Indicate( j, apEvents );
  579. }
  580. for( DWORD k=0; k < j; k++ )
  581. {
  582. apEvents[k]->Release();
  583. }
  584. }
  585. //
  586. // if we switched the com call context, then switch it back.
  587. //
  588. if ( pSec != NULL )
  589. {
  590. IUnknown* pDummy;
  591. if ( SUCCEEDED(CoSwitchCallContext( NULL, &pDummy ) ) )
  592. {
  593. _DBG_ASSERT( pDummy == pSec );
  594. pSec->Release();
  595. }
  596. }
  597. return hr;
  598. EXIT_API_CALL
  599. }
  600. HRESULT CFwdEventProv::HandleRecvError( HRESULT hr, LPCWSTR wszError )
  601. {
  602. //
  603. // right now just log to ESS log.
  604. //
  605. ERRORTRACE((LOG_ESS,"FEVPROV: RECV Error, ErrorString=%S, HR=0x%x\n",
  606. wszError, hr ));
  607. return S_OK;
  608. }