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.

1593 lines
35 KiB

  1. /*++
  2. (c) 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. fsaftclt.cpp
  5. Abstract:
  6. This class represents a user who the filter has detected accessing a file with placeholder information.
  7. Author:
  8. Chuck Bardeen [cbardeen] 12-Feb-1997
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. extern "C" {
  13. #include <ntseapi.h>
  14. #include <wchar.h>
  15. #include <lmaccess.h>
  16. #include <lmserver.h>
  17. #include <lmshare.h>
  18. #include <lmapibuf.h>
  19. #include <lmerr.h>
  20. // #define MAC_SUPPORT // NOTE: You must define MAC_SUPPORT in fsafltr.cpp to enable all the code
  21. #ifdef MAC_SUPPORT
  22. #include <macfile.h>
  23. #endif
  24. }
  25. #define WSB_TRACE_IS WSB_TRACE_BIT_FSA
  26. #include "wsb.h"
  27. #include "fsa.h"
  28. #include "fsaftclt.h"
  29. static USHORT iCountFtclt = 0; // Count of existing objects
  30. //
  31. // We need to dynamically load the DLL for MAC support because it is not there if
  32. // the MAC service is not installed.
  33. //
  34. #ifdef MAC_SUPPORT
  35. HANDLE FsaDllSfm = 0;
  36. BOOL FsaMacSupportInstalled = FALSE;
  37. extern "C" {
  38. DWORD (*pAfpAdminConnect) (LPWSTR lpwsServerName, PAFP_SERVER_HANDLE phAfpServer);
  39. VOID (*pAfpAdminDisconnect) (AFP_SERVER_HANDLE hAfpServer);
  40. VOID (*pAfpAdminBufferFree) (PVOID pBuffer);
  41. DWORD (*pAfpAdminSessionEnum) (AFP_SERVER_HANDLE hAfpServer, LPBYTE *lpbBuffer,
  42. DWORD dwPrefMaxLen, LPDWORD lpdwEntriesRead, LPDWORD lpdwTotalEntries,
  43. LPDWORD lpdwResumeHandle);
  44. }
  45. #endif
  46. DWORD FsaIdentifyThread(void *pNotifyInterface);
  47. DWORD FsaIdentifyThread(
  48. void* pVoid
  49. )
  50. /*++
  51. Entry point of the thread that performs identify operation with remote clients.
  52. --*/
  53. {
  54. HRESULT hr;
  55. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  56. hr = ((CFsaFilterClient*) pVoid)->IdentifyThread();
  57. CoUninitialize();
  58. return(hr);
  59. }
  60. static
  61. HRESULT
  62. GetNotifyClientInterface(
  63. IN OLECHAR * machineName,
  64. OUT IFsaRecallNotifyClient ** ppClient
  65. )
  66. {
  67. HRESULT hr = S_OK;
  68. try {
  69. //
  70. // Make sure parameters OK and OUTs initially cleared
  71. //
  72. WsbAffirmPointer ( ppClient );
  73. *ppClient = 0;
  74. //
  75. // If connecting local, things work better to use NULL
  76. // for the computer name
  77. //
  78. if ( machineName ) {
  79. CWsbStringPtr localMachine;
  80. WsbAffirmHr( WsbGetComputerName( localMachine ) );
  81. if( _wcsicmp( localMachine, machineName ) == 0 ) {
  82. machineName = 0;
  83. }
  84. }
  85. //
  86. // Set server info
  87. //
  88. COSERVERINFO csi;
  89. COAUTHINFO cai;
  90. memset ( &csi, 0, sizeof ( csi ) );
  91. memset ( &cai, 0, sizeof ( cai ) );
  92. // Set machine name
  93. csi.pwszName = machineName;
  94. // Create a proxy with security settings of no authentication (note that RsNotify is running with this security)
  95. cai.dwAuthnSvc = RPC_C_AUTHN_WINNT;
  96. cai.dwAuthzSvc = RPC_C_AUTHZ_DEFAULT;
  97. cai.pwszServerPrincName = NULL;
  98. cai.dwImpersonationLevel = RPC_C_IMP_LEVEL_IMPERSONATE;
  99. cai.pAuthIdentityData = NULL;
  100. cai.dwCapabilities = EOAC_NONE;
  101. cai.dwAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
  102. csi.pAuthInfo = &cai;
  103. //
  104. // We want IFsaRecallNotifyClient back
  105. //
  106. MULTI_QI mqi;
  107. memset ( &mqi, 0, sizeof ( mqi ) );
  108. mqi.pIID = &IID_IFsaRecallNotifyClient;
  109. //
  110. // Make the connection...
  111. //
  112. WsbAffirmHr ( CoCreateInstanceEx (
  113. CLSID_CFsaRecallNotifyClient, 0,
  114. CLSCTX_NO_FAILURE_LOG | ( machineName ? CLSCTX_REMOTE_SERVER : CLSCTX_LOCAL_SERVER ),
  115. &csi, 1, &mqi ) );
  116. WsbAffirmHr ( mqi.hr );
  117. //
  118. // We need to make sure we clean up correctly if any interface
  119. // post-processing fails, so assign over to a smart pointer for
  120. // the time being
  121. //
  122. CComPtr<IFsaRecallNotifyClient> pClientTemp = (IFsaRecallNotifyClient*)mqi.pItf;
  123. mqi.pItf->Release ( );
  124. //
  125. // Finally, we need to set the security on the procy to allow the
  126. // anonymous connection. Values should be the same as above (COAUTHINFO)
  127. // We need to make sure this is a remote machine first. Otherwise, we
  128. // get an error of E_INVALIDARG.
  129. //
  130. if( machineName ) {
  131. CComPtr<IClientSecurity> pSecurity;
  132. WsbAffirmHr( pClientTemp->QueryInterface( IID_IClientSecurity, (void**)&pSecurity ) );
  133. WsbAffirmHr( pSecurity->SetBlanket ( pClientTemp, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IDENTIFY, 0, 0 ) );
  134. }
  135. //
  136. // Finally, assign over and AddRef the return.
  137. //
  138. *ppClient = pClientTemp;
  139. (*ppClient)->AddRef ( );
  140. } WsbCatch ( hr );
  141. return ( hr );
  142. }
  143. HRESULT
  144. CFsaFilterClient::CheckRecallLimit(
  145. IN DWORD minRecallInterval,
  146. IN DWORD maxRecalls,
  147. IN BOOLEAN exemptAdmin
  148. )
  149. /*++
  150. Implements:
  151. IWsbCollectable::CheckRecallLimit().
  152. --*/
  153. {
  154. HRESULT hr = S_OK;
  155. FILETIME now, last;
  156. LARGE_INTEGER tNow, tLast;
  157. ULONG rCount;
  158. WsbTraceIn(OLESTR("CFsaFilterClient::CheckRecallLimit"), OLESTR(""));
  159. try {
  160. //
  161. // Now check for runaway recall limits if the user is not
  162. // an administrator
  163. //
  164. if ((!m_isAdmin) || (!exemptAdmin)) {
  165. //
  166. // See if the time since the end of the last recall is
  167. // less than m_minRecallInterval (in seconds) and if so,
  168. // increment the count.
  169. // If not, then reset the count (if we were not
  170. // already triggered).
  171. // If the count is equal to the max then set the trigger.
  172. //
  173. WsbTrace(OLESTR("CHsmFilter::IoctlThread: Not an administrator or admin is not exempt.\n"));
  174. GetSystemTimeAsFileTime(&now);
  175. tNow.LowPart = now.dwLowDateTime;
  176. tNow.HighPart = now.dwHighDateTime;
  177. GetLastRecallTime(&last);
  178. tLast.LowPart = last.dwLowDateTime;
  179. tLast.HighPart = last.dwHighDateTime;
  180. //
  181. // Get the time (in 100 nano-second units)
  182. // from the end of the last recall until now.
  183. //
  184. tNow.QuadPart -= tLast.QuadPart;
  185. //
  186. // Convert to seconds and check against the interval time
  187. //
  188. tNow.QuadPart /= (LONGLONG) 10000000;
  189. if (tNow.QuadPart < (LONGLONG) minRecallInterval) {
  190. //
  191. // This one counts - increment the count
  192. // and check for a trigger.
  193. //
  194. GetRecallCount(&rCount);
  195. rCount++;
  196. SetRecallCount(rCount);
  197. WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Recall count bumped to %ls.\n"),
  198. WsbLongAsString(rCount));
  199. if (rCount >= maxRecalls) {
  200. //
  201. // Hit the runaway recall limit. Set the
  202. // limit flag.
  203. //
  204. WsbTrace(OLESTR("CHsmFilter::IoctlThread: Hit the runaway recall limit!!!.\n"));
  205. SetHitRecallLimit(TRUE);
  206. }
  207. } else {
  208. //
  209. // Reset the count if they are not already triggered.
  210. // If they are triggered then reset the trigger and
  211. // limit if it has been a respectable time.
  212. // TBD - What is a respectable time??
  213. //
  214. if (HitRecallLimit() != S_FALSE) {
  215. if (tNow.QuadPart > (LONGLONG) minRecallInterval * 100) {
  216. //
  217. // A respectable time has passed - reset the trigger and count.
  218. //
  219. WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Resetting recall limit trigger and count.\n"));
  220. SetHitRecallLimit(FALSE);
  221. SetRecallCount(0);
  222. m_loggedLimitError = FALSE;
  223. }
  224. } else {
  225. //
  226. // This one did not count and they were not already triggered.
  227. // Reset the count to zero.
  228. //
  229. WsbTrace(OLESTR("CHsmFilterClient::CheckRecallLimit: Resetting recall count.\n"));
  230. SetRecallCount(0);
  231. }
  232. }
  233. //
  234. // Fail if the limit is hit.
  235. //
  236. WsbAffirm(HitRecallLimit() == S_FALSE, FSA_E_HIT_RECALL_LIMIT);
  237. }
  238. } WsbCatch(hr);
  239. // NOTE - IF RUNAWAY RECALL BEHAVIOR CHANGES TO TRUNCATE ON CLOSE, CHANGE
  240. // FSA_MESSAGE_HIT_RECALL_LIMIT_ACCESSDENIED TO FSA_MESSAGE_HIT_RECALL_LIMIT_TRUNCATEONCLOSE.
  241. if ( (hr == FSA_E_HIT_RECALL_LIMIT) && (!m_loggedLimitError)) {
  242. WsbLogEvent(FSA_MESSAGE_HIT_RECALL_LIMIT_ACCESSDENIED, 0, NULL, (WCHAR *) m_userName, NULL);
  243. m_loggedLimitError = TRUE;
  244. }
  245. WsbTraceOut(OLESTR("CHsmFilterClient::CheckRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  246. return(hr);
  247. }
  248. HRESULT
  249. CFsaFilterClient::CompareBy(
  250. FSA_FILTERCLIENT_COMPARE by
  251. )
  252. /*++
  253. Implements:
  254. IFsaFilterClient::CompareBy().
  255. --*/
  256. {
  257. HRESULT hr = S_OK;
  258. m_compareBy = by;
  259. m_isDirty = TRUE;
  260. return(hr);
  261. }
  262. HRESULT
  263. CFsaFilterClient::CompareTo(
  264. IN IUnknown* pUnknown,
  265. OUT SHORT* pResult
  266. )
  267. /*++
  268. Implements:
  269. IWsbCollectable::CompareTo().
  270. --*/
  271. {
  272. HRESULT hr = S_OK;
  273. CComPtr<IFsaFilterClient> pClient;
  274. WsbTraceIn(OLESTR("CFsaFilterClient::CompareTo"), OLESTR(""));
  275. try {
  276. // Did they give us a valid item to compare to?
  277. WsbAssert(0 != pUnknown, E_POINTER);
  278. // We need the IWsbBool interface to get the value of the object.
  279. WsbAffirmHr(pUnknown->QueryInterface(IID_IFsaFilterClient, (void**) &pClient));
  280. // Compare the rules.
  281. hr = CompareToIClient(pClient, pResult);
  282. } WsbCatch(hr);
  283. WsbTraceOut(OLESTR("CHsmFilterClient::CompareTo"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  284. return(hr);
  285. }
  286. HRESULT
  287. CFsaFilterClient::CompareToAuthenticationId(
  288. IN LONG luidHigh,
  289. IN ULONG luidLow,
  290. OUT SHORT* pResult
  291. )
  292. /*++
  293. Implements:
  294. IFsaFilterClient::CompareToAuthenticationId().
  295. --*/
  296. {
  297. HRESULT hr = S_OK;
  298. SHORT aResult;
  299. WsbTraceIn(OLESTR("CFsaFilterClient::CompareToAuthenticationId"), OLESTR(""));
  300. try {
  301. if (m_luidHigh > luidHigh) {
  302. aResult = 1;
  303. } else if (m_luidHigh < luidHigh) {
  304. aResult = -1;
  305. } else if (m_luidLow > luidLow) {
  306. aResult = 1;
  307. } else if (m_luidLow < luidLow) {
  308. aResult = -1;
  309. } else {
  310. aResult = 0;
  311. }
  312. if (0 != aResult) {
  313. hr = S_FALSE;
  314. }
  315. if (0 != pResult) {
  316. *pResult = aResult;
  317. }
  318. } WsbCatch(hr);
  319. WsbTraceOut(OLESTR("CFsaFilterClient::CompareToAuthenticationId"), OLESTR("hr = <%ls>, result = <%d>"), WsbHrAsString(hr), aResult);
  320. return(hr);
  321. }
  322. HRESULT
  323. CFsaFilterClient::CompareToIClient(
  324. IN IFsaFilterClient* pClient,
  325. OUT SHORT* pResult
  326. )
  327. /*++
  328. Implements:
  329. IFsaFilterClient::CompareToIClient().
  330. --*/
  331. {
  332. HRESULT hr = S_OK;
  333. CWsbStringPtr name;
  334. LONG luidHigh;
  335. ULONG luidLow;
  336. WsbTraceIn(OLESTR("CFsaFilterClient::CompareToIClient"), OLESTR(""));
  337. try {
  338. // Did they give us a valid item to compare to?
  339. WsbAssert(0 != pClient, E_POINTER);
  340. switch (m_compareBy) {
  341. case FSA_FILTERCLIENT_COMPARE_ID:
  342. WsbAffirmHr(pClient->GetAuthenticationId(&luidHigh, &luidLow));
  343. hr = CompareToAuthenticationId(luidHigh, luidLow, pResult);
  344. break;
  345. case FSA_FILTERCLIENT_COMPARE_MACHINE:
  346. WsbAffirmHr(pClient->GetMachineName(&name, 0));
  347. hr = CompareToMachineName(name, pResult);
  348. break;
  349. default:
  350. WsbAssert(FALSE, E_UNEXPECTED);
  351. }
  352. } WsbCatch(hr);
  353. WsbTraceOut(OLESTR("CFsaFilterClient::CompareToIClient"), OLESTR("hr = <%ls>, result = <%ls>"), WsbHrAsString(hr), WsbPtrToShortAsString(pResult));
  354. return(hr);
  355. }
  356. HRESULT
  357. CFsaFilterClient::CompareToMachineName(
  358. IN OLECHAR* name,
  359. OUT SHORT* pResult
  360. )
  361. /*++
  362. Implements:
  363. IFsaFilterClient::CompareToMachineName().
  364. --*/
  365. {
  366. HRESULT hr = S_OK;
  367. SHORT aResult;
  368. WsbTraceIn(OLESTR("CFsaFilterClient::CompareToMachineName"), OLESTR(""));
  369. try {
  370. aResult = (SHORT)wcscmp(name, m_machineName); // TBD - Case sensitive or not?
  371. if (0 != aResult) {
  372. hr = S_FALSE;
  373. }
  374. if (0 != pResult) {
  375. *pResult = aResult;
  376. }
  377. } WsbCatch(hr);
  378. WsbTraceOut(OLESTR("CFsaFilterClient::CompareToMachineName"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  379. return(hr);
  380. }
  381. HRESULT
  382. CFsaFilterClient::FinalConstruct(
  383. void
  384. )
  385. /*++
  386. Implements:
  387. CComObjectRoot::FinalConstruct().
  388. --*/
  389. {
  390. HRESULT hr = S_OK;
  391. WsbTraceIn(OLESTR("CFsaFilterClient::FinalConstruct"),OLESTR(""));
  392. try {
  393. WsbAffirmHr(CWsbCollectable::FinalConstruct());
  394. m_compareBy = FSA_FILTERCLIENT_COMPARE_ID;
  395. m_luidHigh = 0;
  396. m_luidLow = 0;
  397. m_hasRecallDisabled = FALSE;
  398. m_hitRecallLimit = FALSE;
  399. m_lastRecallTime.dwLowDateTime = 0;
  400. m_lastRecallTime.dwHighDateTime = 0;
  401. m_identified = FALSE;
  402. m_tokenSource = L"";
  403. m_msgCounter = 1;
  404. m_identifyThread = NULL;
  405. m_isAdmin = FALSE;
  406. m_loggedLimitError = FALSE;
  407. } WsbCatch(hr);
  408. iCountFtclt++;
  409. WsbTraceOut(OLESTR("CFsaFilterClient::FinalConstruct"),OLESTR("Count is <%d>"), iCountFtclt);
  410. return(hr);
  411. }
  412. void
  413. CFsaFilterClient::FinalRelease(
  414. void
  415. )
  416. /*++
  417. Implements:
  418. CComObjectRoot::FinalRelease().
  419. --*/
  420. {
  421. WsbTraceIn(OLESTR("CFsaFilterClient::FinalRelease"),OLESTR(""));
  422. CWsbCollectable::FinalRelease();
  423. iCountFtclt--;
  424. WsbTraceOut(OLESTR("CFsaFilterClient::FinalRelease"),OLESTR("Count is <%d>"), iCountFtclt);
  425. }
  426. HRESULT
  427. CFsaFilterClient::GetClassID(
  428. OUT CLSID* pClsid
  429. )
  430. /*++
  431. Implements:
  432. IPersist::GetClassID().
  433. --*/
  434. {
  435. HRESULT hr = S_OK;
  436. WsbTraceIn(OLESTR("CFsaFilterClient::GetClassID"), OLESTR(""));
  437. try {
  438. WsbAssert(0 != pClsid, E_POINTER);
  439. *pClsid = CLSID_CFsaFilterClientNTFS;
  440. } WsbCatch(hr);
  441. WsbTraceOut(OLESTR("CFsaFilterClient::GetClassID"), OLESTR("hr = <%ls>, CLSID = <%ls>"), WsbHrAsString(hr), WsbGuidAsString(*pClsid));
  442. return(hr);
  443. }
  444. HRESULT
  445. CFsaFilterClient::GetAuthenticationId(
  446. OUT LONG* pLuidHigh,
  447. OUT ULONG* pLuidLow
  448. )
  449. /*++
  450. Implements:
  451. IFsaFilterClient::GetAuthenticationId().
  452. --*/
  453. {
  454. HRESULT hr = S_OK;
  455. try {
  456. WsbAssert(0 != pLuidHigh, E_POINTER);
  457. WsbAssert(0 != pLuidLow, E_POINTER);
  458. *pLuidHigh = m_luidHigh;
  459. *pLuidLow = m_luidLow;
  460. } WsbCatch(hr);
  461. return(hr);
  462. }
  463. HRESULT
  464. CFsaFilterClient::GetDomainName(
  465. OUT OLECHAR** pName,
  466. IN ULONG bufferSize
  467. )
  468. /*++
  469. Implements:
  470. IFsaFilterClient::GetDomainName().
  471. --*/
  472. {
  473. HRESULT hr = S_OK;
  474. try {
  475. WsbAssert(0 != pName, E_POINTER);
  476. WsbAffirmHr(m_domainName.CopyTo(pName, bufferSize));
  477. } WsbCatch(hr);
  478. return(hr);
  479. }
  480. HRESULT
  481. CFsaFilterClient::GetIsAdmin(
  482. OUT BOOLEAN *pIsAdmin
  483. )
  484. /*++
  485. Implements:
  486. IPersist::GetIsAdmin().
  487. --*/
  488. {
  489. HRESULT hr = S_OK;
  490. WsbTraceIn(OLESTR("CFsaFilterClient::GetIsAdmin"), OLESTR(""));
  491. try {
  492. WsbAssert(0 != pIsAdmin, E_POINTER);
  493. *pIsAdmin = m_isAdmin;
  494. } WsbCatch(hr);
  495. WsbTraceOut(OLESTR("CFsaFilterClient::GetIsAdmin"), OLESTR("hr = <%ls>, isAdmin = <%u>"), WsbHrAsString(hr), *pIsAdmin);
  496. return(hr);
  497. }
  498. HRESULT
  499. CFsaFilterClient::GetLastRecallTime(
  500. OUT FILETIME* pTime
  501. )
  502. /*++
  503. Implements:
  504. IFsaFilterClient::GetLastRecallTime().
  505. --*/
  506. {
  507. HRESULT hr = S_OK;
  508. try {
  509. WsbAssert(0 != pTime, E_POINTER);
  510. *pTime = m_lastRecallTime;
  511. } WsbCatch(hr);
  512. return(hr);
  513. }
  514. HRESULT
  515. CFsaFilterClient::GetMachineName(
  516. OUT OLECHAR** pName,
  517. IN ULONG bufferSize
  518. )
  519. /*++
  520. Implements:
  521. IFsaFilterClient::GetMachineName().
  522. --*/
  523. {
  524. HRESULT hr = S_OK;
  525. try {
  526. WsbAssert(0 != pName, E_POINTER);
  527. WsbAffirmHr(m_machineName.CopyTo(pName, bufferSize));
  528. } WsbCatch(hr);
  529. return(hr);
  530. }
  531. HRESULT
  532. CFsaFilterClient::GetRecallCount(
  533. OUT ULONG* pCount
  534. )
  535. /*++
  536. Implements:
  537. IFsaFilterClient::GetRecallCount().
  538. --*/
  539. {
  540. HRESULT hr = S_OK;
  541. try {
  542. WsbAssert(0 != pCount, E_POINTER);
  543. *pCount = m_recallCount;
  544. } WsbCatch(hr);
  545. return(hr);
  546. }
  547. HRESULT
  548. CFsaFilterClient::GetUserName(
  549. OUT OLECHAR** pName,
  550. IN ULONG bufferSize
  551. )
  552. /*++
  553. Implements:
  554. IFsaFilterClient::GetUserName().
  555. --*/
  556. {
  557. HRESULT hr = S_OK;
  558. try {
  559. WsbAssert(0 != pName, E_POINTER);
  560. WsbAffirmHr(m_userName.CopyTo(pName, bufferSize));
  561. } WsbCatch(hr);
  562. return(hr);
  563. }
  564. HRESULT
  565. CFsaFilterClient::GetSizeMax(
  566. OUT ULARGE_INTEGER* pSize
  567. )
  568. /*++
  569. Implements:
  570. IPersistStream::GetSizeMax().
  571. --*/
  572. {
  573. HRESULT hr = S_OK;
  574. WsbTraceIn(OLESTR("CFsaFilterClient::GetSizeMax"), OLESTR(""));
  575. try {
  576. WsbAssert(0 != pSize, E_POINTER);
  577. pSize->QuadPart = 0;
  578. // WE don't need to persist these.
  579. hr = E_NOTIMPL;
  580. } WsbCatch(hr);
  581. WsbTraceOut(OLESTR("CFsaFilterClient::GetSizeMax"), OLESTR("hr = <%ls>, Size = <%ls>"), WsbHrAsString(hr), WsbPtrToUliAsString(pSize));
  582. return(hr);
  583. }
  584. HRESULT
  585. CFsaFilterClient::HasRecallDisabled(
  586. void
  587. )
  588. /*++
  589. Implements:
  590. IFsaFilterClient::HasRecallDisabled().
  591. --*/
  592. {
  593. HRESULT hr = S_OK;
  594. WsbTraceIn(OLESTR("CFsaFilterClient::HasRecallDisabled"), OLESTR(""));
  595. if (!m_hasRecallDisabled) {
  596. hr = S_FALSE;
  597. }
  598. WsbTraceOut(OLESTR("CHsmFilterClient::HasRecallDisabled"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  599. return(hr);
  600. }
  601. HRESULT
  602. CFsaFilterClient::HitRecallLimit(
  603. void
  604. )
  605. /*++
  606. Implements:
  607. IFsaFilterClient::HitRecallLimit().
  608. --*/
  609. {
  610. HRESULT hr = S_OK;
  611. WsbTraceIn(OLESTR("CFsaFilterClient::HitRecallLimit"), OLESTR(""));
  612. if (!m_hitRecallLimit) {
  613. hr = S_FALSE;
  614. }
  615. WsbTraceOut(OLESTR("CHsmFilterClient::HitRecallLimit"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  616. return(hr);
  617. }
  618. HRESULT
  619. CFsaFilterClient::IdentifyThread(
  620. void
  621. )
  622. /*++
  623. Implements:
  624. CFsaFilterClient::IdentifyThread().
  625. --*/
  626. {
  627. #define WSB_BUFF_SIZE 1024
  628. HRESULT hr = S_OK;
  629. BOOL done, guestUser, noUser;
  630. DWORD res, totalEnt, numEnt;
  631. UCHAR *buff = NULL;
  632. NET_API_STATUS status;
  633. SESSION_INFO_1 *sess;
  634. CWsbStringPtr pipePath;
  635. ULONG holdOff = 0;
  636. #ifdef MAC_SUPPORT
  637. LPBYTE macBuff = NULL;
  638. PAFP_SESSION_INFO macInfo;
  639. AFP_SERVER_HANDLE macHandle = 0;
  640. DWORD macResume = 0;
  641. DWORD macTotalEntries, macTotalRead;
  642. DWORD result;
  643. #endif
  644. WsbTraceIn(OLESTR("CFsaFilterClient::IdentifyThread"), OLESTR(""));
  645. try {
  646. WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread Flag: %x Client ID: %x:%x Source: %ls\n"),
  647. m_identified, m_luidHigh, m_luidLow, (WCHAR *) m_tokenSource);
  648. //
  649. // If already identified then we bail out here.
  650. //
  651. WsbAffirm(m_identified == FALSE, S_OK);
  652. done = FALSE;
  653. res = 0;
  654. noUser = FALSE;
  655. if (_wcsicmp(m_userName, L"GUEST") == 0) {
  656. /* It is the guest user - find all sessions and
  657. send to ones marked guest */
  658. guestUser = TRUE;
  659. } else {
  660. guestUser = FALSE;
  661. if (wcslen(m_userName) == 0) {
  662. noUser = TRUE;
  663. }
  664. }
  665. CComPtr<IFsaRecallNotifyClient> pRecallClient;
  666. WsbGetComputerName( pipePath );
  667. WsbAffirmHr(pipePath.Prepend("\\\\"));
  668. WsbAffirmHr(pipePath.Append("\\pipe\\"));
  669. WsbAffirmHr(pipePath.Append(WSB_PIPE_NAME));
  670. while ( done == FALSE ) {
  671. if ( (guestUser == FALSE) && (noUser == FALSE) ) {
  672. // If NetSessionEnum fails, try calling again for all users
  673. status = NetSessionEnum(NULL, NULL, m_userName, 1, &buff,
  674. WSB_BUFF_SIZE, &numEnt, &totalEnt, &res);
  675. if (status != 0) {
  676. status = NetSessionEnum(NULL, NULL, NULL, 1, &buff,
  677. WSB_BUFF_SIZE, &numEnt, &totalEnt, &res);
  678. }
  679. } else {
  680. status = NetSessionEnum( NULL, NULL, NULL, 1, &buff,
  681. WSB_BUFF_SIZE, &numEnt, &totalEnt, &res );
  682. }
  683. if ((status == NERR_Success) || (status == ERROR_MORE_DATA)) {
  684. WsbTrace(OLESTR("CHsmFilterClient::IdentifyThread: NetSessionEnum output: Total entries=%ls , Read entries=%ls \n"),
  685. WsbLongAsString(totalEnt), WsbLongAsString(numEnt));
  686. if (status != ERROR_MORE_DATA) {
  687. done = TRUE;
  688. }
  689. sess = (SESSION_INFO_1 *) buff;
  690. while ( numEnt != 0 ) {
  691. //
  692. // If the request was made from the user GUEST then
  693. // we enumerate all sessions and send the
  694. // identification request to all the machines with
  695. // sessions marked as GUEST. This is because the
  696. // session may have some other user name but the
  697. // request could still have GUEST access.
  698. //
  699. if (((guestUser) && (sess->sesi1_user_flags & SESS_GUEST)) ||
  700. (!guestUser)) {
  701. //
  702. // Send the identify request message
  703. //
  704. WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - Sending identify request to %ls (local machine = %ls)\n"),
  705. sess->sesi1_cname, (WCHAR *) pipePath);
  706. hr = GetNotifyClientInterface ( sess->sesi1_cname, &pRecallClient );
  707. if ( SUCCEEDED ( hr ) ) {
  708. hr = pRecallClient->IdentifyWithServer( pipePath );
  709. if (hr != S_OK) {
  710. WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - error Identifing (%ls)\n"),
  711. WsbHrAsString(hr));
  712. }
  713. } else {
  714. WsbTrace(OLESTR("CFsaFilterClient::IdentifyThread - error getting notify client interface hr = %ls (%x)\n"),
  715. WsbHrAsString( hr ), hr);
  716. }
  717. hr = S_OK;
  718. pRecallClient.Release ( );
  719. }
  720. sess++;
  721. numEnt--;
  722. }
  723. NetApiBufferFree(buff);
  724. buff = NULL;
  725. } else {
  726. done = TRUE;
  727. }
  728. }
  729. #ifdef MAC_SUPPORT
  730. //
  731. // Done with LAN manager scan, now do a MAC scan.
  732. //
  733. if ( (FsaMacSupportInstalled) && ((pAfpAdminConnect)(NULL, &macHandle) == NO_ERROR) ) {
  734. //
  735. // We have connected to the MAC service - do a session enumeration
  736. //
  737. macResume = 0;
  738. done = FALSE;
  739. while (done == FALSE) {
  740. result = (pAfpAdminSessionEnum)(macHandle, &macBuff, -1,
  741. &macTotalRead, &macTotalEntries, &macResume);
  742. if ((result == NO_ERROR) || (result == ERROR_MORE_DATA)) {
  743. //
  744. // Read some entries - send the message to each one
  745. //
  746. if (macTotalRead == macTotalEntries) {
  747. done = TRUE;
  748. }
  749. macInfo = (PAFP_SESSION_INFO) macBuff;
  750. while ( macTotalRead != 0 ) {
  751. //
  752. // Send to each matching user
  753. //
  754. if ( ( NULL != macInfo->afpsess_ws_name ) &&
  755. ( _wcsicmp(m_userName, macInfo->afpsess_username ) == 0 ) ) {
  756. WsbTrace(OLESTR("CHsmFilterClient::IdentifyThread: Send Identify to MAC %ls.\n"),
  757. macInfo->afpsess_ws_name);
  758. //
  759. // Send the identify request message
  760. //
  761. hr = GetNotifyClientInterface ( sess->sesi1_cname, &pRecallClient );
  762. if ( SUCCEEDED ( hr ) ) {
  763. pRecallClient->IdentifyWithServer ( pipePath );
  764. }
  765. hr = S_OK;
  766. pRecallClient.Release ( );
  767. }
  768. macInfo++;
  769. macTotalRead--;
  770. }
  771. (pAfpAdminBufferFree)(macBuff);
  772. macBuff = NULL;
  773. } else {
  774. done = TRUE;
  775. }
  776. (pAfpAdminDisconnect)(macHandle);
  777. macHandle = 0;
  778. }
  779. }
  780. #endif
  781. } WsbCatch(hr);
  782. if (buff != NULL) {
  783. NetApiBufferFree(buff);
  784. }
  785. #ifdef MAC_SUPPORT
  786. if (FsaMacSupportInstalled) {
  787. if (macBuff != NULL) {
  788. (pAfpAdminBufferFree)(macBuff);
  789. }
  790. if (macHandle != 0) {
  791. (pAfpAdminDisconnect)(macHandle);
  792. }
  793. }
  794. #endif
  795. CloseHandle(m_identifyThread);
  796. m_identifyThread = NULL;
  797. WsbTraceOut(OLESTR("CFsaFilterClient::IdentifyThread"), OLESTR("hr = %ls"), WsbHrAsString(hr));
  798. return(hr);
  799. }
  800. HRESULT
  801. CFsaFilterClient::Load(
  802. IN IStream* pStream
  803. )
  804. /*++
  805. Implements:
  806. IPersistStream::Load().
  807. --*/
  808. {
  809. HRESULT hr = S_OK;
  810. WsbTraceIn(OLESTR("CFsaFilterClient::Load"), OLESTR(""));
  811. try {
  812. WsbAssert(0 != pStream, E_POINTER);
  813. // No persistence.
  814. hr = E_NOTIMPL;
  815. } WsbCatch(hr);
  816. WsbTraceOut(OLESTR("CFsaFilterClient::Load"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  817. return(hr);
  818. }
  819. HRESULT
  820. CFsaFilterClient::Save(
  821. IN IStream* pStream,
  822. IN BOOL clearDirty
  823. )
  824. /*++
  825. Implements:
  826. IPersistStream::Save().
  827. --*/
  828. {
  829. HRESULT hr = S_OK;
  830. CComPtr<IPersistStream> pPersistStream;
  831. WsbTraceIn(OLESTR("CFsaFilterClient::Save"), OLESTR("clearDirty = <%ls>"), WsbBoolAsString(clearDirty));
  832. try {
  833. WsbAssert(0 != pStream, E_POINTER);
  834. // No persistence.
  835. hr = E_NOTIMPL;
  836. // If we got it saved and we were asked to clear the dirty bit, then
  837. // do so now.
  838. if (clearDirty) {
  839. m_isDirty = FALSE;
  840. }
  841. } WsbCatch(hr);
  842. WsbTraceOut(OLESTR("CFsaFilterClient::Save"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  843. return(hr);
  844. }
  845. HRESULT
  846. CFsaFilterClient::SendRecallInfo(
  847. IFsaFilterRecall *pRecall,
  848. BOOL starting,
  849. HRESULT rHr
  850. )
  851. /*++
  852. Implements:
  853. CFsaFilterClient::SendRecallInfo
  854. --*/
  855. {
  856. HRESULT hr = E_FAIL;
  857. if( ! m_identified && ( m_identifyThread != NULL ) ) {
  858. //
  859. // Wait for up to 10 seconds for identify thread to complete if
  860. // Client not yet identified
  861. //
  862. WaitForMultipleObjects( 1, &m_identifyThread, FALSE, 10000 );
  863. }
  864. //
  865. // Let the client know that the recall is starting or is finished
  866. //
  867. if ( m_identified ) {
  868. try {
  869. WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - Client (%ls) is being notified of recall status (starting = %u hr = %x).\n"),
  870. (WCHAR *) m_machineName, starting, rHr);
  871. //
  872. // Create intermediate server object which will be the client's
  873. // connection back to the service. This object acts as a middle
  874. // man to overcome the admin-only access into the FSA service.
  875. //
  876. CComPtr<IFsaRecallNotifyServer> pRecallServer;
  877. WsbAffirmHr(CoCreateInstance(CLSID_CFsaRecallNotifyServer, 0, CLSCTX_NO_FAILURE_LOG | CLSCTX_ALL, IID_IFsaRecallNotifyServer, (void**)&pRecallServer));
  878. WsbAffirmHr(pRecallServer->Init(pRecall));
  879. CComPtr<IFsaRecallNotifyClient> pRecallClient;
  880. hr = GetNotifyClientInterface ( m_machineName, &pRecallClient );
  881. if ( SUCCEEDED( hr ) ) {
  882. if (starting) {
  883. hr = pRecallClient->OnRecallStarted ( pRecallServer );
  884. } else {
  885. hr = pRecallClient->OnRecallFinished ( pRecallServer, rHr );
  886. }
  887. if (hr != S_OK) {
  888. WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - Got the interface but failed in OnRecall... (%ls)\n"),
  889. WsbHrAsString(hr));
  890. }
  891. } else {
  892. WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - error getting notify client interface hr = %ls (%x)\n"),
  893. WsbHrAsString( hr ), hr);
  894. }
  895. } WsbCatchAndDo(hr,
  896. WsbTrace(OLESTR("CFsaFilterClient::SendRecallInfo - hr = %ls\n"),
  897. WsbHrAsString(hr));
  898. );
  899. }
  900. return(hr);
  901. }
  902. HRESULT
  903. CFsaFilterClient::SetAuthenticationId(
  904. IN LONG luidHigh,
  905. IN ULONG luidLow
  906. )
  907. /*++
  908. Implements:
  909. IFsaFilterClient::SetAuthenticationId().
  910. --*/
  911. {
  912. m_luidHigh = luidHigh;
  913. m_luidLow = luidLow;
  914. return(S_OK);
  915. }
  916. HRESULT
  917. CFsaFilterClient::SetDomainName(
  918. IN OLECHAR* name
  919. )
  920. /*++
  921. Implements:
  922. IFsaFilterClient::SetDomainName().
  923. --*/
  924. {
  925. HRESULT hr = S_OK;
  926. try {
  927. m_domainName = name;
  928. WsbAssert(m_domainName != 0, E_UNEXPECTED);
  929. } WsbCatch(hr);
  930. return(hr);
  931. }
  932. HRESULT
  933. CFsaFilterClient::SetIsAdmin(
  934. IN BOOLEAN isAdmin
  935. )
  936. /*++
  937. Implements:
  938. IFsaFilterClient::SetIsAdmin().
  939. --*/
  940. {
  941. m_isAdmin = isAdmin;
  942. return(S_OK);
  943. }
  944. HRESULT
  945. CFsaFilterClient::SetLastRecallTime(
  946. IN FILETIME time
  947. )
  948. /*++
  949. Implements:
  950. IFsaFilterClient::SetLastRecallTime().
  951. --*/
  952. {
  953. m_lastRecallTime = time;
  954. return(S_OK);
  955. }
  956. HRESULT
  957. CFsaFilterClient::SetMachineName(
  958. IN OLECHAR* name
  959. )
  960. /*++
  961. Implements:
  962. IFsaFilterClient::SetMachineName().
  963. --*/
  964. {
  965. HRESULT hr = S_OK;
  966. try {
  967. WsbAssert(name != 0, E_UNEXPECTED);
  968. m_machineName = name;
  969. m_identified = TRUE;
  970. WsbTrace(OLESTR("CFsaFilterClient::SetMachineName Flag: %x Client ID: %x:%x Source: %ls == %ls\n"),
  971. m_identified, m_luidLow, m_luidHigh, (WCHAR *) m_tokenSource, (WCHAR *) m_machineName);
  972. } WsbCatch(hr);
  973. return(hr);
  974. }
  975. HRESULT
  976. CFsaFilterClient::SetRecallCount(
  977. IN ULONG count
  978. )
  979. /*++
  980. Implements:
  981. IFsaFilterClient::SetRecallCount().
  982. --*/
  983. {
  984. m_recallCount = count;
  985. return(S_OK);
  986. }
  987. HRESULT
  988. CFsaFilterClient::SetUserName(
  989. IN OLECHAR* name
  990. )
  991. /*++
  992. Implements:
  993. IFsaFilterClient::SetUserName().
  994. --*/
  995. {
  996. HRESULT hr = S_OK;
  997. try {
  998. m_userName = _wcsupr(name);
  999. WsbAssert(m_userName != 0, E_UNEXPECTED);
  1000. } WsbCatch(hr);
  1001. return(hr);
  1002. }
  1003. HRESULT
  1004. CFsaFilterClient::SetHasRecallDisabled(
  1005. IN BOOL hasBeen
  1006. )
  1007. /*++
  1008. Implements:
  1009. IFsaFilterClient::SetHasRecallDisabled().
  1010. --*/
  1011. {
  1012. m_hasRecallDisabled = hasBeen;
  1013. return(S_OK);
  1014. }
  1015. HRESULT
  1016. CFsaFilterClient::SetHitRecallLimit(
  1017. IN BOOL hasBeen
  1018. )
  1019. /*++
  1020. Implements:
  1021. IFsaFilterClient::SetHitRecallLimit().
  1022. --*/
  1023. {
  1024. m_hitRecallLimit = hasBeen;
  1025. return(S_OK);
  1026. }
  1027. HRESULT
  1028. CFsaFilterClient::SetTokenSource(
  1029. IN CHAR *source
  1030. )
  1031. /*++
  1032. Implements:
  1033. IFsaFilterClient::SetTokenSource()
  1034. --*/
  1035. {
  1036. OLECHAR tSource[TOKEN_SOURCE_LENGTH + 1];
  1037. mbstowcs((WCHAR *) tSource, source, TOKEN_SOURCE_LENGTH);
  1038. m_tokenSource = tSource;
  1039. return(S_OK);
  1040. }
  1041. HRESULT
  1042. CFsaFilterClient::StartIdentify(
  1043. void
  1044. )
  1045. /*++
  1046. Implements:
  1047. CFsaFilterClient::StartIdentify().
  1048. --*/
  1049. {
  1050. #define WSB_BUFF_SIZE 1024
  1051. HRESULT hr = S_OK;
  1052. DWORD tid;
  1053. WsbTraceIn(OLESTR("CFsaFilterClient::StartIdentify"), OLESTR(""));
  1054. try {
  1055. WsbTrace(OLESTR("CFsaFilterClient::StartIdentify Flag: %x Client ID: %x:%x Source: %ls\n"),
  1056. m_identified, m_luidHigh, m_luidLow, (WCHAR *) m_tokenSource);
  1057. //
  1058. // If already identified then we bail out here.
  1059. //
  1060. WsbAffirm(m_identified == FALSE, S_OK);
  1061. //
  1062. // If the request is from User32 then it is local
  1063. //
  1064. if (_wcsicmp(m_tokenSource, L"User32") == 0) {
  1065. //
  1066. // Identified as the local machine.
  1067. // Set the name and bail out with S_OK
  1068. //
  1069. WsbGetComputerName( m_machineName );
  1070. m_identified = TRUE;
  1071. WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Identified as %ls.\n"),
  1072. (WCHAR *) m_machineName);
  1073. WsbThrow( S_OK );
  1074. } else {
  1075. //
  1076. // Start the identification thread
  1077. //
  1078. if (NULL == m_identifyThread) {
  1079. WsbTrace(OLESTR("CHsmFilterClient::StartIdentify: Starting ID thread.\n"));
  1080. WsbAffirm((m_identifyThread = CreateThread(0, 0, FsaIdentifyThread, (void*) this, 0, &tid)) != 0, HRESULT_FROM_WIN32(GetLastError()));
  1081. if (m_identifyThread == NULL) {
  1082. WsbAssertHr(E_FAIL); // TBD What error to return here??
  1083. }
  1084. }
  1085. }
  1086. } WsbCatch(hr);
  1087. WsbTraceOut(OLESTR("CFsaFilterClient::StartIdentify"), OLESTR("hr = %ls"), WsbHrAsString(hr));
  1088. return(hr);
  1089. }
  1090. HRESULT
  1091. CFsaFilterClient::Test(
  1092. USHORT* passed,
  1093. USHORT* failed
  1094. )
  1095. /*++
  1096. Implements:
  1097. IWsbTestable::Test().
  1098. --*/
  1099. {
  1100. HRESULT hr = S_OK;
  1101. try {
  1102. WsbAssert(0 != passed, E_POINTER);
  1103. WsbAssert(0 != failed, E_POINTER);
  1104. *passed = 0;
  1105. *failed = 0;
  1106. } WsbCatch(hr);
  1107. return(hr);
  1108. }