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.

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