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.

907 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. apiinit.c
  5. Abstract:
  6. Initialization for Cluster API component (CLUSAPI) of the
  7. NT Cluster Service
  8. Author:
  9. John Vert (jvert) 7-Feb-1996
  10. Revision History:
  11. --*/
  12. #include "apip.h"
  13. #include "aclapi.h"
  14. #include "stdio.h"
  15. #include <psapi.h>
  16. extern LPWSTR g_pszServicesPath;
  17. extern DWORD g_dwServicesPid;
  18. PSECURITY_DESCRIPTOR g_SD = NULL;
  19. CRITICAL_SECTION g_SDCritSect;
  20. API_INIT_STATE ApiState=ApiStateUninitialized;
  21. const DWORD NO_USER_SID = 0;
  22. const DWORD USER_SID_GRANTED = 1;
  23. const DWORD USER_SID_DENIED = 2;
  24. //forward declarations
  25. DWORD
  26. ApipGetLocalCallerInfo(
  27. IN handle_t hIDL,
  28. IN OUT OPTIONAL LPDWORD pdwCheckPid,
  29. IN OPTIONAL LPCWSTR pszModuleName,
  30. OUT BOOL *pbLocal,
  31. OUT OPTIONAL BOOL *pbMatchedPid,
  32. OUT OPTIONAL BOOL *pbMatchedModule,
  33. OUT OPTIONAL BOOL *pbLocalSystemAccount
  34. );
  35. RPC_STATUS
  36. ApipConnectCallback(
  37. IN RPC_IF_ID * Interface,
  38. IN void * Context
  39. )
  40. /*++
  41. Routine Description:
  42. RPC callback for authenticating connecting clients of CLUSAPI
  43. Arguments:
  44. Interface - Supplies the UUID and version of the interface.
  45. Context - Supplies a server binding handle representing the client
  46. Return Value:
  47. RPC_S_OK if the user is granted permission.
  48. RPC_S_ACCESS_DENIED if the user is denied permission.
  49. Win32 error code otherwise
  50. --*/
  51. {
  52. PSECURITY_DESCRIPTOR pdefaultSD = NULL;
  53. DWORD Status;
  54. HANDLE ClientToken = NULL;
  55. PRIVILEGE_SET psPrivileges;
  56. DWORD PrivSize = sizeof(psPrivileges);
  57. DWORD GrantedAccess;
  58. DWORD AccessStatus;
  59. DWORD dwMask = CLUSAPI_ALL_ACCESS;
  60. GENERIC_MAPPING gmMap;
  61. DWORD dwStatus = 0;
  62. BOOL bReturn = FALSE;
  63. BOOL bACRtn = FALSE;
  64. DWORD dwUserPermStatus;
  65. RPC_STATUS RpcStatus;
  66. BOOL bRevertToSelfRequired = FALSE;
  67. BOOL bLocal, bMatchedPid, bMatchedModule, bLocalSystemAccount;
  68. DWORD dwRetries = 0;
  69. BOOL bGotCritSect = FALSE;
  70. //check if services is calling the cluster service for
  71. //services calls the interface only for eventlog propagation
  72. //if so, avoid the security checks
  73. // Get the process id
  74. Status = ApipGetLocalCallerInfo(Context,
  75. &g_dwServicesPid,
  76. g_dwServicesPid ? NULL : g_pszServicesPath, //perform the module name match the first time
  77. &bLocal,
  78. &bMatchedPid,
  79. &bMatchedModule,
  80. g_dwServicesPid ? &bLocalSystemAccount : NULL);//perform the local system account check if it is the first time
  81. if (Status != ERROR_SUCCESS)
  82. {
  83. ClRtlLogPrint(LOG_NOISE, "[API] ApipGetLocalCallerInfo failed with %1!u!.\n",
  84. Status);
  85. Status = RPC_S_ACCESS_DENIED;
  86. goto FnExit;
  87. }
  88. if (Status == ERROR_SUCCESS)
  89. {
  90. //if the caller is local and if it matches the pid or if it matches
  91. //the module and is in local system account, allow access
  92. if ((bLocal) &&
  93. (bMatchedPid || (bMatchedModule && bLocalSystemAccount)))
  94. {
  95. Status = RPC_S_OK;
  96. goto FnExit;
  97. }
  98. }
  99. //
  100. // The authentication we do here is to retrieve the Security value
  101. // from the cluster registry, impersonate the client, and call
  102. // AccessCheck.
  103. //
  104. RpcStatus = RpcImpersonateClient(Context);
  105. if (RpcStatus != RPC_S_OK) {
  106. Status = RpcStatus;
  107. ClRtlLogPrint(LOG_NOISE, "[API] RpcImpersonateClient() failed. Status = 0x%1!.8x!\n", Status);
  108. goto FnExit;
  109. }
  110. bRevertToSelfRequired = TRUE;
  111. if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &ClientToken)) {
  112. Status = GetLastError();
  113. ClRtlLogPrint(LOG_NOISE, "[API] OpenThreadToken() failed. Status = 0x%1!.8x!\n", Status);
  114. goto FnExit;
  115. }
  116. gmMap.GenericRead = CLUSAPI_READ_ACCESS;
  117. gmMap.GenericWrite = CLUSAPI_CHANGE_ACCESS;
  118. gmMap.GenericExecute = CLUSAPI_READ_ACCESS | CLUSAPI_CHANGE_ACCESS;
  119. gmMap.GenericAll = CLUSAPI_ALL_ACCESS;
  120. MapGenericMask(&dwMask, &gmMap);
  121. // RAID 519037: We no longer read the security descriptor from the cluster database, as this
  122. // can cause an RPC timeout. The SD is now read during initialization and upon notification
  123. // of registry changes.
  124. // Synchronize access to SD without blocking for more than 15 seconds.
  125. // 15 seconds was chosen because it is half of the timeout for an RPC call.
  126. while (( dwRetries++ < 15 ) && !( bGotCritSect = TryEnterCriticalSection( &g_SDCritSect))) {
  127. Sleep( 1000 );
  128. }
  129. if ( !bGotCritSect ) {
  130. ClRtlLogPrint( LOG_UNUSUAL, "[API] Timed out waiting for SD critsect.\n" );
  131. Status = WAIT_FAILED;
  132. goto FnExit;
  133. }
  134. bACRtn = ( g_SD != NULL )
  135. && AccessCheck(g_SD, ClientToken, dwMask, &gmMap, &psPrivileges, &PrivSize, &dwStatus, &bReturn);
  136. if (bACRtn && bReturn) {
  137. Status = RPC_S_OK;
  138. } else {
  139. DWORD dwSDLen;
  140. if ( g_SD != NULL ) {
  141. ClRtlLogPrint(LOG_NOISE,
  142. "[API] User denied access. GetLastError() = 0x%1!.8x!; dwStatus = 0x%2!.8x!. Trying the default SD...\n",
  143. GetLastError(),
  144. dwStatus);
  145. }
  146. Status = RPC_S_ACCESS_DENIED;
  147. ClRtlLogPrint(LOG_NOISE, "[API] Dump access mask.\n");
  148. ClRtlExamineMask(dwMask, "[API]");
  149. #if CLUSTER_BETA
  150. if ( g_SD != NULL ) {
  151. //
  152. // SDs can be big and this could add hundreds of lines of text to the log
  153. //
  154. ClRtlLogPrint(LOG_NOISE, "[API] Dump the SD that failed...\n" );
  155. ClRtlExamineSD(g_SD, "[API]");
  156. }
  157. #endif
  158. ClRtlLogPrint(LOG_NOISE, "[API] Dump the ClientToken that failed...\n" );
  159. ClRtlExamineClientToken(ClientToken, "[API]");
  160. Status = ClRtlBuildDefaultClusterSD(NULL, &pdefaultSD, &dwSDLen);
  161. if (SUCCEEDED(Status)) {
  162. ClRtlLogPrint(LOG_NOISE, "[API] Successfully built default cluster SD.\n");
  163. bACRtn = AccessCheck(pdefaultSD, ClientToken, dwMask, &gmMap, &psPrivileges, &PrivSize, &dwStatus, &bReturn);
  164. if (bACRtn && bReturn) {
  165. ClRtlLogPrint(LOG_NOISE, "[API] User granted access using default cluster SD.\n");
  166. Status = RPC_S_OK;
  167. } else {
  168. ClRtlLogPrint(LOG_NOISE,
  169. "[API] User denied access using default cluster SD. GetLastError() = 0x%1!.8x!; dwStatus = 0x%2!.8x!.\n",
  170. GetLastError(),
  171. dwStatus);
  172. Status = RPC_S_ACCESS_DENIED;
  173. }
  174. // InitializeClusterSD may have been temporarily unable to set g_SD due to low memory; if at this
  175. // point we have successfully built a default SD, assign it to g_SD.
  176. if ( g_SD == NULL ) {
  177. g_SD = pdefaultSD;
  178. pdefaultSD = NULL;
  179. }
  180. }
  181. else {
  182. ClRtlLogPrint(LOG_CRITICAL,
  183. "[API] Did not successfully build default cluster SD. Error = 0x%1!.8x!\n",
  184. Status);
  185. Status = RPC_S_ACCESS_DENIED;
  186. }
  187. }
  188. FnExit:
  189. if ( bGotCritSect ) {
  190. LeaveCriticalSection( &g_SDCritSect );
  191. }
  192. if (bRevertToSelfRequired) {
  193. RpcRevertToSelf();
  194. }
  195. if (ClientToken) {
  196. CloseHandle(ClientToken);
  197. }
  198. if (pdefaultSD) {
  199. LocalFree(pdefaultSD);
  200. }
  201. return(Status);
  202. }
  203. DWORD
  204. ApiInitialize(
  205. VOID
  206. )
  207. /*++
  208. Routine Description:
  209. Performs one-time initialization of the API data structures.
  210. Arguments:
  211. None.
  212. Return Value:
  213. ERROR_SUCCESS if successful
  214. Win32 error code otherwise.
  215. --*/
  216. {
  217. ClRtlLogPrint(LOG_NOISE, "[API] Initializing\n");
  218. CL_ASSERT(ApiState == ApiStateUninitialized);
  219. //
  220. // Initialize global data.
  221. //
  222. InitializeListHead(&NotifyListHead);
  223. InitializeCriticalSection(&NotifyListLock);
  224. InitializeCriticalSection( &g_SDCritSect );
  225. ApiState = ApiStateOffline;
  226. return(ERROR_SUCCESS);
  227. }
  228. DWORD
  229. InitializeClusterSD(
  230. VOID
  231. )
  232. /*++
  233. --*/
  234. {
  235. DWORD BufferSize=0;
  236. DWORD Size=0;
  237. DWORD Status = ERROR_SUCCESS;
  238. EnterCriticalSection( &g_SDCritSect );
  239. if ( g_SD ) {
  240. LocalFree( g_SD );
  241. g_SD = NULL;
  242. }
  243. Status = DmQueryString(DmClusterParametersKey,
  244. CLUSREG_NAME_CLUS_SD,
  245. REG_BINARY,
  246. (LPWSTR *) &g_SD,
  247. &BufferSize,
  248. &Size);
  249. if (Status == ERROR_SUCCESS) {
  250. if (!IsValidSecurityDescriptor(g_SD)) {
  251. ClRtlLogPrint(LOG_CRITICAL, "[API] ApiReadSDFromReg - SD is not valid!\n");
  252. // Set Status, but do not bail yet. Further down we will create a default SD.
  253. Status = RPC_S_ACCESS_DENIED;
  254. }
  255. }
  256. else {
  257. PSECURITY_DESCRIPTOR psd4;
  258. ClRtlLogPrint(LOG_NOISE, "[API] InitializeClusterSD - Did not find Security Descriptor key in the cluster DB.\n");
  259. Status = DmQueryString(DmClusterParametersKey,
  260. CLUSREG_NAME_CLUS_SECURITY,
  261. REG_BINARY,
  262. (LPWSTR *) &psd4,
  263. &BufferSize,
  264. &Size);
  265. if (Status == ERROR_SUCCESS) {
  266. g_SD = ClRtlConvertClusterSDToNT5Format(psd4);
  267. if ( g_SD == NULL ) {
  268. ClRtlLogPrint(LOG_CRITICAL, "[API] InitializeClusterSD - Unable to convert SD to NT5 format." );
  269. Status = ERROR_INVALID_PARAMETER;
  270. }
  271. LocalFree(psd4);
  272. }
  273. else {
  274. ClRtlLogPrint(LOG_NOISE, "[API] InitializeClusterSD - Did not find Security key in the cluster DB.\n");
  275. } // Else failed to read CLUS_SECURITY
  276. } // Else failed to read CLUS_SD
  277. // If we still haven't got a valid SD at this point, create a default one.
  278. if ( Status != ERROR_SUCCESS ) {
  279. DWORD dwSDLen;
  280. Status = ClRtlBuildDefaultClusterSD(NULL, &g_SD, &dwSDLen);
  281. if (SUCCEEDED(Status)) {
  282. ClRtlLogPrint(LOG_NOISE, "[API] InitializeClusterSD - Successfully built default cluster SD.\n");
  283. }
  284. else {
  285. ClRtlLogPrint(LOG_CRITICAL,
  286. "[API] InitializeClusterSD - Did not successfully build default cluster SD. Error = 0x%1!.8x!\n",
  287. Status);
  288. Status = RPC_S_ACCESS_DENIED;
  289. }
  290. }
  291. if (( Status != ERROR_SUCCESS ) && ( g_SD != NULL )) {
  292. LocalFree( g_SD );
  293. g_SD = NULL;
  294. }
  295. if ( Status == ERROR_SUCCESS ) {
  296. CL_ASSERT( g_SD != NULL );
  297. }
  298. LeaveCriticalSection( &g_SDCritSect );
  299. return Status;
  300. }
  301. DWORD
  302. ApiOnlineReadOnly(
  303. VOID
  304. )
  305. /*++
  306. Routine Description:
  307. Brings up a limited set of APIs - currently OpenResource/read-only
  308. registry APIs. Only LPC connections are enabled.
  309. Arguments:
  310. None.
  311. Return Value:
  312. ERROR_SUCCESS if successful
  313. Win32 error code otherwise.
  314. --*/
  315. {
  316. DWORD Status = ERROR_SUCCESS;
  317. if (ApiState == ApiStateOffline) {
  318. ClRtlLogPrint(LOG_NOISE, "[API] Online read only\n");
  319. // No need to log anything here -- the routine does its own logging,
  320. if (( Status = InitializeClusterSD()) != ERROR_SUCCESS ) {
  321. goto FnExit;
  322. }
  323. //
  324. // Register the clusapi RPC server interface so resources can use
  325. // the API when they are created by the FM. Note that we won't receive
  326. // any calls from remote clients yet because we haven't registered
  327. // the dynamic UDP endpoint. That will happnen in ApiOnline().
  328. //
  329. Status = RpcServerRegisterIfEx(s_clusapi_v2_0_s_ifspec,
  330. NULL,
  331. NULL,
  332. 0, // No need to set RPC_IF_ALLOW_SECURE_ONLY if security callback
  333. // is specified. If security callback is specified, RPC
  334. // will reject unauthenticated requests without invoking
  335. // callback. This is the info obtained from RpcDev. See
  336. // Windows Bug 572035.
  337. RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
  338. ApipConnectCallback
  339. );
  340. if (Status != RPC_S_OK) {
  341. ClRtlLogPrint(LOG_UNUSUAL,
  342. "[API] Failed to register clusapi RPC interface, status %1!u!.\n",
  343. Status
  344. );
  345. goto FnExit;
  346. }
  347. if ( Status == ERROR_SUCCESS ) {
  348. ApiState = ApiStateReadOnly;
  349. }
  350. }
  351. else {
  352. //CL_ASSERT(ApiState == ApiStateOffline);
  353. }
  354. FnExit:
  355. return Status;
  356. }
  357. DWORD
  358. ApiOnline(
  359. VOID
  360. )
  361. /*++
  362. Routine Description:
  363. Enables the rest of the API set and starts listening for remote
  364. connections.
  365. Arguments:
  366. None
  367. Return Value:
  368. ERROR_SUCCESS if successful.
  369. Win32 error code otherwise.
  370. --*/
  371. {
  372. DWORD Status = ERROR_SUCCESS;
  373. ClRtlLogPrint(LOG_NOISE, "[API] Online\n");
  374. if (ApiState == ApiStateReadOnly) {
  375. // No need to log anything here -- the routine does its own logging,
  376. if (( Status = InitializeClusterSD()) != ERROR_SUCCESS ) {
  377. goto FnExit;
  378. }
  379. //
  380. // Register for all events
  381. //
  382. Status = EpRegisterEventHandler(CLUSTER_EVENT_ALL,ApipEventHandler);
  383. if (Status != ERROR_SUCCESS) {
  384. return(Status);
  385. }
  386. //
  387. // Register the dynamic UDP endpoint for the clusapi interface.
  388. // This will enable remote clients to begin calling us. We do this
  389. // here to minimize the chances that we will service an external
  390. // call before we are ready. If we ever have to rollback after
  391. // this point, we will still be listening externally. Nothing we can
  392. // do about that.
  393. //
  394. CL_ASSERT(CsRpcBindingVector != NULL);
  395. Status = RpcEpRegister(s_clusapi_v2_0_s_ifspec,
  396. CsRpcBindingVector,
  397. NULL,
  398. L"Microsoft Cluster Server API");
  399. if (Status != RPC_S_OK) {
  400. ClRtlLogPrint(LOG_UNUSUAL,
  401. "[API] Failed to register endpoint for clusapi RPC interface, status %1!u!.\n",
  402. Status
  403. );
  404. NmDumpRpcExtErrorInfo(Status);
  405. goto FnExit;
  406. }
  407. if ( Status == ERROR_SUCCESS ) {
  408. ApiState = ApiStateOnline;
  409. }
  410. }
  411. else {
  412. CL_ASSERT(ApiState == ApiStateReadOnly);
  413. }
  414. FnExit:
  415. return Status;
  416. }
  417. VOID
  418. ApiOffline(
  419. VOID
  420. )
  421. /*++
  422. Routine Description:
  423. Takes the Cluster Api offline.
  424. Arguments:
  425. None.
  426. Returns:
  427. None.
  428. --*/
  429. {
  430. DWORD Status;
  431. if (ApiState == ApiStateOnline) {
  432. ClRtlLogPrint(LOG_NOISE, "[API] Offline\n");
  433. //
  434. // Deregister the Clusapi RPC endpoint
  435. //
  436. CL_ASSERT(CsRpcBindingVector != NULL);
  437. Status = RpcEpUnregister(
  438. s_clusapi_v2_0_s_ifspec,
  439. CsRpcBindingVector,
  440. NULL
  441. );
  442. if ((Status != RPC_S_OK) && (Status != EPT_S_NOT_REGISTERED)) {
  443. ClRtlLogPrint(LOG_UNUSUAL,
  444. "[API] Failed to deregister endpoint for clusapi RPC interface, status %1!u!.\n",
  445. Status
  446. );
  447. }
  448. ApiState = ApiStateReadOnly;
  449. }
  450. //
  451. // KB - We can't deregister the interface because we can't wait for
  452. // pending calls to complete - pending notifies never complete.
  453. // If we deregistered the interface after a failed join without
  454. // a complete shutdown, the subsequent form would fail. As a
  455. // result, the API won't go offline until service shutdown.
  456. //
  457. #if 0
  458. if (ApiState == ApiStateReadOnly) {
  459. //
  460. // Deregister the Clusapi RPC interface
  461. //
  462. Status = RpcServerUnregisterIf(
  463. s_clusapi_v2_0_s_ifspec,
  464. NULL,
  465. 1 // Wait for outstanding calls to complete
  466. );
  467. if ((Status != RPC_S_OK) && (Status != RPC_S_UNKNOWN_IF)) {
  468. ClRtlLogPrint(LOG_UNUSUAL,
  469. "[INIT] Unable to deregister the clusapi RPC interface, Status %1!u!.\n",
  470. Status
  471. );
  472. }
  473. ApiState = ApiStateOffline;
  474. }
  475. #endif
  476. return;
  477. }
  478. VOID
  479. ApiShutdown(
  480. VOID
  481. )
  482. /*++
  483. Routine Description:
  484. Shuts down the Cluster Api
  485. Arguments:
  486. None.
  487. Returns:
  488. None.
  489. --*/
  490. {
  491. DWORD Status;
  492. if (ApiState > ApiStateOffline) {
  493. ApiOffline();
  494. //
  495. // KB - We do this here because shutdown of the Clusapi RPC
  496. // interface is broken due to pending notifies.
  497. //
  498. Status = RpcServerUnregisterIf(
  499. s_clusapi_v2_0_s_ifspec,
  500. NULL,
  501. 0 // Don't wait for calls to complete
  502. );
  503. if ((Status != RPC_S_OK) && (Status != RPC_S_UNKNOWN_IF)) {
  504. ClRtlLogPrint(LOG_UNUSUAL,
  505. "[INIT] Unable to deregister the clusapi RPC interface, Status %1!u!.\n",
  506. Status
  507. );
  508. }
  509. ApiState = ApiStateOffline;
  510. }
  511. if (ApiState == ApiStateOffline) {
  512. ClRtlLogPrint(LOG_NOISE, "[API] Shutdown\n");
  513. //
  514. // KB
  515. //
  516. // Because we cannot shutdown the RPC server and cannot
  517. // unregister our event handler, it is not safe to delete
  518. // the critical section.
  519. //
  520. // DeleteCriticalSection(&NotifyListLock);
  521. // ApiState = ApiStateUninitialized;
  522. //
  523. // TODO?
  524. //
  525. // SS: free notify list head
  526. // SS: how do we deregister with the event handler
  527. //
  528. }
  529. return;
  530. }
  531. DWORD
  532. ApipGetLocalCallerInfo(
  533. IN handle_t hIDL,
  534. IN OUT OPTIONAL LPDWORD pdwCheckPid,
  535. IN OPTIONAL LPCWSTR pszModuleName,
  536. OUT BOOL *pbLocal,
  537. OUT OPTIONAL BOOL *pbMatchedPid,
  538. OUT OPTIONAL BOOL *pbMatchedModule,
  539. OUT OPTIONAL BOOL *pbLocalSystemAccount
  540. )
  541. /*++
  542. Routine Description:
  543. This function checks whether the caller's account is the local system
  544. account.
  545. Arguments:
  546. hIDL - The handle to the binding context
  547. pdwCheckPid - if the value passed in is NULL, the pid of the calling process is returned. If
  548. is returned.
  549. pszModuleName - If non null, the call performs the check to compare
  550. the module name of the caller against pszModuleName. If they
  551. match, *pbMatchedPid is set to TRUE.
  552. pbLocal - TRUE is returned if the caller initiated this call using
  553. lrpc. If this is FALSE, all other output values will be FALSE.
  554. pbMatchedModule - TRUE is returned, if the caller matches the module
  555. name specified by lpszModuleName. This pointer can be NULL.
  556. pbMatchedPid - if *pdwCheckPid is non NULL, and it matched the pid of the
  557. caller, then this is set to TRUE. Else, this is set to FALSE.
  558. pbLocalSystemAccount - If this is NON NULL, the call performs a check
  559. to see if the the caller is running in LocalSystemAccount. If it is
  560. then TRUE is returned, else FALSE is returned.
  561. Return Value:
  562. ERROR_SUCCESS on success.
  563. Win32 error code on failure.
  564. Remarks:
  565. --*/
  566. {
  567. DWORD Pid;
  568. HANDLE hProcess = NULL;
  569. DWORD dwNumChar;
  570. DWORD dwLen;
  571. WCHAR wCallerPath[MAX_PATH + 1];
  572. RPC_STATUS RpcStatus;
  573. DWORD dwStatus = ERROR_SUCCESS;
  574. BOOLEAN bWasEnabled;
  575. if (pbMatchedModule)
  576. *pbMatchedModule = FALSE;
  577. if (pbMatchedPid)
  578. *pbMatchedPid = FALSE;
  579. if (pbLocalSystemAccount)
  580. *pbLocalSystemAccount = FALSE;
  581. //assume the caller is local
  582. *pbLocal = TRUE;
  583. RpcStatus = I_RpcBindingInqLocalClientPID(NULL, &Pid );
  584. if (RpcStatus == RPC_S_INVALID_BINDING)
  585. {
  586. *pbLocal = FALSE;
  587. RpcStatus = RPC_S_OK;
  588. goto FnExit;
  589. }
  590. dwStatus = I_RpcMapWin32Status(RpcStatus);
  591. if (dwStatus != ERROR_SUCCESS)
  592. {
  593. ClRtlLogPrint( LOG_CRITICAL,
  594. "[API] ApipGetLocalCallerInfo: Error %1!u! calling RpcBindingInqLocalClientPID.\n",
  595. dwStatus
  596. );
  597. goto FnExit;
  598. }
  599. dwStatus = ClRtlEnableThreadPrivilege(SE_DEBUG_PRIVILEGE, &bWasEnabled);
  600. if ( dwStatus != ERROR_SUCCESS )
  601. {
  602. if (dwStatus == STATUS_PRIVILEGE_NOT_HELD)
  603. {
  604. ClRtlLogPrint(LOG_CRITICAL,
  605. "[API] ApipGetLocalCallerInfo: Debug privilege not held by cluster service\n");
  606. }
  607. else
  608. {
  609. ClRtlLogPrint(LOG_CRITICAL,
  610. "[API] ApipGetLocalCallerInfo: Attempt to enable debug privilege failed %1!lx!\n",
  611. dwStatus);
  612. }
  613. goto FnExit;
  614. }
  615. // Get the process
  616. hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, Pid);
  617. //restore the thread privilege, now that we have a process handle with the right access
  618. ClRtlRestoreThreadPrivilege(SE_DEBUG_PRIVILEGE,
  619. bWasEnabled);
  620. if(hProcess == NULL)
  621. {
  622. dwStatus = GetLastError();
  623. ClRtlLogPrint( LOG_CRITICAL,
  624. "[API] ApipGetLocalCallerInfo: Error %1!u! calling OpenProcess %2!u!.\n",
  625. dwStatus,
  626. Pid
  627. );
  628. goto FnExit;
  629. }
  630. //if a process id has been specified, see if it matches that one
  631. if (pdwCheckPid)
  632. {
  633. if ((*pdwCheckPid) && (*pdwCheckPid == Pid))
  634. {
  635. *pbMatchedPid = TRUE;
  636. }
  637. }
  638. if (pszModuleName && pbMatchedModule)
  639. {
  640. // Get the module name of whoever is calling us.
  641. dwNumChar = GetModuleFileNameExW(hProcess, NULL, wCallerPath, MAX_PATH);
  642. if(dwNumChar == 0)
  643. {
  644. dwStatus = GetLastError();
  645. ClRtlLogPrint( LOG_CRITICAL,
  646. "[API] ApipGetLocalCallerInfo: Error %1!u! calling GetModuleFileNameExW.\n",
  647. dwStatus
  648. );
  649. goto FnExit;
  650. }
  651. if(!lstrcmpiW(wCallerPath, pszModuleName))
  652. {
  653. *pbMatchedModule = TRUE;
  654. }
  655. }
  656. //check if it is the local system account, if requested
  657. if (pbLocalSystemAccount && hIDL)
  658. {
  659. // Impersonate the client.
  660. if ( ( RpcStatus = RpcImpersonateClient( hIDL ) ) != RPC_S_OK )
  661. {
  662. dwStatus = I_RpcMapWin32Status(RpcStatus);
  663. ClRtlLogPrint( LOG_CRITICAL,
  664. "[API] ApipGetLocalCallerInfo: Error %1!u! trying to impersonate caller...\n",
  665. dwStatus
  666. );
  667. goto FnExit;
  668. }
  669. // Check that the caller's account is local system account
  670. dwStatus = ClRtlIsCallerAccountLocalSystemAccount(pbLocalSystemAccount );
  671. RpcRevertToSelf();
  672. if (dwStatus != ERROR_SUCCESS )
  673. {
  674. ClRtlLogPrint( LOG_CRITICAL,
  675. "[API] ApipGetLocalCallerInfo : Error %1!u! trying to check caller's account...\n",
  676. dwStatus);
  677. goto FnExit;
  678. }
  679. }
  680. //return the pid if the pid passed in is NULL and the pid passes
  681. //the criteria - matches pszModuleName if specified and is in
  682. //local system account
  683. if (pdwCheckPid && !(*pdwCheckPid))
  684. {
  685. //if we need to check for local system, the process must be in local system account
  686. //if the module name needs to be checked
  687. if (((pbLocalSystemAccount && *pbLocalSystemAccount) || (!pbLocalSystemAccount))
  688. && ((pszModuleName && pbMatchedModule && *pbMatchedModule) || (!pbMatchedModule)))
  689. {
  690. ClRtlLogPrint( LOG_NOISE,
  691. "[API] ApipGetLocalCallerInfo : Returning Pid %1!u!\n",
  692. Pid);
  693. *pdwCheckPid = Pid;
  694. }
  695. }
  696. FnExit:
  697. if (hProcess)
  698. CloseHandle(hProcess);
  699. return(dwStatus);
  700. }