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.

2100 lines
71 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995.
  5. //
  6. // File:
  7. // remact.cxx
  8. //
  9. // Contents:
  10. //
  11. // Implementation of binding handle cache to remote activation services.
  12. //
  13. // History:
  14. //
  15. //--------------------------------------------------------------------------
  16. #include "act.hxx"
  17. #include "misc.hxx"
  18. CRemoteMachineList * gpRemoteMachineList = NULL;
  19. CSharedLock * gpRemoteMachineLock = NULL;
  20. // These globals are set to their defaults here, but can be overridden at boot
  21. // time via registry knobs. See ReadRemoteBindingHandleCacheKeys in registry.cxx.
  22. // Also note that gdwRemoteBindingHandleCacheMaxSize cannot be adjusted after boot,
  23. // but gdwRemoteBindingHandleCacheMaxLifetime and gdwRemoteBindingHandleCacheIdleTimeout can
  24. // be played with in the debugger at will for those so inclined.
  25. DWORD gdwRemoteBindingHandleCacheMaxSize = 16; // in # of cache elements
  26. DWORD gdwRemoteBindingHandleCacheMaxLifetime = 0; // in minutes
  27. DWORD gdwRemoteBindingHandleCacheIdleTimeout = 15; // in minutes
  28. class CRemActPPing : public CParallelPing
  29. {
  30. public:
  31. CRemActPPing(WCHAR *pMachine) :
  32. _ndx(0),
  33. _pMachine(pMachine)
  34. {}
  35. BOOL NextCall(PROTSEQINFO *pProtseqInfo)
  36. {
  37. RPC_STATUS status;
  38. if (_ndx < cMyProtseqs)
  39. {
  40. status = CreateRemoteBinding(_pMachine,
  41. _ndx,
  42. &pProtseqInfo->hRpc);
  43. if (status != RPC_S_OK)
  44. {
  45. pProtseqInfo->hRpc = NULL;
  46. }
  47. pProtseqInfo->dwUserInfo = _ndx;
  48. _ndx++;
  49. return TRUE;
  50. }
  51. else
  52. {
  53. return FALSE;
  54. }
  55. }
  56. void ReleaseCall(PROTSEQINFO *pProtseqInfo)
  57. {
  58. if (pProtseqInfo->hRpc)
  59. {
  60. RpcBindingFree(&pProtseqInfo->hRpc);
  61. }
  62. }
  63. private:
  64. DWORD _ndx;
  65. WCHAR *_pMachine;
  66. };
  67. //+---------------------------------------------------------------------------
  68. //
  69. // Function: RemoteActivationCall
  70. //
  71. // Synopsis: Finds or creates a machine object to cache binding handles
  72. // to the server machine and forwards the activation request
  73. // to it.
  74. //
  75. //----------------------------------------------------------------------------
  76. HRESULT
  77. RemoteActivationCall(
  78. ACTIVATION_PARAMS * pActParams,
  79. WCHAR * pwszServerName )
  80. {
  81. CRemoteMachine * pRemoteMachine;
  82. WCHAR wszPathForServer[MAX_PATH+1];
  83. WCHAR * pwszPathForServer;
  84. HRESULT hr;
  85. pActParams->activatedRemote = TRUE;
  86. ASSERT( pwszServerName );
  87. pwszPathForServer = 0;
  88. if ( pActParams->pwszPath )
  89. {
  90. hr = GetPathForServer( pActParams->pwszPath, wszPathForServer, &pwszPathForServer );
  91. if ( hr != S_OK )
  92. return hr;
  93. }
  94. pRemoteMachine = gpRemoteMachineList->GetOrAdd( pwszServerName );
  95. if ( ! pRemoteMachine )
  96. return E_OUTOFMEMORY;
  97. ASSERT(pActParams->pActPropsIn);
  98. BOOL fUseSystemId;
  99. pActParams->pActPropsIn->GetRemoteActivationFlags(&pActParams->fComplusOnly,
  100. &fUseSystemId);
  101. if (!fUseSystemId)
  102. {
  103. if (pActParams->pToken != NULL)
  104. pActParams->pToken->Impersonate();
  105. else
  106. {
  107. pRemoteMachine->Release();
  108. return HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  109. }
  110. }
  111. IServerLocationInfo *pServerLocationInfo = NULL;
  112. ISpecialSystemProperties* pSSP = NULL;
  113. ULONG ulCurrentSessionId = 0;
  114. BOOL bUseConsole = FALSE;
  115. BOOL fRemoteThisSessionId = FALSE;
  116. pServerLocationInfo = pActParams->pActPropsIn->GetServerLocationInfo();
  117. ASSERT(pServerLocationInfo != NULL);
  118. pServerLocationInfo->SetRemoteServerName(NULL);
  119. //
  120. // Session id's should flow off-machine only when explicitly told to; make sure
  121. // this is the case:
  122. //
  123. hr = pActParams->pActPropsIn->QueryInterface(IID_ISpecialSystemProperties, (void**)&pSSP);
  124. if (SUCCEEDED(hr))
  125. {
  126. pSSP->GetSessionId2(&ulCurrentSessionId, &bUseConsole, &fRemoteThisSessionId);
  127. if (!fRemoteThisSessionId)
  128. {
  129. hr = pSSP->SetSessionId(INVALID_SESSION_ID, FALSE, FALSE);
  130. ASSERT(SUCCEEDED(hr) && "SetSessionId failed");
  131. }
  132. }
  133. //
  134. // Try the activation:
  135. //
  136. hr = pRemoteMachine->Activate( pActParams, pwszPathForServer );
  137. //
  138. // Restore session id just in case the activation ends up being re-tried (for
  139. // whatever reason) on this machine (eg, if a load-balancing activator is loaded)
  140. //
  141. if (!fRemoteThisSessionId)
  142. {
  143. HRESULT hrLocal;
  144. hrLocal = pSSP->SetSessionId(ulCurrentSessionId, bUseConsole, FALSE);
  145. ASSERT(SUCCEEDED(hrLocal) && "SetSessionId failed");
  146. }
  147. if (pSSP)
  148. pSSP->Release();
  149. pRemoteMachine->Release();
  150. if (!fUseSystemId)
  151. pActParams->pToken->Revert();
  152. return hr;
  153. }
  154. //+---------------------------------------------------------------------------
  155. //
  156. // Function: CRemoteMachineList::GetOrAdd
  157. //
  158. // Synopsis: Scans the machine list for a matching name. Returns it if
  159. // found. Otherwise, creates a machine list entry. Returned
  160. // object is refcounted.
  161. //
  162. // Changes: jsimmons 4/6/00 Fix for bug 22803 -- cap cache size
  163. //
  164. //----------------------------------------------------------------------------
  165. CRemoteMachine *
  166. CRemoteMachineList::GetOrAdd(
  167. IN WCHAR * pwszMachine
  168. )
  169. {
  170. CRemoteMachine * pMachine;
  171. WCHAR * pwszMachineCopy;
  172. WCHAR * pwszScmSPNCopy;
  173. gpRemoteMachineLock->LockExclusive();
  174. for ( pMachine = (CRemoteMachine *) First();
  175. pMachine;
  176. pMachine = (CRemoteMachine *) pMachine->Next() )
  177. {
  178. if ( lstrcmpiW( pMachine->_pwszMachine, pwszMachine ) == 0 )
  179. {
  180. pMachine->_dwLastUsedTickCount = GetTickCount();
  181. pMachine->AddRef(); // add caller reference
  182. break;
  183. }
  184. }
  185. if ( ! pMachine )
  186. {
  187. pwszMachineCopy = (WCHAR *) PrivMemAlloc( (lstrlenW( pwszMachine ) + 1) * sizeof(WCHAR) );
  188. if (pwszMachineCopy)
  189. {
  190. pwszScmSPNCopy = (WCHAR *) PrivMemAlloc( (lstrlenW( pwszMachine ) +
  191. (sizeof(RPCSS_SPN_PREFIX) / sizeof(WCHAR))
  192. + 1) * sizeof(WCHAR) );
  193. if (pwszScmSPNCopy)
  194. {
  195. lstrcpyW( pwszMachineCopy, pwszMachine );
  196. // Form server principal name for the remote scm
  197. lstrcpyW( pwszScmSPNCopy, RPCSS_SPN_PREFIX);
  198. lstrcatW( pwszScmSPNCopy, pwszMachine);
  199. pMachine = new CRemoteMachine( pwszMachineCopy, pwszScmSPNCopy);
  200. // constructed with refcount of 1, don't addref it again
  201. if ( pMachine )
  202. {
  203. // Only attempt to save new object in cache if cache size > 0:
  204. if (_dwMaxCacheSize > 0)
  205. {
  206. ASSERT(_dwCacheSize <= _dwMaxCacheSize);
  207. if (_dwCacheSize == _dwMaxCacheSize)
  208. {
  209. // Cache has no more room. Dump the oldest one
  210. RemoveOldestCacheElement();
  211. ASSERT(_dwCacheSize < _dwMaxCacheSize);
  212. }
  213. Insert( pMachine );
  214. pMachine->AddRef();
  215. _dwCacheSize++;
  216. ASSERT(_dwCacheSize <= _dwMaxCacheSize);
  217. }
  218. }
  219. else
  220. {
  221. PrivMemFree( pwszMachineCopy );
  222. PrivMemFree( pwszScmSPNCopy );
  223. }
  224. }
  225. else
  226. {
  227. PrivMemFree(pwszMachineCopy);
  228. }
  229. }
  230. }
  231. gpRemoteMachineLock->UnlockExclusive();
  232. return pMachine;
  233. }
  234. //+---------------------------------------------------------------------------
  235. //
  236. // Function: CRemoteMachineList::CRemoteMachine
  237. //
  238. // Synopsis: Looks thru the cache for the lru element and removes it.
  239. //
  240. //----------------------------------------------------------------------------
  241. void CRemoteMachineList::RemoveOldestCacheElement()
  242. {
  243. ASSERT(_dwCacheSize > 0);
  244. ASSERT(gpRemoteMachineLock->HeldExclusive());
  245. CRemoteMachine* pLRUMachine = (CRemoteMachine*)First();
  246. CRemoteMachine* pMachine = (CRemoteMachine*)pLRUMachine->Next();
  247. while (pMachine)
  248. {
  249. if (pMachine->_dwLastUsedTickCount < pLRUMachine->_dwLastUsedTickCount)
  250. {
  251. pLRUMachine = pMachine;
  252. }
  253. pMachine = (CRemoteMachine*)pMachine->Next();
  254. }
  255. Remove(pLRUMachine);
  256. pLRUMachine->Release();
  257. _dwCacheSize--;
  258. return;
  259. }
  260. //+---------------------------------------------------------------------------
  261. //
  262. // Function: CRemoteMachineList::FlushSpecificBindings
  263. //
  264. // Synopsis: Looks thru the cache for the specified element and removes it
  265. // from the cache if found.
  266. //
  267. // Arguments: [pszMachine] -- name of the machine to flush from the cache. Can
  268. // be ""; this means all bindings should be flushed
  269. //
  270. // Returns: S_OK -- the specified bindings were found and flushed
  271. // CO_S_MACHINENAMENOTFOUND -- if "" was passed, means the cache was
  272. // empty; otherwise means that the specified machine name was not
  273. // found in the cache.
  274. //
  275. //----------------------------------------------------------------------------
  276. HRESULT CRemoteMachineList::FlushSpecificBindings(WCHAR* pszMachine)
  277. {
  278. HRESULT hr = CO_S_MACHINENAMENOTFOUND;
  279. BOOL bFlushAll = (0 == lstrcmpW(pszMachine, L""));
  280. CRemoteMachine* pMachine;
  281. CRemoteMachine* pNextMachine;
  282. gpRemoteMachineLock->LockExclusive();
  283. if (bFlushAll)
  284. {
  285. // Loop thru and release all of them
  286. while (pMachine = (CRemoteMachine*)First())
  287. {
  288. Remove(pMachine);
  289. pMachine->Release();
  290. _dwCacheSize--;
  291. hr = S_OK; // there was at least one item in the cache, so return S_OK
  292. }
  293. }
  294. else
  295. {
  296. // Loop thru looking for the specified machine name
  297. pMachine = (CRemoteMachine*)First();
  298. while (pMachine)
  299. {
  300. if (lstrcmpiW(pszMachine, pMachine->_pwszMachine) == 0)
  301. {
  302. // Found it
  303. Remove(pMachine);
  304. pMachine->Release();
  305. _dwCacheSize--;
  306. hr = S_OK; // found it so return S_OK
  307. break;
  308. }
  309. pMachine = (CRemoteMachine*)pMachine->Next();
  310. }
  311. }
  312. gpRemoteMachineLock->UnlockExclusive();
  313. return hr;
  314. }
  315. //+---------------------------------------------------------------------------
  316. //
  317. // Function: CRemoteMachineList::TryToFlushIdleOrTooOldElements
  318. //
  319. // Synopsis: Looks thru the cache for elements which have either 1) not been
  320. // used for a period than the idle timeout period; or 2) been in the cache
  321. // longer than the maximum allowable period. If any are found they are
  322. // deleted from the cache.
  323. //
  324. // Arguments: none
  325. //
  326. // Returns: void
  327. //
  328. //----------------------------------------------------------------------------
  329. void CRemoteMachineList::TryToFlushIdleOrTooOldElements()
  330. {
  331. CRemoteMachine* pMachine;
  332. CRemoteMachine* pNextMachine;
  333. DWORD dwNow = GetTickCount();
  334. DWORD dwIdleTimeout = gdwRemoteBindingHandleCacheIdleTimeout * 1000 * 60;
  335. DWORD dwLifetimeTimeout = gdwRemoteBindingHandleCacheMaxLifetime * 1000 * 60;
  336. if (!dwIdleTimeout && !dwLifetimeTimeout)
  337. return; // nothing to do
  338. gpRemoteMachineLock->LockExclusive();
  339. pMachine = (CRemoteMachine*)First();
  340. while (pMachine)
  341. {
  342. BOOL bRemoveCurrentItem;
  343. bRemoveCurrentItem = FALSE;
  344. // Check if it's been idle too long
  345. if (dwIdleTimeout > 0)
  346. {
  347. if (dwNow - pMachine->_dwLastUsedTickCount > dwIdleTimeout)
  348. {
  349. bRemoveCurrentItem = TRUE;
  350. }
  351. }
  352. // Check if it's been around too long, period
  353. if (dwLifetimeTimeout > 0)
  354. {
  355. if (dwNow - pMachine->_dwTickCountAtCreate > dwLifetimeTimeout)
  356. {
  357. bRemoveCurrentItem = TRUE;
  358. }
  359. }
  360. pNextMachine = (CRemoteMachine*)pMachine->Next();
  361. if (bRemoveCurrentItem)
  362. {
  363. Remove(pMachine);
  364. pMachine->Release();
  365. _dwCacheSize--;
  366. }
  367. pMachine = pNextMachine;
  368. }
  369. gpRemoteMachineLock->UnlockExclusive();
  370. }
  371. //+---------------------------------------------------------------------------
  372. //
  373. // Function: OLESCMBindingHandleFlush
  374. //
  375. // Synopsis: This function gets called periodically by objex's worker
  376. // thread. It gives us a chance to flush idle or too-old cache elements
  377. // in the remote binding handle cache.
  378. //
  379. //----------------------------------------------------------------------------
  380. void OLESCMBindingHandleFlush()
  381. {
  382. gpRemoteMachineList->TryToFlushIdleOrTooOldElements();
  383. }
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Function: CRemoteMachine::CRemoteMachine
  387. //
  388. // Synopsis: Constructor
  389. //
  390. //----------------------------------------------------------------------------
  391. CRemoteMachine::CRemoteMachine(
  392. IN WCHAR * pwszMachine,
  393. IN WCHAR * pwszScmSPN
  394. )
  395. {
  396. _pwszMachine = pwszMachine;
  397. _pwszScmSPN = pwszScmSPN;
  398. _dsa = NULL;
  399. _ulRefCount = 1; // starts with non-zero refcount
  400. _dwLastUsedTickCount = GetTickCount();
  401. _dwTickCountAtCreate = _dwLastUsedTickCount;
  402. _fUseOldActivationInterface = TRUE;
  403. }
  404. //+---------------------------------------------------------------------------
  405. //
  406. // Function: CRemoteMachine::CRemoteMachine
  407. //
  408. // Synopsis: Destructor
  409. //
  410. //----------------------------------------------------------------------------
  411. CRemoteMachine::~CRemoteMachine()
  412. {
  413. ASSERT(_ulRefCount == 0);
  414. // We don't need to hold a lock to flush the bindings,
  415. // since no one else has a reference to us.
  416. FlushBindingsNoLock();
  417. if (_pwszMachine)
  418. PrivMemFree(_pwszMachine);
  419. if (_pwszScmSPN)
  420. PrivMemFree(_pwszScmSPN);
  421. if (_dsa)
  422. _dsa->Release();
  423. }
  424. // AddRef function
  425. ULONG CRemoteMachine::AddRef()
  426. {
  427. return InterlockedIncrement((PLONG)&_ulRefCount);
  428. }
  429. // Release function
  430. ULONG CRemoteMachine::Release()
  431. {
  432. ULONG ulNewRefCount = InterlockedDecrement((PLONG)&_ulRefCount);
  433. if (ulNewRefCount == 0)
  434. {
  435. delete this;
  436. }
  437. return ulNewRefCount;
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Function: CRemoteMachine::Activate
  442. //
  443. // Synopsis: Picks a protocol and authentication service to use to call
  444. // the server machine. Forwards the activation request to
  445. // CallRemoteMachine.
  446. //
  447. // Description:
  448. //
  449. // This method tries several different methods to get a binding handle.
  450. // Look for auth info match in cache
  451. // Look for any binding handle in cache
  452. // Ping server to find valid protocol sequence
  453. //
  454. // After it gets a binding handle, it tries to pick auth info.
  455. // Use client params if specified
  456. // Use cached params if they exist
  457. // Try all auth svc valid on client and server
  458. // Try unsecure
  459. //
  460. // This function maintains a cache of binding handles with the following
  461. // rules.
  462. // - All binding handles in the cache at any point in time use the same
  463. // protocol sequence.
  464. // - The best non-custom authentication info is before any other
  465. // non-custom authentication info.
  466. // - The cache is flushed if the protocol is competely invalid.
  467. // - If a cached entry gets a non security error, it is discarded
  468. // (security errors may be due to the current credentials rather then
  469. // the binding handle itself).
  470. // - Only binding handles that actually worked once are cached.
  471. //
  472. //----------------------------------------------------------------------------
  473. HRESULT
  474. CRemoteMachine::Activate(
  475. IN ACTIVATION_PARAMS * pActParams,
  476. IN WCHAR * pwszPathForServer
  477. )
  478. {
  479. CMachineBinding * pMachineBinding;
  480. handle_t hBinding = NULL;
  481. BOOL bNoEndpoint;
  482. BOOL bStatus;
  483. HRESULT hr = E_OUTOFMEMORY;
  484. USHORT AuthnSvc;
  485. USHORT ProtseqId = 0;
  486. DWORD AuthnLevel;
  487. RPC_STATUS Status = RPC_S_INTERNAL_ERROR;
  488. // Try to use a cached handle first.
  489. if (pActParams->pAuthInfo != NULL)
  490. AuthnSvc = (USHORT) pActParams->pAuthInfo->dwAuthnSvc;
  491. else
  492. AuthnSvc = AUTHN_ANY;
  493. hr = GetAuthnLevel(pActParams, &AuthnLevel);
  494. if (FAILED(hr))
  495. return hr;
  496. pMachineBinding = LookupBinding( AuthnSvc, AuthnLevel, pActParams->pAuthInfo );
  497. if ( pMachineBinding )
  498. {
  499. AuthnSvc = pMachineBinding->_AuthnSvc;
  500. Status = pMachineBinding->GetMarshaledTargetInfo(&pActParams->ulMarshaledTargetInfoLength, &pActParams->pMarshaledTargetInfo);
  501. if (Status == RPC_S_OK)
  502. {
  503. Status = CallRemoteMachine(pMachineBinding->_hBinding,
  504. pMachineBinding->_ProtseqId,
  505. pActParams,
  506. pwszPathForServer,
  507. _pwszMachine,
  508. _fUseOldActivationInterface,
  509. &hr);
  510. }
  511. if (Status == RPC_S_OK)
  512. {
  513. pActParams->AuthnSvc = AuthnSvc;
  514. pMachineBinding->Release();
  515. return hr;
  516. }
  517. // Throw away the binding if it is unlikely to work again in the
  518. // future.
  519. else if (Status != RPC_S_ACCESS_DENIED &&
  520. Status != RPC_S_SEC_PKG_ERROR)
  521. {
  522. RemoveBinding( pMachineBinding );
  523. }
  524. pMachineBinding->Release();
  525. }
  526. // Throw away all bindings if the protocol is unlikely to work
  527. // again.
  528. if (Status == RPC_S_SERVER_UNAVAILABLE ||
  529. Status == EPT_S_NOT_REGISTERED)
  530. {
  531. FlushBindings();
  532. }
  533. // Get any binding handle from the cache.
  534. else
  535. {
  536. gpRemoteMachineLock->LockShared();
  537. pMachineBinding = (CMachineBinding *) _BindingList.First();
  538. if (pMachineBinding != NULL)
  539. {
  540. Status = RpcBindingCopy( pMachineBinding->_hBinding, &hBinding );
  541. if (Status == RPC_S_OK)
  542. {
  543. ASSERT(hBinding != NULL);
  544. ProtseqId = pMachineBinding->_ProtseqId;
  545. }
  546. else
  547. hBinding = NULL;
  548. }
  549. gpRemoteMachineLock->UnlockShared();
  550. // Try to find auth info that will work.
  551. if (hBinding != NULL)
  552. {
  553. Assert (pMachineBinding != NULL);
  554. Status = PickAuthnAndActivate( pActParams, pwszPathForServer,
  555. &hBinding, AuthnSvc, AuthnLevel,
  556. ProtseqId, &hr );
  557. if (Status == RPC_S_OK)
  558. {
  559. Assert( hBinding == NULL );
  560. return hr;
  561. }
  562. else
  563. {
  564. // Stop if the activation failed but the protocol was
  565. // probably good.
  566. Assert( hBinding != NULL );
  567. RpcBindingFree( &hBinding );
  568. hBinding = NULL;
  569. if (Status != RPC_S_SERVER_UNAVAILABLE &&
  570. Status != EPT_S_NOT_REGISTERED)
  571. {
  572. if (Status == RPC_S_ACCESS_DENIED)
  573. {
  574. // Don't map security errors as this is just confusing.
  575. return HRESULT_FROM_WIN32(RPC_S_ACCESS_DENIED);
  576. }
  577. else
  578. {
  579. LogRemoteSideUnavailable( pActParams->ClsContext, _pwszMachine );
  580. return HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE);
  581. }
  582. }
  583. }
  584. }
  585. }
  586. // No cached binding handles worked. Try to ping for one.
  587. {
  588. CRemActPPing ping(_pwszMachine);
  589. // This loop only executes twice if we need to try the call without
  590. // an endpoint specified.
  591. //
  592. bNoEndpoint = FALSE;
  593. for (;;)
  594. {
  595. Status = ping.Ping();
  596. if ( RPC_S_UNKNOWN_IF == Status )
  597. {
  598. if ( ! bNoEndpoint )
  599. {
  600. for ( ULONG ProtseqIndex = 0; ProtseqIndex < ping.HandleCount(); ProtseqIndex++ )
  601. {
  602. RPC_BINDING_HANDLE tmpBinding;
  603. Status = RpcBindingCopy( ping.Info(ProtseqIndex)->hRpc, &tmpBinding);
  604. if (Status != RPC_S_OK)
  605. break;
  606. Status = RpcBindingFree( &(ping.Info(ProtseqIndex)->hRpc));
  607. if (Status != RPC_S_OK)
  608. {
  609. RpcBindingFree(&tmpBinding);
  610. break;
  611. }
  612. Status = RpcBindingReset(tmpBinding);
  613. if (Status != RPC_S_OK)
  614. {
  615. RpcBindingFree(&tmpBinding);
  616. break;
  617. }
  618. ping.Info(ProtseqIndex)->hRpc = tmpBinding;
  619. }
  620. if (Status == RPC_S_OK)
  621. {
  622. bNoEndpoint = TRUE;
  623. continue;
  624. }
  625. }
  626. }
  627. break;
  628. }
  629. if (Status == RPC_S_OK)
  630. {
  631. gpRemoteMachineLock->LockExclusive();
  632. if (_dsa != NULL)
  633. _dsa->Release();
  634. hBinding = ping.GetWinner()->hRpc;
  635. ping.GetWinner()->hRpc = NULL;
  636. _dsa = ping.TakeOrBindings();
  637. ProtseqId = aMyProtseqs[ping.GetWinner()->dwUserInfo];
  638. ASSERT( hBinding != NULL );
  639. //
  640. // If this is not a win2k or better system, then use the old activation
  641. // interface. Otherwise, use the new activation interface.
  642. //
  643. if (ping.GetWinner()->comVersion.MinorVersion < 6)
  644. {
  645. _fUseOldActivationInterface = TRUE;
  646. }
  647. else
  648. {
  649. _fUseOldActivationInterface = FALSE;
  650. }
  651. gpRemoteMachineLock->UnlockExclusive();
  652. }
  653. ping.Reset();
  654. }
  655. // Try auth info with the new binding.
  656. if (hBinding != NULL)
  657. {
  658. // We've had to re-bind. Make sure we've still decided on
  659. // the right authentication level here.
  660. hr = GetAuthnLevel(pActParams, &AuthnLevel);
  661. if (SUCCEEDED(hr))
  662. {
  663. Status = PickAuthnAndActivate( pActParams, pwszPathForServer,
  664. &hBinding, RPC_C_AUTHN_NONE,
  665. AuthnLevel, ProtseqId, &hr );
  666. if (Status == RPC_S_OK)
  667. {
  668. // asserts that in success cases binding was added to the cache
  669. Assert( hBinding == NULL );
  670. }
  671. }
  672. }
  673. // If the call never worked, return a nice error code.
  674. // except for security errors.
  675. if (Status != RPC_S_OK)
  676. {
  677. if (Status == RPC_S_ACCESS_DENIED)
  678. hr = HRESULT_FROM_WIN32(RPC_S_ACCESS_DENIED);
  679. else
  680. {
  681. hr = HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE);
  682. LogRemoteSideUnavailable( pActParams->ClsContext, _pwszMachine );
  683. }
  684. }
  685. // Clean up resources.
  686. if (hBinding != NULL)
  687. RpcBindingFree( &hBinding );
  688. return hr;
  689. }
  690. //+---------------------------------------------------------------------------
  691. //
  692. // Function: CRemoteMachine::GetAuthnLevel
  693. //
  694. // Synopsis: Figures out what the authentication level for this call ought
  695. // to be.
  696. //
  697. //----------------------------------------------------------------------------
  698. HRESULT CRemoteMachine::GetAuthnLevel(ACTIVATION_PARAMS *pActParams, DWORD *pdwDefaultAuthnLevel)
  699. {
  700. ISpecialSystemProperties *pSpecialSystemProperties;
  701. HRESULT hr = S_OK;
  702. if (pActParams->pAuthInfo)
  703. {
  704. *pdwDefaultAuthnLevel = pActParams->pAuthInfo->dwAuthnLevel;
  705. }
  706. else
  707. {
  708. // Get the default authentication level from the actprops, if we're talking over
  709. // the "new" style interface.
  710. if (!_fUseOldActivationInterface)
  711. {
  712. hr = pActParams->pActPropsIn->QueryInterface(IID_ISpecialSystemProperties,
  713. (void **)&pSpecialSystemProperties);
  714. if (SUCCEEDED(hr))
  715. {
  716. hr = pSpecialSystemProperties->GetDefaultAuthenticationLevel(pdwDefaultAuthnLevel);
  717. pSpecialSystemProperties->Release();
  718. if (SUCCEEDED(hr))
  719. {
  720. if (*pdwDefaultAuthnLevel < RPC_C_AUTHN_LEVEL_CONNECT)
  721. {
  722. // Don't do the activation at less than connect.
  723. *pdwDefaultAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  724. }
  725. }
  726. }
  727. }
  728. else
  729. {
  730. // Always use RPC_C_AUTHN_LEVEL_CONNECT for talking to < Win2k servers.
  731. *pdwDefaultAuthnLevel = RPC_C_AUTHN_LEVEL_CONNECT;
  732. }
  733. }
  734. return hr;
  735. }
  736. //+---------------------------------------------------------------------------
  737. //
  738. // Function: CRemoteMachine::PickAuthnAndActivate
  739. //
  740. // Synopsis: Determine what authentication information to use for the
  741. // activation. The AuthnSvc parameter indicates an
  742. // authentication service that was already tried.
  743. //
  744. //----------------------------------------------------------------------------
  745. RPC_STATUS CRemoteMachine::PickAuthnAndActivate(
  746. IN ACTIVATION_PARAMS * pActParams,
  747. IN WCHAR * pwszPathForServer,
  748. IN handle_t * pBinding,
  749. IN USHORT AuthnSvc,
  750. IN DWORD AuthnLevel,
  751. IN USHORT ProtseqId,
  752. OUT HRESULT * phr )
  753. {
  754. RPC_SECURITY_QOS Qos;
  755. DWORD i;
  756. RPC_STATUS Status;
  757. CMachineBinding *pMachineBinding;
  758. BOOL fTry;
  759. CDualStringArray *pdsa = NULL;
  760. HRESULT hr = S_OK;
  761. // If the client specified security, try exactly the settings requested.
  762. Qos.Version = RPC_C_SECURITY_QOS_VERSION;
  763. pActParams->UnsecureActivation = FALSE;
  764. if (pActParams->pAuthInfo)
  765. {
  766. // Set the requested authentication information.
  767. AuthnSvc = (USHORT) pActParams->pAuthInfo->dwAuthnSvc;
  768. pActParams->AuthnSvc = (USHORT) pActParams->pAuthInfo->dwAuthnSvc;
  769. AuthnLevel = pActParams->pAuthInfo->dwAuthnLevel;
  770. Qos.Capabilities = pActParams->pAuthInfo->dwCapabilities;
  771. Qos.ImpersonationType = pActParams->pAuthInfo->dwImpersonationLevel;
  772. if (pActParams->pAuthInfo->pAuthIdentityData != NULL)
  773. Qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  774. else
  775. Qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  776. Status = RpcBindingSetAuthInfoExW(
  777. *pBinding,
  778. pActParams->pAuthInfo->pwszServerPrincName,
  779. pActParams->pAuthInfo->dwAuthnLevel,
  780. pActParams->pAuthInfo->dwAuthnSvc,
  781. pActParams->pAuthInfo->pAuthIdentityData,
  782. pActParams->pAuthInfo->dwAuthzSvc,
  783. &Qos );
  784. // Try the activation.
  785. if (Status == RPC_S_OK)
  786. {
  787. Status = CallRemoteMachine(*pBinding,
  788. ProtseqId,
  789. pActParams,
  790. pwszPathForServer,
  791. _pwszMachine,
  792. _fUseOldActivationInterface,
  793. phr);
  794. }
  795. }
  796. // Try all authentication services and then try unsecure.
  797. else
  798. {
  799. // Get a reference to the dual string array.
  800. gpRemoteMachineLock->LockShared();
  801. pdsa = _dsa;
  802. if (pdsa) pdsa->AddRef();
  803. gpRemoteMachineLock->UnlockShared();
  804. // Initialize the QOS structure.
  805. Qos.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  806. Qos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  807. Qos.IdentityTracking = RPC_C_QOS_IDENTITY_DYNAMIC;
  808. // Loop over the authentication services.
  809. Status = RPC_S_INTERNAL_ERROR;
  810. for (i = 0; i < s_cRpcssSvc; i++)
  811. {
  812. // Skip the authentication service that was already tried.
  813. if (s_aRpcssSvc[i].wId == AuthnSvc)
  814. continue;
  815. // If there are no security bindings, only try NTLM.
  816. if (pdsa == NULL)
  817. {
  818. fTry = s_aRpcssSvc[i].wId == RPC_C_AUTHN_WINNT;
  819. }
  820. else
  821. {
  822. // If there are security bindings, try the next authentication
  823. // service if both machines use it.
  824. fTry = ValidAuthnSvc( pdsa->DSA(), s_aRpcssSvc[i].wId );
  825. }
  826. if (fTry)
  827. {
  828. BOOL bSetSecurityCallBack = FALSE;
  829. USHORT usAuthSvcFromCallback = RPC_C_AUTHN_GSS_NEGOTIATE;
  830. // Set the security.
  831. Status = RPC_S_OK;
  832. if (s_aRpcssSvc[i].wId == RPC_C_AUTHN_GSS_NEGOTIATE)
  833. {
  834. // Using snego, compute list of compatible authnsvcs:
  835. ASSERT(pdsa);
  836. // if using snego, we need to know what sec pkg is eventually negotiated:
  837. if (gpCRpcSecurityCallbackMgr->RegisterForRpcAuthSvcCallBack(*pBinding))
  838. bSetSecurityCallBack = TRUE;
  839. }
  840. if (Status == RPC_S_OK)
  841. {
  842. Status = RpcBindingSetAuthInfoEx(
  843. *pBinding,
  844. _pwszScmSPN,
  845. AuthnLevel,
  846. s_aRpcssSvc[i].wId,
  847. NULL,
  848. 0,
  849. &Qos );
  850. }
  851. if (Status != RPC_S_OK)
  852. {
  853. if (bSetSecurityCallBack)
  854. gpCRpcSecurityCallbackMgr->GetSecurityContextDetailsAndTurnOffCallback(*pBinding, NULL,
  855. &pActParams->ulMarshaledTargetInfoLength, &pActParams->pMarshaledTargetInfo);
  856. }
  857. // Try the activation.
  858. if (Status == RPC_S_OK)
  859. {
  860. Status = CallRemoteMachine(*pBinding,
  861. ProtseqId,
  862. pActParams,
  863. pwszPathForServer,
  864. _pwszMachine,
  865. _fUseOldActivationInterface,
  866. phr);
  867. if (bSetSecurityCallBack)
  868. {
  869. //
  870. // Only ask for the result of the callback if the call went through; otherwise
  871. // just cancel the registration.
  872. //
  873. if (Status == RPC_S_OK)
  874. {
  875. if (!gpCRpcSecurityCallbackMgr->GetSecurityContextDetailsAndTurnOffCallback(*pBinding,
  876. &usAuthSvcFromCallback, &pActParams->ulMarshaledTargetInfoLength, &pActParams->pMarshaledTargetInfo))
  877. {
  878. // something went wrong. In this case we don't trust what the callback
  879. // told us. Fall back on the original behavior
  880. bSetSecurityCallBack = FALSE;
  881. }
  882. }
  883. else
  884. {
  885. // cancel the callback
  886. gpCRpcSecurityCallbackMgr->GetSecurityContextDetailsAndTurnOffCallback(*pBinding, NULL,
  887. &pActParams->ulMarshaledTargetInfoLength, &pActParams->pMarshaledTargetInfo);
  888. bSetSecurityCallBack = FALSE;
  889. }
  890. }
  891. if (Status == RPC_S_OK ||
  892. Status == RPC_S_SERVER_UNAVAILABLE ||
  893. Status == EPT_S_NOT_REGISTERED)
  894. {
  895. if (bSetSecurityCallBack)
  896. {
  897. // snego call, and we succesfully got a callback telling us
  898. // what the real authentication service was
  899. if (usAuthSvcFromCallback == RPC_C_AUTHN_GSS_KERBEROS)
  900. {
  901. // if we got back kerberos we're going to cache snego anyway; this
  902. // helps NTLM-only clients who can't use kerberos
  903. pActParams->AuthnSvc = AuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
  904. }
  905. else
  906. pActParams->AuthnSvc = AuthnSvc = usAuthSvcFromCallback;
  907. }
  908. else
  909. {
  910. // non-snego, or something went wrong with security callback
  911. // on a snego call
  912. pActParams->AuthnSvc = AuthnSvc = s_aRpcssSvc[i].wId;
  913. }
  914. break;
  915. }
  916. }
  917. }
  918. }
  919. if (pdsa)
  920. {
  921. pdsa->Release();
  922. pdsa = NULL;
  923. }
  924. // If no authentication services worked and the protocol doesn't
  925. // look bad, try no authentication
  926. if (Status != RPC_S_OK &&
  927. Status != RPC_S_SERVER_UNAVAILABLE &&
  928. Status != EPT_S_NOT_REGISTERED)
  929. {
  930. // remember that unsecure activation was done.
  931. // This will be used later when creating the MID
  932. // so we do unsecure pinging also.
  933. pActParams->UnsecureActivation = TRUE;
  934. // Look for a cached unsecure binding handle.
  935. pMachineBinding = LookupBinding( RPC_C_AUTHN_NONE, RPC_C_AUTHN_LEVEL_NONE, NULL );
  936. if ( pMachineBinding )
  937. {
  938. Status = CallRemoteMachine(pMachineBinding->_hBinding,
  939. pMachineBinding->_ProtseqId,
  940. pActParams,
  941. pwszPathForServer,
  942. _pwszMachine,
  943. _fUseOldActivationInterface,
  944. phr);
  945. // Throw away the binding handle received as a parameter so
  946. // it doesn't get cached.
  947. if (Status == RPC_S_OK)
  948. {
  949. RpcBindingFree( pBinding );
  950. *pBinding = NULL;
  951. }
  952. // Throw away the binding if it is unlikely to work again in the
  953. // future.
  954. else
  955. {
  956. RemoveBinding( pMachineBinding );
  957. }
  958. pMachineBinding->Release();
  959. }
  960. // Make the current binding handle unsecure.
  961. else
  962. {
  963. // Set the authentication information.
  964. Status = RpcBindingSetAuthInfoEx(
  965. *pBinding,
  966. NULL,
  967. RPC_C_AUTHN_LEVEL_NONE,
  968. RPC_C_AUTHN_NONE,
  969. NULL,
  970. 0,
  971. NULL );
  972. if (Status == RPC_S_OK)
  973. {
  974. AuthnSvc = RPC_C_AUTHN_NONE;
  975. AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
  976. Status = CallRemoteMachine(
  977. *pBinding,
  978. ProtseqId,
  979. pActParams,
  980. pwszPathForServer,
  981. _pwszMachine,
  982. _fUseOldActivationInterface,
  983. phr );
  984. }
  985. }
  986. }
  987. }
  988. if (Status == RPC_S_OK && *pBinding != NULL)
  989. {
  990. //
  991. // The call completed. We now cache this binding handle.
  992. // Caching is just an optimization so we don't care if this
  993. // insert fails.
  994. //
  995. InsertBinding(
  996. *pBinding,
  997. ProtseqId,
  998. AuthnSvc,
  999. pActParams->ulMarshaledTargetInfoLength,
  1000. pActParams->pMarshaledTargetInfo,
  1001. AuthnLevel,
  1002. pActParams->pAuthInfo);
  1003. *pBinding = NULL;
  1004. }
  1005. // Throw away all bindings if the protocol is unlikely to work
  1006. // again.
  1007. else if (Status == RPC_S_SERVER_UNAVAILABLE ||
  1008. Status == EPT_S_NOT_REGISTERED)
  1009. {
  1010. FlushBindings();
  1011. }
  1012. return Status;
  1013. }
  1014. //+---------------------------------------------------------------------------
  1015. //
  1016. // Function: CRemoteMachine::LookupBinding
  1017. //
  1018. // Synopsis: Scan the binding list for a binding with matching
  1019. // authentication information
  1020. //
  1021. //----------------------------------------------------------------------------
  1022. CMachineBinding *
  1023. CRemoteMachine::LookupBinding(
  1024. IN USHORT AuthnSvc,
  1025. IN DWORD AuthnLevel,
  1026. IN COAUTHINFO * pAuthInfo OPTIONAL
  1027. )
  1028. {
  1029. CMachineBinding * pMachineBinding;
  1030. gpRemoteMachineLock->LockShared();
  1031. for ( pMachineBinding = (CMachineBinding *) _BindingList.First();
  1032. pMachineBinding;
  1033. pMachineBinding = (CMachineBinding *) pMachineBinding->Next() )
  1034. {
  1035. if ( pMachineBinding->Equal( AuthnSvc, AuthnLevel, pAuthInfo ) )
  1036. {
  1037. pMachineBinding->Reference();
  1038. break;
  1039. }
  1040. }
  1041. gpRemoteMachineLock->UnlockShared();
  1042. return pMachineBinding;
  1043. }
  1044. //+---------------------------------------------------------------------------
  1045. //
  1046. // Function: CRemoteMachine::FlushBindings
  1047. //
  1048. // Synopsis: Release all entries under a lock
  1049. //
  1050. //----------------------------------------------------------------------------
  1051. void
  1052. CRemoteMachine::FlushBindings()
  1053. {
  1054. gpRemoteMachineLock->LockExclusive();
  1055. FlushBindingsNoLock();
  1056. gpRemoteMachineLock->UnlockExclusive();
  1057. }
  1058. //+---------------------------------------------------------------------------
  1059. //
  1060. // Function: CRemoteMachine::FlushBindingsNoLock
  1061. //
  1062. // Synopsis: Release all entries without taking a lock first.
  1063. //
  1064. //----------------------------------------------------------------------------
  1065. void CRemoteMachine::FlushBindingsNoLock()
  1066. {
  1067. CMachineBinding * pMachineBinding;
  1068. while ( pMachineBinding = (CMachineBinding *) _BindingList.First() )
  1069. {
  1070. _BindingList.Remove( pMachineBinding );
  1071. pMachineBinding->Release();
  1072. }
  1073. }
  1074. //+---------------------------------------------------------------------------
  1075. //
  1076. // Function: CRemoteMachine::InsertBinding
  1077. //
  1078. // Synopsis: Add the specified binding handle to the cache of binding
  1079. // handles for this machine. Free it if the insertion fails.
  1080. //
  1081. //----------------------------------------------------------------------------
  1082. void
  1083. CRemoteMachine::InsertBinding(
  1084. IN handle_t hBinding,
  1085. IN USHORT ProtseqId,
  1086. IN USHORT AuthnSvc,
  1087. IN unsigned long ulMarshaledTargetInfoLength,
  1088. IN unsigned char* pMarshaledTargetInfo,
  1089. IN DWORD AuthnLevel,
  1090. IN COAUTHINFO * pAuthInfo OPTIONAL)
  1091. {
  1092. CMachineBinding * pMachineBinding;
  1093. CMachineBinding * pExistingBinding;
  1094. COAUTHINFO * pAuthInfoCopy;
  1095. pAuthInfoCopy = 0;
  1096. pMachineBinding = 0;
  1097. if (pAuthInfo && pAuthInfo->pAuthIdentityData)
  1098. {
  1099. // Cannot cache this particular binding.
  1100. // Just free the binding handle.
  1101. RpcBindingFree( &hBinding );
  1102. return;
  1103. }
  1104. if ( ! pAuthInfo || (CopyAuthInfo( pAuthInfo, &pAuthInfoCopy ) == S_OK) )
  1105. {
  1106. pMachineBinding = new CMachineBinding(
  1107. hBinding,
  1108. ProtseqId,
  1109. AuthnSvc,
  1110. AuthnLevel,
  1111. pAuthInfoCopy);
  1112. }
  1113. if ( ! pMachineBinding )
  1114. {
  1115. RpcBindingFree( &hBinding );
  1116. return;
  1117. }
  1118. gpRemoteMachineLock->LockExclusive();
  1119. for ( pExistingBinding = (CMachineBinding *) _BindingList.First();
  1120. pExistingBinding;
  1121. pExistingBinding = (CMachineBinding *) pExistingBinding->Next() )
  1122. {
  1123. if ( pExistingBinding->Equal( AuthnSvc, AuthnLevel, pAuthInfoCopy ) )
  1124. break;
  1125. }
  1126. if ( ! pExistingBinding )
  1127. {
  1128. pMachineBinding->SetMarshaledTargetInfo(ulMarshaledTargetInfoLength, pMarshaledTargetInfo);
  1129. _BindingList.Insert( pMachineBinding );
  1130. }
  1131. gpRemoteMachineLock->UnlockExclusive();
  1132. if ( pExistingBinding )
  1133. {
  1134. // Will delete the new binding we created above.
  1135. pMachineBinding->Release();
  1136. }
  1137. }
  1138. //+---------------------------------------------------------------------------
  1139. //
  1140. // Function: CRemoteMachine::RemoveBinding
  1141. //
  1142. // Synopsis: Remove the specified binding handle from the cache for
  1143. // this machine.
  1144. //
  1145. //----------------------------------------------------------------------------
  1146. void
  1147. CRemoteMachine::RemoveBinding(
  1148. IN CMachineBinding * pMachineBinding
  1149. )
  1150. {
  1151. CMachineBinding * pBinding;
  1152. gpRemoteMachineLock->LockExclusive();
  1153. for ( pBinding = (CMachineBinding *) _BindingList.First();
  1154. pBinding;
  1155. pBinding = (CMachineBinding *) pBinding->Next() )
  1156. {
  1157. if ( pBinding == pMachineBinding )
  1158. {
  1159. _BindingList.Remove( pMachineBinding );
  1160. pMachineBinding->Release();
  1161. break;
  1162. }
  1163. }
  1164. gpRemoteMachineLock->UnlockExclusive();
  1165. }
  1166. //+---------------------------------------------------------------------------
  1167. //
  1168. // Function: CMachineBinding::CMachineBinding
  1169. //
  1170. // Synopsis: Constructor
  1171. //
  1172. //----------------------------------------------------------------------------
  1173. //
  1174. // CMachineBinding
  1175. //
  1176. CMachineBinding::CMachineBinding(
  1177. IN handle_t hBinding,
  1178. IN USHORT ProtseqId,
  1179. IN USHORT AuthnSvc,
  1180. IN DWORD AuthnLevel,
  1181. IN COAUTHINFO * pAuthInfo OPTIONAL
  1182. )
  1183. {
  1184. _hBinding = hBinding;
  1185. _ProtseqId = ProtseqId;
  1186. _AuthnSvc = AuthnSvc;
  1187. _AuthnLevel = AuthnLevel;
  1188. _pAuthInfo = pAuthInfo;
  1189. _ulMarshaledTargetInfoLength = 0;
  1190. _pMarshaledTargetInfo = NULL;
  1191. ASSERT(pAuthInfo == NULL || pAuthInfo->pAuthIdentityData == NULL);
  1192. }
  1193. //+---------------------------------------------------------------------------
  1194. //
  1195. // Function: CMachineBinding::~CMachineBinding
  1196. //
  1197. // Synopsis: Destructor
  1198. //
  1199. //----------------------------------------------------------------------------
  1200. CMachineBinding::~CMachineBinding()
  1201. {
  1202. if ( _hBinding )
  1203. RpcBindingFree( &_hBinding );
  1204. if ( _pAuthInfo )
  1205. {
  1206. PrivMemFree( _pAuthInfo->pwszServerPrincName );
  1207. PrivMemFree( _pAuthInfo );
  1208. }
  1209. if (_ulMarshaledTargetInfoLength)
  1210. {
  1211. MIDL_user_free(_pMarshaledTargetInfo);
  1212. }
  1213. }
  1214. //keeps a copy of the passed in creds
  1215. RPC_STATUS CMachineBinding::SetMarshaledTargetInfo(unsigned long ulMarshaledTargetInfoLength, unsigned char *pMarshaledTargetInfo)
  1216. {
  1217. // I don't expect any existing creds here
  1218. ASSERT( (_ulMarshaledTargetInfoLength == 0) && (_pMarshaledTargetInfo == NULL));
  1219. // but just in case
  1220. if (_pMarshaledTargetInfo)
  1221. {
  1222. MIDL_user_free(_pMarshaledTargetInfo);
  1223. }
  1224. _ulMarshaledTargetInfoLength = 0;
  1225. _pMarshaledTargetInfo = NULL;
  1226. RPC_STATUS status=OR_OK;
  1227. if (ulMarshaledTargetInfoLength)
  1228. {
  1229. _pMarshaledTargetInfo = (unsigned char *) MIDL_user_allocate(ulMarshaledTargetInfoLength * sizeof(char));
  1230. if (_pMarshaledTargetInfo)
  1231. {
  1232. memcpy(_pMarshaledTargetInfo, pMarshaledTargetInfo, ulMarshaledTargetInfoLength);
  1233. _ulMarshaledTargetInfoLength = ulMarshaledTargetInfoLength;
  1234. }
  1235. else
  1236. status = ERROR_NOT_ENOUGH_MEMORY;
  1237. }
  1238. return status;
  1239. }
  1240. // hands out a copy of my creds
  1241. RPC_STATUS CMachineBinding::GetMarshaledTargetInfo(unsigned long *pulMarshaledTargetInfoLength, unsigned char **pucMarshaledTargetInfo)
  1242. {
  1243. RPC_STATUS status=OR_OK;
  1244. *pulMarshaledTargetInfoLength = 0;
  1245. *pucMarshaledTargetInfo = NULL;
  1246. if (_ulMarshaledTargetInfoLength)
  1247. {
  1248. *pucMarshaledTargetInfo = (unsigned char *) MIDL_user_allocate(_ulMarshaledTargetInfoLength * sizeof(char));
  1249. if (*pucMarshaledTargetInfo)
  1250. {
  1251. memcpy(*pucMarshaledTargetInfo, _pMarshaledTargetInfo, _ulMarshaledTargetInfoLength);
  1252. *pulMarshaledTargetInfoLength = _ulMarshaledTargetInfoLength;
  1253. }
  1254. else
  1255. status = ERROR_NOT_ENOUGH_MEMORY;
  1256. }
  1257. return status;
  1258. }
  1259. //+---------------------------------------------------------------------------
  1260. //
  1261. // Function: CMachineBinding::Equal
  1262. //
  1263. // Synopsis: Return TRUE if the specified authentication information
  1264. // matches this binding handle. If the AUTHN_ANY flag is
  1265. // specified, do not check the authentication service but do
  1266. // check the authentication info.
  1267. //
  1268. //----------------------------------------------------------------------------
  1269. BOOL
  1270. CMachineBinding::Equal(
  1271. IN USHORT AuthnSvc,
  1272. IN DWORD AuthnLevel,
  1273. IN COAUTHINFO * pAuthInfo OPTIONAL
  1274. )
  1275. {
  1276. if (AuthnSvc == _AuthnSvc ||
  1277. (AuthnSvc == AUTHN_ANY && _AuthnSvc != RPC_C_AUTHN_NONE))
  1278. {
  1279. if (AuthnLevel > _AuthnLevel)
  1280. {
  1281. // Asking for an authentication level greater than what this
  1282. // machine binding supports.
  1283. return FALSE;
  1284. }
  1285. if (!EqualAuthInfo( pAuthInfo, _pAuthInfo ))
  1286. {
  1287. // Specified COAUTHINFO does not match.
  1288. return FALSE;
  1289. }
  1290. return TRUE;
  1291. }
  1292. return FALSE;
  1293. }
  1294. //+---------------------------------------------------------------------------
  1295. //
  1296. // Function: CallRemoteMachine
  1297. //
  1298. // Synopsis: Marshal/Unmarshal the activation parameters. Call the right
  1299. // remote activation interface.
  1300. //
  1301. //----------------------------------------------------------------------------
  1302. RPC_STATUS
  1303. CallRemoteMachine(
  1304. handle_t hBinding,
  1305. USHORT ProtseqId,
  1306. ACTIVATION_PARAMS * pActParams,
  1307. WCHAR * pwszPathForServer,
  1308. WCHAR * pwszMachine,
  1309. BOOL fUseOldActivationInterface,
  1310. HRESULT * phr
  1311. )
  1312. {
  1313. RPC_STATUS Status=RPC_S_OK;
  1314. if (fUseOldActivationInterface)
  1315. {
  1316. Status = CallOldRemoteActivation(hBinding,
  1317. ProtseqId,
  1318. pActParams,
  1319. pwszPathForServer,
  1320. pwszMachine,
  1321. phr);
  1322. }
  1323. else
  1324. {
  1325. Status = CallNewRemoteActivation(hBinding,
  1326. ProtseqId,
  1327. pActParams,
  1328. pwszPathForServer,
  1329. pwszMachine,
  1330. phr);
  1331. }
  1332. return Status;
  1333. }
  1334. //+---------------------------------------------------------------------------
  1335. //
  1336. // Function: CallNewRemoteActivation
  1337. //
  1338. // Synopsis: Call the COM+ remote activation functions. Returns the RPC
  1339. // status of the call, not the end result. In other words, the
  1340. // call might fail because of some out of memory, or something,
  1341. // but we will still say "success".
  1342. //
  1343. // If everything works out, then when we are finished, the
  1344. // interface information will be in the actprops, and the
  1345. // ProtseqId will be in the ActParams.
  1346. //
  1347. //----------------------------------------------------------------------------
  1348. RPC_STATUS
  1349. CallNewRemoteActivation(
  1350. handle_t hBinding,
  1351. USHORT ProtseqId,
  1352. ACTIVATION_PARAMS * pActParams,
  1353. WCHAR * pwszPathForServer,
  1354. WCHAR * pwszMachine,
  1355. HRESULT * phr)
  1356. {
  1357. RPC_STATUS Status=RPC_S_OK;
  1358. //
  1359. // Setup the ActProps for the new stuff.
  1360. //
  1361. if (pwszPathForServer && (pwszPathForServer != pActParams->pwszPath))
  1362. {
  1363. ASSERT(pActParams->pInstanceInfo != NULL);
  1364. pActParams->pInstanceInfo->SetFile(pwszPathForServer, pActParams->Mode);
  1365. }
  1366. ASSERT(pActParams->pActPropsIn != NULL);
  1367. IScmRequestInfo *pRequestInfo;
  1368. *phr = pActParams->pActPropsIn->QueryInterface(IID_IScmRequestInfo,
  1369. (void**) &pRequestInfo);
  1370. if (*phr != S_OK)
  1371. return Status;
  1372. REMOTE_REQUEST_SCM_INFO *pRequest;
  1373. pRequest = (REMOTE_REQUEST_SCM_INFO *)
  1374. MIDL_user_allocate(sizeof(REMOTE_REQUEST_SCM_INFO));
  1375. if (pRequest == NULL)
  1376. {
  1377. pRequestInfo->Release();
  1378. *phr = E_OUTOFMEMORY;
  1379. return Status;
  1380. }
  1381. pRequest->ClientImpLevel = RPC_C_IMP_LEVEL_IDENTIFY;
  1382. pRequest->cRequestedProtseqs = cMyProtseqs;
  1383. pRequest->pRequestedProtseqs = (unsigned short*)
  1384. MIDL_user_allocate(sizeof(short)*pRequest->cRequestedProtseqs);
  1385. if (pRequest->pRequestedProtseqs==NULL)
  1386. {
  1387. *phr = E_OUTOFMEMORY;
  1388. MIDL_user_free(pRequest);
  1389. pRequestInfo->Release();
  1390. return RPC_S_OK;
  1391. }
  1392. memcpy(pRequest->pRequestedProtseqs, aMyProtseqs, sizeof(short)*cMyProtseqs);
  1393. pRequestInfo->SetRemoteRequestInfo(pRequest);
  1394. pRequestInfo->Release();
  1395. MInterfacePointer *pIFDIn, *pIFDOut=NULL;
  1396. *phr = ActPropsMarshalHelper(pActParams->pActPropsIn,
  1397. IID_IActivationPropertiesIn,
  1398. MSHCTX_DIFFERENTMACHINE,
  1399. MSHLFLAGS_NORMAL,
  1400. &pIFDIn);
  1401. if (*phr != S_OK)
  1402. {
  1403. return RPC_S_OK;
  1404. }
  1405. RpcTryExcept
  1406. {
  1407. if (pActParams->MsgType == GETCLASSOBJECT)
  1408. {
  1409. *phr = RemoteGetClassObject(hBinding,
  1410. pActParams->ORPCthis,
  1411. pActParams->ORPCthat,
  1412. pIFDIn,
  1413. &pIFDOut);
  1414. }
  1415. else
  1416. {
  1417. *phr = RemoteCreateInstance(hBinding,
  1418. pActParams->ORPCthis,
  1419. pActParams->ORPCthat,
  1420. NULL,
  1421. pIFDIn,
  1422. &pIFDOut);
  1423. }
  1424. }
  1425. RpcExcept(TRUE)
  1426. {
  1427. Status = RpcExceptionCode();
  1428. }
  1429. RpcEndExcept;
  1430. // Don't need the marshalled [in] interface anymore.
  1431. MIDL_user_free(pIFDIn);
  1432. //
  1433. // If the status we got back was not RPC_S_OK, just return it.
  1434. // Set *phr, too, but depending on the error, the caller might
  1435. // not care.
  1436. //
  1437. if (Status != RPC_S_OK)
  1438. {
  1439. *phr = HRESULT_FROM_WIN32(Status);
  1440. return Status;
  1441. }
  1442. if (*phr != S_OK)
  1443. {
  1444. // a-sergiv (Sergei O. Ivanov), 6-17-99
  1445. // Fix for com+ 14808/nt 355212
  1446. LogRemoteSideFailure( &pActParams->Clsid, pActParams->ClsContext, pwszMachine, pwszPathForServer, *phr);
  1447. return RPC_S_OK;
  1448. }
  1449. // AWFUL HACK ALERT: This is too hacky even for the SCM
  1450. ActivationStream ActStream((InterfaceData*)(((BYTE*)pIFDOut)+48));
  1451. pActParams->pActPropsOut = new ActivationPropertiesOut(FALSE /* fBrokenRefCount */);
  1452. if (pActParams->pActPropsOut==NULL)
  1453. {
  1454. *phr = E_OUTOFMEMORY;
  1455. return RPC_S_OK;
  1456. }
  1457. IScmReplyInfo *pReplyInfo;
  1458. *phr = pActParams->pActPropsOut->UnmarshalInterface(&ActStream,
  1459. IID_IScmReplyInfo,
  1460. (LPVOID*)&pReplyInfo);
  1461. if (*phr != S_OK)
  1462. {
  1463. pReplyInfo->Release();
  1464. pActParams->pActPropsOut->Release();
  1465. pActParams->pActPropsOut=NULL;
  1466. MIDL_user_free(pIFDOut);
  1467. return RPC_S_OK;
  1468. }
  1469. // If in a remote LB router, just return
  1470. if (pActParams->RemoteActivation)
  1471. {
  1472. pReplyInfo->Release();
  1473. MIDL_user_free(pIFDOut);
  1474. return RPC_S_OK;
  1475. }
  1476. REMOTE_REPLY_SCM_INFO *pReply;
  1477. pReplyInfo->GetRemoteReplyInfo(&pReply);
  1478. ASSERT(pReply!=NULL);
  1479. *pActParams->pOxidServer = pReply->Oxid;
  1480. //We will not have protocol bindings for custom marshalled objrefs
  1481. if ((pReply->pdsaOxidBindings) && (pReply->pdsaOxidBindings->wNumEntries))
  1482. {
  1483. ASSERT(pActParams->pOxidInfo != NULL);
  1484. pActParams->pOxidInfo->psa = (DUALSTRINGARRAY *)
  1485. MIDL_user_allocate(pReply->pdsaOxidBindings->wNumEntries
  1486. * sizeof(WCHAR) +
  1487. sizeof(DUALSTRINGARRAY));
  1488. if (pActParams->pOxidInfo->psa == NULL)
  1489. {
  1490. pReplyInfo->Release();
  1491. pActParams->pActPropsOut->Release();
  1492. pActParams->pActPropsOut=NULL;
  1493. *phr = E_OUTOFMEMORY;
  1494. return RPC_S_OK;
  1495. }
  1496. dsaCopy(pActParams->pOxidInfo->psa, pReply->pdsaOxidBindings);
  1497. }
  1498. else
  1499. pActParams->pOxidInfo->psa = NULL;
  1500. pActParams->ProtseqId = ProtseqId;
  1501. pActParams->pOxidInfo->ipidRemUnknown = pReply->ipidRemUnknown;
  1502. pActParams->pOxidInfo->dwAuthnHint = pReply->authnHint;
  1503. pActParams->pOxidInfo->version = pReply->serverVersion;
  1504. pActParams->pIIDs = 0;
  1505. pActParams->pResults = 0;
  1506. pActParams->ppIFD = 0;
  1507. MIDL_user_free(pIFDOut);
  1508. pReplyInfo->Release();
  1509. return RPC_S_OK;
  1510. }
  1511. //+---------------------------------------------------------------------------
  1512. //
  1513. // Function: CallOldRemoteActivation
  1514. //
  1515. // Synopsis: Call the down-level "RemoteActivation" function, for downrev
  1516. // servers. Returns the RPC status of the call, not the end
  1517. // result. In other words, the call might fail because of some
  1518. // out of memory, or something, but we will still say "success".
  1519. //
  1520. // If everything works out, then when we are finished, the
  1521. // interface information will be in the actprops, and the
  1522. // ProtseqId will be in the ActParams.
  1523. //
  1524. //----------------------------------------------------------------------------
  1525. RPC_STATUS
  1526. CallOldRemoteActivation(
  1527. handle_t hBinding,
  1528. USHORT ProtseqId,
  1529. ACTIVATION_PARAMS * pActParams,
  1530. WCHAR * pwszPathForServer,
  1531. WCHAR * pwszMachine,
  1532. HRESULT * phr)
  1533. {
  1534. RPC_STATUS Status;
  1535. // Use Old Down-level interface
  1536. //
  1537. // all remote activations on this interface have to be made with
  1538. // minor version 1, since remote downlevel (version 5.1) servers
  1539. // refuse any other version.
  1540. pActParams->ORPCthis->version.MinorVersion = COM_MINOR_VERSION_1;
  1541. pActParams->ORPCthis->flags = ORPCF_NULL;
  1542. pActParams->ppIFD = (MInterfacePointer **)
  1543. MIDL_user_allocate(sizeof(MInterfacePointer *) *
  1544. pActParams->Interfaces);
  1545. pActParams->pResults = (HRESULT*) MIDL_user_allocate(sizeof(HRESULT) *
  1546. pActParams->Interfaces);
  1547. if ((pActParams->ppIFD == NULL) || (pActParams->pResults == NULL))
  1548. {
  1549. MIDL_user_free(pActParams->ppIFD);
  1550. MIDL_user_free(pActParams->pResults);
  1551. *phr = E_OUTOFMEMORY;
  1552. return RPC_S_OK;
  1553. }
  1554. for (DWORD i=0; i<pActParams->Interfaces;i++)
  1555. {
  1556. pActParams->ppIFD[i] = NULL;
  1557. pActParams->pResults[i] = E_FAIL;
  1558. }
  1559. Status = RemoteActivation(
  1560. hBinding,
  1561. pActParams->ORPCthis,
  1562. pActParams->ORPCthat,
  1563. &pActParams->Clsid,
  1564. pwszPathForServer,
  1565. pActParams->pIFDStorage,
  1566. RPC_C_IMP_LEVEL_IDENTIFY,
  1567. pActParams->Mode,
  1568. pActParams->Interfaces,
  1569. pActParams->pIIDs,
  1570. cMyProtseqs,
  1571. aMyProtseqs,
  1572. pActParams->pOxidServer,
  1573. &pActParams->pOxidInfo->psa,
  1574. &pActParams->pOxidInfo->ipidRemUnknown,
  1575. &pActParams->pOxidInfo->dwAuthnHint,
  1576. &pActParams->pOxidInfo->version,
  1577. phr,
  1578. pActParams->ppIFD,
  1579. pActParams->pResults );
  1580. //
  1581. // Note that this will only give us a bad status if there is a
  1582. // communication failure.
  1583. //
  1584. if ( Status != RPC_S_OK )
  1585. return Status;
  1586. // Tweak the COMVERSION to be the lower of the two.
  1587. Status = NegotiateDCOMVersion( &pActParams->pOxidInfo->version );
  1588. if ( Status != RPC_S_OK )
  1589. return Status;
  1590. if ( (RPC_S_OK == Status) && FAILED(*phr) )
  1591. LogRemoteSideFailure( &pActParams->Clsid, pActParams->ClsContext, pwszMachine, pwszPathForServer, *phr );
  1592. if ((pActParams->MsgType == GETCLASSOBJECT) && (*phr == S_OK))
  1593. {
  1594. *pActParams->pResults = *phr;
  1595. }
  1596. //
  1597. // If the activation fails we return success for the communication
  1598. // status, but the overall operation has failed and the error will
  1599. // be propogated back to the client.
  1600. //
  1601. if ( FAILED(*phr) )
  1602. return RPC_S_OK;
  1603. //
  1604. // Anything that fails from here on out is our fault, not the server's.
  1605. // So it is now safe to remember the ProtseqId.
  1606. //
  1607. pActParams->ProtseqId = ProtseqId;
  1608. ASSERT(pActParams->pActPropsIn != NULL);
  1609. *phr =
  1610. pActParams->pActPropsIn->GetReturnActivationProperties((ActivationPropertiesOut **)
  1611. &pActParams->pActPropsOut);
  1612. if ( FAILED(*phr) )
  1613. return RPC_S_OK;
  1614. *phr = pActParams->pActPropsOut->SetMarshalledResults(pActParams->Interfaces,
  1615. pActParams->pIIDs,
  1616. pActParams->pResults,
  1617. pActParams->ppIFD);
  1618. //pActParams->pIIDs belongs to ActPropsIn
  1619. MIDL_user_free(pActParams->pResults);
  1620. for (i=0;i<pActParams->Interfaces ; i++)
  1621. MIDL_user_free(pActParams->ppIFD[i]);
  1622. MIDL_user_free(pActParams->ppIFD);
  1623. pActParams->pResults = NULL;
  1624. pActParams->ppIFD = NULL;
  1625. return RPC_S_OK;
  1626. }
  1627. //+---------------------------------------------------------------------------
  1628. //
  1629. // Function: CreateRemoteBinding
  1630. //
  1631. // Synopsis: Create a binding handle for the specified machine and protseq.
  1632. //
  1633. //----------------------------------------------------------------------------
  1634. RPC_STATUS
  1635. CreateRemoteBinding(
  1636. IN WCHAR * pwszMachine,
  1637. IN int ProtseqIndex,
  1638. OUT handle_t * phBinding
  1639. )
  1640. {
  1641. WCHAR * pwszStringBinding;
  1642. RPC_STATUS Status;
  1643. *phBinding = 0;
  1644. Status = RpcStringBindingCompose(
  1645. NULL,
  1646. gaProtseqInfo[aMyProtseqs[ProtseqIndex]].pwstrProtseq,
  1647. pwszMachine,
  1648. gaProtseqInfo[aMyProtseqs[ProtseqIndex]].pwstrEndpoint,
  1649. NULL,
  1650. &pwszStringBinding );
  1651. if ( Status != RPC_S_OK )
  1652. return Status;
  1653. Status = RpcBindingFromStringBinding( pwszStringBinding, phBinding );
  1654. RpcStringFree( &pwszStringBinding );
  1655. return Status;
  1656. }
  1657. //+---------------------------------------------------------------------------
  1658. //
  1659. // Function: CopyAuthIdentity
  1660. //
  1661. // Synopsis: Copy an auth identity structure and all its strings.
  1662. //
  1663. //----------------------------------------------------------------------------
  1664. HRESULT
  1665. CopyAuthIdentity(
  1666. IN COAUTHIDENTITY * pAuthIdentSrc,
  1667. IN COAUTHIDENTITY ** ppAuthIdentDest
  1668. )
  1669. {
  1670. HRESULT hr = E_OUTOFMEMORY;
  1671. ULONG ulCharLen = 1;
  1672. COAUTHIDENTITY *pAuthIdentTemp = NULL;
  1673. *ppAuthIdentDest = NULL;
  1674. // Guard against both being set, although presumably this would have
  1675. // caused grief before we got to this point.
  1676. if ((pAuthIdentSrc->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE) &&
  1677. (pAuthIdentSrc->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI))
  1678. {
  1679. ASSERT(0 && "Both string type flags were set!");
  1680. hr = E_UNEXPECTED;
  1681. goto Cleanup;
  1682. }
  1683. if (pAuthIdentSrc->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
  1684. {
  1685. ulCharLen = sizeof(WCHAR);
  1686. }
  1687. else if (pAuthIdentSrc->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
  1688. {
  1689. ulCharLen = sizeof(CHAR);
  1690. }
  1691. else
  1692. {
  1693. // The user didn't specify either string bit? How did we get here?
  1694. ASSERT(0 && "String type flag was not set!");
  1695. hr = E_UNEXPECTED;
  1696. goto Cleanup;
  1697. }
  1698. pAuthIdentTemp = (COAUTHIDENTITY*) ActMemAlloc(sizeof(COAUTHIDENTITY));
  1699. if (!pAuthIdentTemp)
  1700. goto Cleanup;
  1701. CopyMemory(pAuthIdentTemp, pAuthIdentSrc, sizeof(COAUTHIDENTITY));
  1702. // Strings need to be allocated individually and copied
  1703. pAuthIdentTemp->User = pAuthIdentTemp->Domain = pAuthIdentTemp->Password = NULL;
  1704. if (pAuthIdentSrc->User)
  1705. {
  1706. pAuthIdentTemp->User = (USHORT *)ActMemAlloc((pAuthIdentTemp->UserLength+1) * ulCharLen);
  1707. if (!pAuthIdentTemp->User)
  1708. goto Cleanup;
  1709. CopyMemory(pAuthIdentTemp->User, pAuthIdentSrc->User, (pAuthIdentTemp->UserLength+1) * ulCharLen);
  1710. }
  1711. if (pAuthIdentSrc->Domain)
  1712. {
  1713. pAuthIdentTemp->Domain = (USHORT *)ActMemAlloc((pAuthIdentTemp->DomainLength+1) * ulCharLen);
  1714. if (!pAuthIdentTemp->Domain)
  1715. goto Cleanup;
  1716. CopyMemory(pAuthIdentTemp->Domain, pAuthIdentSrc->Domain, (pAuthIdentTemp->DomainLength+1) * ulCharLen);
  1717. }
  1718. if (pAuthIdentSrc->Password)
  1719. {
  1720. pAuthIdentTemp->Password = (USHORT *)ActMemAlloc((pAuthIdentTemp->PasswordLength+1) * ulCharLen);
  1721. if (!pAuthIdentTemp->Password)
  1722. goto Cleanup;
  1723. CopyMemory(pAuthIdentTemp->Password, pAuthIdentSrc->Password, (pAuthIdentTemp->PasswordLength+1) * ulCharLen);
  1724. }
  1725. hr = S_OK;
  1726. Cleanup:
  1727. if (SUCCEEDED(hr))
  1728. {
  1729. *ppAuthIdentDest = pAuthIdentTemp;
  1730. }
  1731. else
  1732. {
  1733. if (pAuthIdentTemp)
  1734. {
  1735. SecurityInfo::freeCOAUTHIDENTITY(pAuthIdentTemp);
  1736. }
  1737. }
  1738. return hr;
  1739. }
  1740. //+---------------------------------------------------------------------------
  1741. //
  1742. // Function: CopyAuthInfo
  1743. //
  1744. // Synopsis: Copy an auth info structure and all its sub structures.
  1745. //
  1746. //----------------------------------------------------------------------------
  1747. HRESULT
  1748. CopyAuthInfo(
  1749. IN COAUTHINFO * pAuthInfoSrc,
  1750. IN COAUTHINFO ** ppAuthInfoDest
  1751. )
  1752. {
  1753. HRESULT hr = E_OUTOFMEMORY;
  1754. COAUTHINFO *pAuthInfoTemp = NULL;
  1755. *ppAuthInfoDest = NULL;
  1756. if (pAuthInfoSrc == NULL)
  1757. {
  1758. return S_OK;
  1759. }
  1760. pAuthInfoTemp = (COAUTHINFO*)ActMemAlloc(sizeof(COAUTHINFO));
  1761. if (!pAuthInfoTemp)
  1762. goto Cleanup;
  1763. CopyMemory(pAuthInfoTemp, pAuthInfoSrc, sizeof(COAUTHINFO));
  1764. // We need to allocate these fields and make a copy
  1765. pAuthInfoTemp->pwszServerPrincName = NULL;
  1766. pAuthInfoTemp->pAuthIdentityData = NULL;
  1767. // only alloc space for pwszServerPrincName if its non-null
  1768. if (pAuthInfoSrc->pwszServerPrincName)
  1769. {
  1770. pAuthInfoTemp->pwszServerPrincName =
  1771. (LPWSTR) ActMemAlloc((lstrlenW(pAuthInfoSrc->pwszServerPrincName) + 1) * sizeof(WCHAR));
  1772. if (!pAuthInfoTemp->pwszServerPrincName)
  1773. goto Cleanup;
  1774. lstrcpyW(pAuthInfoTemp->pwszServerPrincName, pAuthInfoSrc->pwszServerPrincName);
  1775. }
  1776. // copy the AuthIdentity if its non-null
  1777. if (pAuthInfoSrc->pAuthIdentityData)
  1778. {
  1779. hr = CopyAuthIdentity(pAuthInfoSrc->pAuthIdentityData, &pAuthInfoTemp->pAuthIdentityData);
  1780. if (FAILED(hr))
  1781. goto Cleanup;
  1782. }
  1783. hr = S_OK;
  1784. Cleanup:
  1785. if (SUCCEEDED(hr))
  1786. {
  1787. *ppAuthInfoDest = pAuthInfoTemp;
  1788. }
  1789. else if (pAuthInfoTemp)
  1790. {
  1791. SecurityInfo::freeCOAUTHINFO(pAuthInfoTemp);
  1792. }
  1793. return hr;
  1794. }
  1795. //+---------------------------------------------------------------------------
  1796. //
  1797. // Function: EqualAuthInfo
  1798. //
  1799. // Synopsis: Compare two auth info structures and their sub structures.
  1800. //
  1801. //----------------------------------------------------------------------------
  1802. BOOL
  1803. EqualAuthInfo(
  1804. COAUTHINFO* pAuthInfo,
  1805. COAUTHINFO* pAuthInfoOther)
  1806. {
  1807. if ( pAuthInfo && pAuthInfoOther )
  1808. {
  1809. if ( (pAuthInfo->dwAuthnSvc != pAuthInfoOther->dwAuthnSvc) ||
  1810. (pAuthInfo->dwAuthzSvc != pAuthInfoOther->dwAuthzSvc) ||
  1811. (pAuthInfo->dwAuthnLevel != pAuthInfoOther->dwAuthnLevel) ||
  1812. (pAuthInfo->dwImpersonationLevel != pAuthInfoOther->dwImpersonationLevel) ||
  1813. (pAuthInfo->dwCapabilities != pAuthInfoOther->dwCapabilities) )
  1814. {
  1815. return FALSE;
  1816. }
  1817. // only compare pwszServerPrincName's if they're both specified
  1818. if (pAuthInfo->pwszServerPrincName && pAuthInfoOther->pwszServerPrincName)
  1819. {
  1820. if ( lstrcmpW(pAuthInfo->pwszServerPrincName,
  1821. pAuthInfoOther->pwszServerPrincName) != 0 )
  1822. {
  1823. return FALSE;
  1824. }
  1825. }
  1826. else
  1827. {
  1828. // if one was NULL, both should be NULL for equality
  1829. if (pAuthInfo->pwszServerPrincName != pAuthInfoOther->pwszServerPrincName)
  1830. {
  1831. return FALSE;
  1832. }
  1833. }
  1834. // we never cache authid, so one of them must be NULL
  1835. ASSERT(!(pAuthInfo->pAuthIdentityData && pAuthInfoOther->pAuthIdentityData));
  1836. if (pAuthInfo->pAuthIdentityData || pAuthInfoOther->pAuthIdentityData)
  1837. {
  1838. return FALSE;
  1839. }
  1840. }
  1841. else
  1842. {
  1843. if ( pAuthInfo != pAuthInfoOther )
  1844. {
  1845. return FALSE;
  1846. }
  1847. }
  1848. return TRUE;
  1849. }