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.

3968 lines
111 KiB

  1. /*++
  2. Copyright (c) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. frsrpc.c
  5. Abstract:
  6. Setup the server and client side of authenticated RPC.
  7. Author:
  8. Billy J. Fuller 20-Mar-1997 (From Jim McNelis)
  9. Environment
  10. User mode winnt
  11. --*/
  12. #include <ntreppch.h>
  13. #pragma hdrstop
  14. #include <frs.h>
  15. #include <ntfrsapi.h>
  16. #include <dsrole.h>
  17. #include <info.h>
  18. #include <perffrs.h>
  19. #include <perrepsr.h>
  20. extern HANDLE PerfmonProcessSemaphore;
  21. extern BOOL MutualAuthenticationIsEnabled;
  22. extern BOOL MutualAuthenticationIsEnabledAndRequired;
  23. extern CRITICAL_SECTION CritSec_pValidPartnerTableStruct;
  24. extern PFRS_VALID_PARTNER_TABLE_STRUCT pValidPartnerTableStruct;
  25. extern BOOL NeedNewPartnerTable;
  26. //
  27. // KERBEROS is not available on a server that isn't a member of
  28. // a domain. It is possible for the non-member server to be a
  29. // client of a KERBEROS RPC server but that doesn't help NtFrs;
  30. // NtFrs requires server-to-server RPC.
  31. //
  32. BOOL KerberosIsNotAvailable;
  33. ULONG MaxRpcServerThreads; // Maximum number of concurrent server RPC calls
  34. ULONG RpcPortAssignment; // User specified port assignment for FRS.
  35. //
  36. // Binding Stats
  37. //
  38. ULONG RpcBinds;
  39. ULONG RpcUnBinds;
  40. ULONG RpcAgedBinds;
  41. LONG RpcMaxBinds;
  42. //
  43. // Table of sysvols being created
  44. //
  45. PGEN_TABLE SysVolsBeingCreated;
  46. //
  47. // This table translates the FRS API access check code number to registry key table
  48. // code for the enable/disable registry key check and the rights registry key check.
  49. // The FRS_API_ACCESS_CHECKS enum in config.h defines the indices for the
  50. // this table. The order of the entries here must match the order of the entries
  51. // in the ENUM.
  52. //
  53. typedef struct _RPC_API_KEYS_ {
  54. FRS_REG_KEY_CODE Enable; // FRS Registry Key Code for the Access Check enable string
  55. FRS_REG_KEY_CODE Rights; // FRS Registry Key Code for the Access Check rights string
  56. PWCHAR KeyName; // Key name for the API.
  57. } RPC_API_KEYS, *PRPC_API_KEYS;
  58. RPC_API_KEYS RpcApiKeys[ACX_MAX] = {
  59. {FKC_ACCCHK_STARTDS_POLL_ENABLE, FKC_ACCCHK_STARTDS_POLL_RIGHTS, ACK_START_DS_POLL},
  60. {FKC_ACCCHK_SETDS_POLL_ENABLE, FKC_ACCCHK_SETDS_POLL_RIGHTS, ACK_SET_DS_POLL},
  61. {FKC_ACCCHK_GETDS_POLL_ENABLE, FKC_ACCCHK_GETDS_POLL_RIGHTS, ACK_GET_DS_POLL},
  62. {FKC_ACCCHK_GET_INFO_ENABLE, FKC_ACCCHK_GET_INFO_RIGHTS, ACK_INTERNAL_INFO},
  63. {FKC_ACCCHK_PERFMON_ENABLE, FKC_ACCCHK_PERFMON_RIGHTS, ACK_COLLECT_PERFMON_DATA},
  64. {FKC_ACCESS_CHK_DCPROMO_ENABLE, FKC_ACCESS_CHK_DCPROMO_RIGHTS, ACK_DCPROMO},
  65. {FKC_ACCESS_CHK_IS_PATH_REPLICATED_ENABLE, FKC_ACCESS_CHK_IS_PATH_REPLICATED_RIGHTS, ACK_IS_PATH_REPLICATED},
  66. {FKC_ACCESS_CHK_WRITER_COMMANDS_ENABLE, FKC_ACCESS_CHK_WRITER_COMMANDS_RIGHTS, ACK_WRITER_COMMANDS}
  67. };
  68. DWORD
  69. UtilRpcServerHandleToAuthSidString(
  70. IN handle_t ServerHandle,
  71. IN PWCHAR AuthClient,
  72. OUT PWCHAR *ClientSid
  73. );
  74. DWORD
  75. FrsRpcCheckAuthIfEnabled(
  76. IN HANDLE ServerHandle,
  77. IN DWORD RpcApiIndex
  78. );
  79. DWORD
  80. FrsRpcCheckAuthIfEnabledForCommitDemotion(
  81. IN HANDLE ServerHandle,
  82. IN DWORD RpcApiIndex
  83. );
  84. //
  85. // Used by all calls to RpcBindingSetAuthInfoEx()
  86. //
  87. // Version set to value indicated by docs
  88. // Mutual authentication
  89. // Client doesn't change credentials
  90. // Impersonation but not delegation
  91. //
  92. RPC_SECURITY_QOS RpcSecurityQos = {
  93. RPC_C_SECURITY_QOS_VERSION, // static version
  94. RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH, // requires mutual auth
  95. RPC_C_QOS_IDENTITY_STATIC, // client credentials don't change
  96. RPC_C_IMP_LEVEL_IMPERSONATE // server cannot delegate
  97. };
  98. #define DPRINT_USER_NAME(Sev) DPrintUserName(Sev)
  99. ULONG
  100. RcsSubmitCmdPktToRcsQueue(
  101. IN PCOMMAND_PACKET Cmd,
  102. IN PCOMM_PACKET CommPkt,
  103. IN PWCHAR AuthClient,
  104. IN PWCHAR AuthName,
  105. IN PWCHAR AuthSid,
  106. IN DWORD AuthLevel,
  107. IN DWORD AuthN,
  108. IN DWORD AuthZ
  109. );
  110. PCOMMAND_PACKET
  111. CommPktToCmd(
  112. IN PCOMM_PACKET CommPkt
  113. );
  114. DWORD
  115. FrsDsIsPartnerADc(
  116. IN PWCHAR PartnerName
  117. );
  118. VOID
  119. FrsDsCreateNewValidPartnerTableStruct(
  120. VOID
  121. );
  122. DWORD
  123. FrsDsVerifyPromotionParent(
  124. IN PWCHAR ReplicaSetName,
  125. IN PWCHAR ReplicaSetType
  126. );
  127. DWORD
  128. FrsDsStartPromotionSeeding(
  129. IN BOOL Inbound,
  130. IN PWCHAR ReplicaSetName,
  131. IN PWCHAR ReplicaSetType,
  132. IN PWCHAR CxtionName,
  133. IN PWCHAR PartnerName,
  134. IN PWCHAR PartnerPrincName,
  135. IN PWCHAR PartnerSid,
  136. IN ULONG PartnerAuthLevel,
  137. IN ULONG GuidSize,
  138. IN UCHAR *CxtionGuid,
  139. IN UCHAR *PartnerGuid,
  140. OUT UCHAR *ParentGuid
  141. );
  142. DWORD
  143. FrsIsPathReplicated(
  144. IN PWCHAR Path,
  145. IN ULONG ReplicaSetTypeOfInterest,
  146. OUT ULONG *Replicated,
  147. OUT ULONG *Primary,
  148. OUT ULONG *Root,
  149. OUT GUID *ReplicaSetGuid
  150. );
  151. VOID
  152. FrsPrintRpcStats(
  153. IN ULONG Severity,
  154. IN PNTFRSAPI_INFO Info, OPTIONAL
  155. IN DWORD Tabs
  156. )
  157. /*++
  158. Routine Description:
  159. Print the rpc stats into the info buffer or using DPRINT (Info == NULL).
  160. Arguments:
  161. Severity - for DPRINT
  162. Info - for IPRINT (use DPRINT if NULL)
  163. Tabs - indentation for prettyprint
  164. Return Value:
  165. None.
  166. --*/
  167. {
  168. #undef DEBSUB
  169. #define DEBSUB "FrsPrintRpcStats:"
  170. WCHAR TabW[MAX_TAB_WCHARS + 1];
  171. InfoTabs(Tabs, TabW);
  172. IDPRINT0(Severity, Info, "\n");
  173. IDPRINT1(Severity, Info, ":S: %wsNTFRS RPC BINDS:\n", TabW);
  174. IDPRINT2(Severity, Info, ":S: %ws Binds : %6d\n", TabW, RpcBinds);
  175. IDPRINT3(Severity, Info, ":S: %ws UnBinds : %6d (%d aged)\n",
  176. TabW, RpcUnBinds, RpcAgedBinds);
  177. IDPRINT2(Severity, Info, ":S: %ws Max Binds : %6d\n", TabW, RpcMaxBinds);
  178. IDPRINT0(Severity, Info, "\n");
  179. }
  180. PVOID
  181. MIDL_user_allocate(
  182. IN size_t Bytes
  183. )
  184. /*++
  185. Routine Description:
  186. Allocate memory for RPC.
  187. XXX This should be using davidor's routines.
  188. Arguments:
  189. Bytes - Number of bytes to allocate.
  190. Return Value:
  191. NULL - memory could not be allocated.
  192. !NULL - address of allocated memory.
  193. --*/
  194. {
  195. #undef DEBSUB
  196. #define DEBSUB "MIDL_user_allocate:"
  197. PVOID VA;
  198. //
  199. // Need to check if Bytes == 0 as FrsAlloc asserts if called with 0 as the first parameter (prefix fix).
  200. //
  201. if (Bytes == 0) {
  202. return NULL;
  203. }
  204. VA = FrsAlloc(Bytes);
  205. return VA;
  206. }
  207. VOID
  208. MIDL_user_free(
  209. IN PVOID Buffer
  210. )
  211. /*++
  212. Routine Description:
  213. Free memory for RPC.
  214. XXX This should be using davidor's routines.
  215. Arguments:
  216. Buffer - Address of memory allocated with MIDL_user_allocate().
  217. Return Value:
  218. None.
  219. --*/
  220. {
  221. #undef DEBSUB
  222. #define DEBSUB "MIDL_user_free:"
  223. FrsFree(Buffer);
  224. }
  225. VOID
  226. DPrintUserName(
  227. IN DWORD Sev
  228. )
  229. /*++
  230. Routine Description:
  231. Print our user name
  232. Arguments:
  233. Sev
  234. Return Value:
  235. None.
  236. --*/
  237. {
  238. #undef DEBSUB
  239. #define DEBSUB "DPrintUserName:"
  240. WCHAR Uname[MAX_PATH + 1];
  241. ULONG Unamesize = MAX_PATH + 1;
  242. if (GetUserName(Uname, &Unamesize)) {
  243. DPRINT1(Sev, "++ User name is %ws\n", Uname);
  244. } else {
  245. DPRINT_WS(0, "++ ERROR - Getting user name;", GetLastError());
  246. }
  247. }
  248. RPC_STATUS
  249. DummyRpcCallback (
  250. IN RPC_IF_ID *Interface,
  251. IN PVOID Context
  252. )
  253. /*++
  254. Routine Description:
  255. Dummy callback routine. By registering this routine, RPC will automatically
  256. refuse requests from clients that don't include authentication info.
  257. WARN: Disabled for now because frs needs to run in dcpromo environments
  258. that do not have any form of authentication.
  259. Arguments:
  260. Ignored
  261. Return Value:
  262. RPC_S_OK
  263. --*/
  264. {
  265. #undef DEBSUB
  266. #define DEBSUB "DummyRpcCallback:"
  267. return RPC_S_OK;
  268. }
  269. DWORD
  270. SERVER_FrsNOP(
  271. handle_t Handle
  272. )
  273. /*++
  274. Routine Description:
  275. The frsrpc interface includes a NOP function for pinging
  276. the server.
  277. Arguments:
  278. None.
  279. Return Value:
  280. None.
  281. --*/
  282. {
  283. #undef DEBSUB
  284. #define DEBSUB "SERVER_FrsNOP:"
  285. return ERROR_SUCCESS;
  286. }
  287. DWORD
  288. SERVER_FrsRpcSendCommPkt(
  289. handle_t Handle,
  290. PCOMM_PACKET CommPkt
  291. )
  292. /*++
  293. Routine Description:
  294. Receiving a command packet
  295. Arguments:
  296. None.
  297. Return Value:
  298. ERROR_SUCCESS - everything was okay
  299. Anything else - the error code says it all
  300. --*/
  301. {
  302. #undef DEBSUB
  303. #define DEBSUB "SERVER_FrsRpcSendCommPkt:"
  304. DWORD WStatus = 0;
  305. DWORD AuthLevel = 0;
  306. DWORD AuthN = 0;
  307. DWORD AuthZ = 0;
  308. PWCHAR AuthName = NULL;
  309. PWCHAR AuthClient = NULL;
  310. PWCHAR AuthSid = NULL;
  311. PCOMMAND_PACKET Cmd = NULL;
  312. PFRS_VALID_PARTNER_TABLE_STRUCT pVptStruct = NULL;
  313. PWCHAR CxtionPartnerName = NULL;
  314. PQHASH_ENTRY pQHashEntry = NULL;
  315. //
  316. // Don't send or receive during shutdown
  317. //
  318. if (FrsIsShuttingDown) {
  319. return ERROR_SUCCESS;
  320. }
  321. try {
  322. if (!CommValidatePkt(CommPkt)) {
  323. WStatus = ERROR_NOT_SUPPORTED;
  324. DPRINT1(0, ":SR: Comm %08x, [RcvFailAuth - bad packet]", PtrToUlong(CommPkt));
  325. //
  326. // Increment the Packets Received in Error Counter
  327. //
  328. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvdError, 1);
  329. goto CLEANUP;
  330. }
  331. #ifndef DS_FREE
  332. if (!ServerGuid) {
  333. WStatus = RpcBindingInqAuthClient(Handle,
  334. &AuthClient,
  335. &AuthName,
  336. &AuthLevel,
  337. &AuthN,
  338. &AuthZ);
  339. DPRINT_WS(4, "++ IGNORED - RpcBindingInqAuthClient;", WStatus);
  340. COMMAND_RCV_AUTH_TRACE(4, CommPkt, WStatus, AuthLevel, AuthN,
  341. AuthClient, AuthName, "RcvAuth");
  342. if (!WIN_SUCCESS(WStatus)) {
  343. WStatus = ERROR_ACCESS_DENIED;
  344. goto CLEANUP;
  345. }
  346. WStatus = UtilRpcServerHandleToAuthSidString(Handle, AuthClient, &AuthSid );
  347. if (!WIN_SUCCESS(WStatus)) {
  348. WStatus = ERROR_ACCESS_DENIED;
  349. goto CLEANUP;
  350. }
  351. ACQUIRE_VALID_PARTNER_TABLE_POINTER(&pVptStruct);
  352. if ((pVptStruct == NULL) ||
  353. (NULL == QHashLookupLock(pVptStruct->pPartnerTable, AuthSid))) {
  354. // invalid partner.
  355. DPRINT2(0, "++ ERROR - Invalid Partner: AuthClient:%ws, AuthSid:%ws\n", AuthClient,AuthSid);
  356. WStatus = ERROR_ACCESS_DENIED;
  357. goto CLEANUP;
  358. }
  359. } else {
  360. //
  361. // For hardwired -- Eventually DS Free configs.
  362. //
  363. DPRINT1(4, ":SR: Comm %08x, [RcvAuth - hardwired]", PtrToUlong(CommPkt));
  364. }
  365. #endif DS_FREE
  366. //
  367. // Increment the Packets Received and
  368. // Packets Received in bytes counters
  369. //
  370. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvd, 1);
  371. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvdBytes, CommPkt->PktLen);
  372. switch(CommPkt->CsId) {
  373. case CS_RS:
  374. //
  375. // Convert the comm packet into a command packet
  376. //
  377. Cmd = CommPktToCmd(CommPkt);
  378. if (Cmd == NULL) {
  379. COMMAND_RCV_TRACE(3, Cmd, NULL, ERROR_INVALID_DATA, "RcvFail - no cmd");
  380. WStatus = ERROR_INVALID_DATA;
  381. goto CLEANUP;
  382. }
  383. //
  384. // Only allow certian cmd types through. Reject anything else.
  385. //
  386. switch (Cmd->Command) {
  387. case CMD_REMOTE_CO:
  388. case CMD_RECEIVING_STAGE:
  389. case CMD_REMOTE_CO_DONE:
  390. case CMD_ABORT_FETCH:
  391. case CMD_RETRY_FETCH:
  392. case CMD_NEED_JOIN:
  393. case CMD_START_JOIN:
  394. case CMD_JOINING_AFTER_FLUSH:
  395. case CMD_JOINING:
  396. case CMD_JOINED:
  397. case CMD_UNJOIN_REMOTE:
  398. case CMD_VVJOIN_DONE:
  399. case CMD_SEND_STAGE:
  400. if (!RsCxtion(Cmd)) {
  401. DPRINT(0, "++ ERROR - No Cxtion");
  402. WStatus = ERROR_INVALID_DATA;
  403. goto CLEANUP;
  404. }
  405. #ifndef DS_FREE
  406. pQHashEntry = QHashLookupLock(pVptStruct->pPartnerConnectionTable,
  407. RsCxtion(Cmd)->Guid);
  408. if((pQHashEntry == NULL) ||
  409. (0 != _wcsicmp((PWCHAR)(pQHashEntry->QData), AuthSid))) {
  410. // invalid cxtion.
  411. CHAR Guid[GUID_CHAR_LEN + 1];
  412. GuidToStr(RsCxtion(Cmd)->Guid, Guid);
  413. if (pQHashEntry == NULL) {
  414. DPRINT2(4, "++ Cxtion %s not found. Partner SID is %ws\n", Guid, AuthSid);
  415. }else {
  416. DPRINT3(0, "++ ERROR - Partner SID mismatch for Cxtion %s. Received %ws instead of %ws\n", Guid, AuthSid, (PWCHAR)(pQHashEntry->QData));
  417. }
  418. WStatus = ERROR_INVALID_DATA;
  419. goto CLEANUP;
  420. }
  421. #endif DS_FREE
  422. break;
  423. default:
  424. DPRINT1(0, "Invalid remote command 0x%x\n", Cmd->Command);
  425. WStatus = ERROR_INVALID_DATA;
  426. FrsCompleteCommand(Cmd, ERROR_INVALID_DATA);
  427. goto CLEANUP;
  428. }
  429. WStatus = RcsSubmitCmdPktToRcsQueue(Cmd,
  430. CommPkt,
  431. AuthClient,
  432. AuthName,
  433. AuthSid,
  434. AuthLevel,
  435. AuthN,
  436. AuthZ);
  437. break;
  438. default:
  439. WStatus = ERROR_INVALID_OPERATION;
  440. COMMAND_RCV_AUTH_TRACE(0, CommPkt, WStatus, AuthLevel, AuthN,
  441. AuthClient, AuthName, "RcvFailAuth - bad csid");
  442. }
  443. CLEANUP:;
  444. } except (EXCEPTION_EXECUTE_HANDLER) {
  445. GET_EXCEPTION_CODE(WStatus);
  446. DPRINT2(0, ":SR: Comm %08x, WStatus 0x%08x [RcvFailAuth - exception]", PtrToUlong(CommPkt), WStatus);
  447. }
  448. try {
  449. if (AuthName) {
  450. RpcStringFree(&AuthName);
  451. }
  452. } except (EXCEPTION_EXECUTE_HANDLER) {
  453. GET_EXCEPTION_CODE(WStatus);
  454. DPRINT2(0, ":SR: Comm %08x, WStatus 0x%08x [RcvFailAuth - cleanup exception]", PtrToUlong(CommPkt), WStatus);
  455. }
  456. #ifndef DS_FREE
  457. if (pVptStruct) {
  458. RELEASE_VALID_PARTNER_TABLE_POINTER(pVptStruct);
  459. }
  460. #endif DS_FREE
  461. if (AuthSid) {
  462. FrsFree(AuthSid);
  463. }
  464. return WStatus;
  465. }
  466. DWORD
  467. SERVER_FrsEnumerateReplicaPathnames(
  468. handle_t Handle
  469. )
  470. /*++
  471. Routine Description:
  472. NOT IMPLEMENTED - Enumerate the replica sets
  473. Arguments:
  474. None.
  475. Return Value:
  476. None.
  477. --*/
  478. {
  479. #undef DEBSUB
  480. #define DEBSUB "SERVER_FrsEnumerateReplicaPathnames:"
  481. return ERROR_CALL_NOT_IMPLEMENTED;
  482. }
  483. DWORD
  484. SERVER_FrsFreeReplicaPathnames(
  485. handle_t Handle
  486. )
  487. /*++
  488. Routine Description:
  489. NOT IMPLEMENTED - Just a placeholder, it won't really be part of
  490. the RPC interface but rather a function in the client-side dll.
  491. Arguments:
  492. None.
  493. Return Value:
  494. None.
  495. --*/
  496. {
  497. #undef DEBSUB
  498. #define DEBSUB "SERVER_FrsFreeReplicaPathnames:"
  499. return ERROR_CALL_NOT_IMPLEMENTED;
  500. }
  501. DWORD
  502. SERVER_FrsPrepareForBackup(
  503. handle_t Handle
  504. )
  505. /*++
  506. Routine Description:
  507. NOT IMPLEMENTED - Prepare for backup
  508. Arguments:
  509. None.
  510. Return Value:
  511. None.
  512. --*/
  513. {
  514. #undef DEBSUB
  515. #define DEBSUB "SERVER_FrsPrepareForBackup:"
  516. return ERROR_CALL_NOT_IMPLEMENTED;
  517. }
  518. DWORD
  519. SERVER_FrsBackupComplete(
  520. handle_t Handle
  521. )
  522. /*++
  523. Routine Description:
  524. NOT IMPLEMENTED - backup is complete; reset state
  525. Arguments:
  526. None.
  527. Return Value:
  528. None.
  529. --*/
  530. {
  531. #undef DEBSUB
  532. #define DEBSUB "SERVER_FrsBackupComplete:"
  533. return ERROR_CALL_NOT_IMPLEMENTED;
  534. }
  535. DWORD
  536. SERVER_FrsPrepareForRestore(
  537. handle_t Handle
  538. )
  539. /*++
  540. Routine Description:
  541. NOT IMPLEMENTED - Prepare for restore
  542. Arguments:
  543. None.
  544. Return Value:
  545. None.
  546. --*/
  547. {
  548. #undef DEBSUB
  549. #define DEBSUB "SERVER_FrsPrepareForRestore:"
  550. return ERROR_CALL_NOT_IMPLEMENTED;
  551. }
  552. DWORD
  553. SERVER_FrsRestoreComplete(
  554. handle_t Handle
  555. )
  556. /*++
  557. Routine Description:
  558. NOT IMPLEMENTED - restore is complete; reset state
  559. Arguments:
  560. None.
  561. Return Value:
  562. None.
  563. --*/
  564. {
  565. #undef DEBSUB
  566. #define DEBSUB "SERVER_FrsRestoreComplete:"
  567. return ERROR_CALL_NOT_IMPLEMENTED;
  568. }
  569. DWORD
  570. FrsRpcAccessChecks(
  571. IN HANDLE ServerHandle,
  572. IN DWORD RpcApiIndex
  573. )
  574. /*++
  575. Routine Description:
  576. Check if the caller has access to this rpc api call.
  577. Arguments:
  578. ServerHandle - From the rpc runtime
  579. RpcApiIndex - identifies key in registry
  580. Return Value:
  581. Win32 Status
  582. --*/
  583. {
  584. #undef DEBSUB
  585. #define DEBSUB "FrsRpcAccessChecks:"
  586. DWORD WStatus;
  587. PWCHAR WStr = NULL, TrimStr;
  588. FRS_REG_KEY_CODE EnableKey, RightsKey;
  589. DWORD ValueSize;
  590. BOOL RequireRead;
  591. BOOL Impersonated = FALSE;
  592. HKEY HRpcApiKey = INVALID_HANDLE_VALUE;
  593. PWCHAR ApiName;
  594. WCHAR ValueBuf[MAX_PATH + 1];
  595. if (RpcApiIndex >= ACX_MAX) {
  596. DPRINT1(0, "++ ERROR - ApiIndex out of range. (%d)\n", RpcApiIndex);
  597. FRS_ASSERT(!"RpcApiIndexout of range");
  598. return ERROR_INVALID_PARAMETER;
  599. }
  600. EnableKey = RpcApiKeys[RpcApiIndex].Enable;
  601. RightsKey = RpcApiKeys[RpcApiIndex].Rights;
  602. ApiName = RpcApiKeys[RpcApiIndex].KeyName;
  603. //
  604. // First go fetch the enable/disable string.
  605. //
  606. WStatus = CfgRegReadString(EnableKey, NULL, 0, &WStr);
  607. if (WStr == NULL) {
  608. DPRINT1_WS(0, "++ ERROR - API Access enable check for API (%ws) failed.", ApiName, WStatus);
  609. WStatus = ERROR_NO_TOKEN;
  610. goto CLEANUP;
  611. }
  612. //
  613. // If access checks are disabled then we're done.
  614. //
  615. TrimStr = FrsWcsTrim(WStr, L' ');
  616. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DISABLED) ||
  617. WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)) {
  618. WStatus = ERROR_SUCCESS;
  619. goto CLEANUP;
  620. }
  621. if (WSTR_NE(TrimStr, ACCESS_CHECKS_ARE_ENABLED) &&
  622. WSTR_NE(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_ENABLED)) {
  623. DPRINT2(0, "++ ERROR - Invalid parameter API Access enable check for API (%ws) :%ws\n",
  624. ApiName, TrimStr );
  625. WStatus = ERROR_CANTREAD;
  626. goto CLEANUP;
  627. }
  628. //
  629. // Fetch the access rights string that tells us if we need to check for
  630. // read or write access.
  631. //
  632. WStr = FrsFree(WStr);
  633. WStatus = CfgRegReadString(RightsKey, NULL, 0, &WStr);
  634. if (WStr == NULL) {
  635. DPRINT1_WS(0, "++ ERROR - API Access rights check for API (%ws) failed.", ApiName, WStatus);
  636. WStatus = ERROR_NO_TOKEN;
  637. goto CLEANUP;
  638. }
  639. TrimStr = FrsWcsTrim(WStr, L' ');
  640. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_READ) ||
  641. WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_DEFAULT_READ)) {
  642. RequireRead = TRUE;
  643. } else
  644. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_WRITE) ||
  645. WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE)) {
  646. RequireRead = FALSE;
  647. } else {
  648. DPRINT2(0, "++ ERROR - Invalid parameter API Access rights check for API (%ws) :%ws\n",
  649. ApiName, TrimStr );
  650. WStatus = ERROR_CANTREAD;
  651. goto CLEANUP;
  652. }
  653. //
  654. // Impersonate the caller
  655. //
  656. if (ServerHandle != NULL) {
  657. WStatus = RpcImpersonateClient(ServerHandle);
  658. CLEANUP1_WS(0, "++ ERROR - Can't impersonate caller for API Access check for API (%ws).",
  659. ApiName, WStatus, CLEANUP);
  660. Impersonated = TRUE;
  661. }
  662. //
  663. // Open the key, with the selected access so the system can check if the
  664. // ACL on the key (presumably set by the admin) gives this user sufficient
  665. // rights. If the test succeeds then we allow API call to proceed.
  666. //
  667. WStatus = CfgRegOpenKey(RightsKey,
  668. NULL,
  669. (RequireRead) ? FRS_RKF_KEY_ACCCHK_READ :
  670. FRS_RKF_KEY_ACCCHK_WRITE,
  671. &HRpcApiKey);
  672. CLEANUP2_WS(0, "++ ERROR - API Access check failed for API (%ws) :%ws",
  673. ApiName, TrimStr, WStatus, CLEANUP);
  674. //
  675. // Access is allowed.
  676. //
  677. DPRINT2(4, "++ Access Check Okay: %s access for API (%ws)\n",
  678. (RequireRead) ? "read" : "write", ApiName);
  679. WStatus = ERROR_SUCCESS;
  680. CLEANUP:
  681. FRS_REG_CLOSE(HRpcApiKey);
  682. //
  683. // Access checks failed, register event
  684. //
  685. if (!WIN_SUCCESS(WStatus)) {
  686. WStatus = FRS_ERR_INSUFFICIENT_PRIV;
  687. //
  688. // Include user name if impersonation succeeded
  689. //
  690. if (Impersonated) {
  691. ValueSize = MAX_PATH;
  692. if (GetUserName(ValueBuf, &ValueSize)) {
  693. EPRINT3(EVENT_FRS_ACCESS_CHECKS_FAILED_USER,
  694. ApiName, ACCESS_CHECKS_ARE, ValueBuf);
  695. } else {
  696. EPRINT2(EVENT_FRS_ACCESS_CHECKS_FAILED_UNKNOWN,
  697. ApiName, ACCESS_CHECKS_ARE);
  698. }
  699. } else {
  700. EPRINT2(EVENT_FRS_ACCESS_CHECKS_FAILED_UNKNOWN,
  701. ApiName, ACCESS_CHECKS_ARE);
  702. }
  703. }
  704. if (Impersonated) {
  705. RpcRevertToSelf();
  706. }
  707. FrsFree(WStr);
  708. return WStatus;
  709. }
  710. DWORD
  711. CheckAuth(
  712. IN HANDLE ServerHandle
  713. )
  714. /*++
  715. Routine Description:
  716. Check if the caller has the correct authentication
  717. Arguments:
  718. ServerHandle
  719. Return Value:
  720. Win32 Status
  721. --*/
  722. {
  723. #undef DEBSUB
  724. #define DEBSUB "CheckAuth:"
  725. DWORD WStatus;
  726. DWORD AuthLevel;
  727. DWORD AuthN;
  728. WStatus = RpcBindingInqAuthClient(ServerHandle, NULL, NULL, &AuthLevel,
  729. &AuthN, NULL);
  730. if (!WIN_SUCCESS(WStatus)) {
  731. DPRINT_WS(0, "++ ERROR - RpcBindingInqAuthClient", WStatus);
  732. return WStatus;
  733. }
  734. //
  735. // Encrypted packet
  736. //
  737. if (AuthLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) {
  738. DPRINT1(4, "++ Authlevel is %d; not RPC_C_AUTHN_LEVEL_PKT_PRIVACE\n", AuthLevel);
  739. return ERROR_NOT_AUTHENTICATED;
  740. }
  741. #ifdef DS_FREE
  742. DPRINT1(4, "++ AuthN is %d; Allowed in DS_FREE mode.\n", AuthN);
  743. #else DS_FREE
  744. //
  745. // KERBEROS
  746. //
  747. if (AuthN != RPC_C_AUTHN_GSS_KERBEROS &&
  748. AuthN != RPC_C_AUTHN_GSS_NEGOTIATE) {
  749. DPRINT1(4, "++ AuthN is %d; not RPC_C_AUTHN_GSS_KERBEROS/NEGOTIATE\n", AuthN);
  750. return ERROR_NOT_AUTHENTICATED;
  751. }
  752. #endif DS_FREE
  753. //
  754. // SUCCESS; RPC is authenticated, encrypted kerberos
  755. //
  756. return ERROR_SUCCESS;
  757. }
  758. DWORD
  759. CheckAuthForLocalRpc(
  760. IN HANDLE ServerHandle
  761. )
  762. /*++
  763. Routine Description:
  764. Check if the caller has the correct authentication.
  765. Make sure the caller is coming over local RPC.
  766. Allow NTLM since Local RPCs use NTLM.
  767. Arguments:
  768. ServerHandle
  769. Return Value:
  770. Win32 Status
  771. --*/
  772. {
  773. #undef DEBSUB
  774. #define DEBSUB "CheckAuthForLocalRpc:"
  775. DWORD WStatus;
  776. DWORD AuthLevel;
  777. DWORD AuthN;
  778. PWCHAR BindingString = NULL;
  779. PWCHAR ProtocolSequence = NULL;
  780. //
  781. // Make sure that the caller is calling over LRPC. We do this by
  782. // determining the protocol sequence used from the string binding.
  783. //
  784. WStatus = RpcBindingToStringBinding(ServerHandle, &BindingString);
  785. CLEANUP_WS(0, "++ ERROR - RpcBindingToStringBinding", WStatus, CLEANUP);
  786. WStatus = RpcStringBindingParse(BindingString,
  787. NULL,
  788. &ProtocolSequence,
  789. NULL,
  790. NULL,
  791. NULL);
  792. CLEANUP_WS(0, "++ ERROR - RpcStringBindingParse", WStatus, CLEANUP);
  793. if ((ProtocolSequence == NULL) || (_wcsicmp(ProtocolSequence, L"ncalrpc") != 0)) {
  794. WStatus = ERROR_NOT_AUTHENTICATED;
  795. CLEANUP_WS(0, "++ ERROR - Illegal protocol sequence.", WStatus, CLEANUP);
  796. }
  797. WStatus = RpcBindingInqAuthClient(ServerHandle, NULL, NULL, &AuthLevel,
  798. &AuthN, NULL);
  799. CLEANUP_WS(0, "++ ERROR - RpcBindingInqAuthClient", WStatus, CLEANUP);
  800. //
  801. // Encrypted packet
  802. //
  803. if (AuthLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) {
  804. WStatus = ERROR_NOT_AUTHENTICATED;
  805. CLEANUP1_WS(4, "++ Authlevel is %d; not RPC_C_AUTHN_LEVEL_PKT_PRIVACE", AuthLevel, WStatus, CLEANUP);
  806. }
  807. #ifdef DS_FREE
  808. DPRINT1(4, "++ AuthN is %d; Allowed in DS_FREE mode.\n", AuthN);
  809. #else DS_FREE
  810. //
  811. // KERBEROS or NTLM
  812. //
  813. if ((AuthN != RPC_C_AUTHN_GSS_KERBEROS) &&
  814. (AuthN != RPC_C_AUTHN_GSS_NEGOTIATE) &&
  815. (AuthN != RPC_C_AUTHN_WINNT)) {
  816. WStatus = ERROR_NOT_AUTHENTICATED;
  817. CLEANUP1_WS(4, "++ AuthN is %d; not RPC_C_AUTHN_GSS_KERBEROS/NEGOTIATE/NTLM", AuthN, WStatus, CLEANUP);
  818. }
  819. #endif DS_FREE
  820. //
  821. // SUCCESS; RPC is local, authenticated, encrypted kerberos or NTLM
  822. //
  823. WStatus = ERROR_SUCCESS;
  824. CLEANUP:
  825. if (BindingString) {
  826. RpcStringFree(&BindingString);
  827. }
  828. if (ProtocolSequence) {
  829. RpcStringFree(&ProtocolSequence);
  830. }
  831. return WStatus;
  832. }
  833. DWORD
  834. CheckAuthForInfoAPIs(
  835. IN HANDLE ServerHandle
  836. )
  837. /*++
  838. Routine Description:
  839. Check if the caller has the correct authentication.
  840. Allow NTLM.
  841. Arguments:
  842. ServerHandle
  843. Return Value:
  844. Win32 Status
  845. --*/
  846. {
  847. #undef DEBSUB
  848. #define DEBSUB "CheckAuthForInfoAPIs:"
  849. DWORD WStatus;
  850. DWORD AuthLevel;
  851. DWORD AuthN;
  852. WStatus = RpcBindingInqAuthClient(ServerHandle, NULL, NULL, &AuthLevel,
  853. &AuthN, NULL);
  854. if (!WIN_SUCCESS(WStatus)) {
  855. DPRINT_WS(0, "++ ERROR - RpcBindingInqAuthClient", WStatus);
  856. return WStatus;
  857. }
  858. //
  859. // Encrypted packet
  860. //
  861. if (AuthLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) {
  862. DPRINT1(4, "++ Authlevel is %d; not RPC_C_AUTHN_LEVEL_PKT_PRIVACE\n", AuthLevel);
  863. return ERROR_NOT_AUTHENTICATED;
  864. }
  865. #ifdef DS_FREE
  866. DPRINT1(4, "++ AuthN is %d; Allowed in DS_FREE mode.\n", AuthN);
  867. #else DS_FREE
  868. //
  869. // KERBEROS or NTLM
  870. //
  871. if ((AuthN != RPC_C_AUTHN_GSS_KERBEROS) &&
  872. (AuthN != RPC_C_AUTHN_GSS_NEGOTIATE) &&
  873. (AuthN != RPC_C_AUTHN_WINNT)) {
  874. DPRINT1(4, "++ AuthN is %d; not RPC_C_AUTHN_GSS_KERBEROS/NEGOTIATE/NTLM\n", AuthN);
  875. return ERROR_NOT_AUTHENTICATED;
  876. }
  877. #endif DS_FREE
  878. //
  879. // SUCCESS; RPC is authenticated, encrypted kerberos
  880. //
  881. return ERROR_SUCCESS;
  882. }
  883. DWORD
  884. NtFrsApi_Rpc_Bind(
  885. IN PWCHAR MachineName,
  886. OUT PWCHAR *OutPrincName,
  887. OUT handle_t *OutHandle,
  888. OUT ULONG *OutParentAuthLevel
  889. )
  890. /*++
  891. Routine Description:
  892. Bind to the NtFrs service on MachineName (this machine if NULL)
  893. using an unauthencated, un-encrypted binding.
  894. Arguments:
  895. MachineName - Bind to the service on this computer. The computer
  896. name can be any RPC-bindable name. Usually, the
  897. NetBIOS or DNS name works just fine. The NetBIOS
  898. name can be found with GetComputerName() or
  899. hostname. The DNS name can be found with
  900. gethostbyname() or ipconfig /all. If NULL, the
  901. service on this computer is contacted. The service
  902. is contacted using Secure RPC.
  903. OutPrincName - Principle name for MachineName
  904. OutHandle - Bound, resolved, authenticated handle
  905. OutParentAuthLevel - Authentication type and level
  906. (Always CXTION_AUTH_NONE)
  907. Return Value:
  908. Win32 Status
  909. --*/
  910. {
  911. #undef DEBSUB
  912. #define DEBSUB "NtFrsApi_Rpc_Bind:"
  913. DWORD WStatus, WStatus1;
  914. handle_t Handle = NULL;
  915. PWCHAR BindingString = NULL;
  916. try {
  917. //
  918. // Return value
  919. //
  920. *OutHandle = NULL;
  921. *OutPrincName = NULL;
  922. *OutParentAuthLevel = CXTION_AUTH_NONE;
  923. //
  924. // Create a binding string to NtFrs on some machine. Trim leading \\
  925. //
  926. FRS_TRIM_LEADING_2SLASH(MachineName);
  927. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  928. NULL, NULL, &BindingString);
  929. CLEANUP1_WS(0, "++ ERROR - Composing binding to %ws;",
  930. MachineName, WStatus, CLEANUP);
  931. //
  932. // Store the binding in the handle
  933. //
  934. WStatus = RpcBindingFromStringBinding(BindingString, &Handle);
  935. CLEANUP1_WS(0, "++ ERROR - From binding for %ws;", MachineName, WStatus, CLEANUP);
  936. //
  937. // Resolve the binding to the dynamic endpoint
  938. //
  939. WStatus = RpcEpResolveBinding(Handle, frsrpc_ClientIfHandle);
  940. CLEANUP1_WS(0, "++ ERROR - Resolving binding for %ws;",
  941. MachineName, WStatus, CLEANUP);
  942. //
  943. // SUCCESS
  944. //
  945. *OutHandle = Handle;
  946. *OutPrincName = FrsWcsDup(MachineName);
  947. Handle = NULL;
  948. WStatus = ERROR_SUCCESS;
  949. DPRINT3(4, "++ NtFrsApi Bound to %ws (PrincName: %ws) Auth %d\n",
  950. MachineName, *OutPrincName, *OutParentAuthLevel);
  951. CLEANUP:;
  952. } except (EXCEPTION_EXECUTE_HANDLER) {
  953. //
  954. // Exception (may be RPC)
  955. //
  956. GET_EXCEPTION_CODE(WStatus);
  957. DPRINT_WS(0, "++ ERROR - Exception -", WStatus);
  958. }
  959. //
  960. // Clean up any handles, events, memory, ...
  961. //
  962. try {
  963. if (BindingString) {
  964. WStatus1 = RpcStringFreeW(&BindingString);
  965. DPRINT_WS(0, "++ WARN - RpcStringFreeW;", WStatus1);
  966. }
  967. if (Handle) {
  968. WStatus1 = RpcBindingFree(&Handle);
  969. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus1);
  970. }
  971. } except (EXCEPTION_EXECUTE_HANDLER) {
  972. //
  973. // Exception (may be RPC)
  974. //
  975. GET_EXCEPTION_CODE(WStatus);
  976. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  977. }
  978. return WStatus;
  979. }
  980. DWORD
  981. NtFrsApi_Rpc_BindEx(
  982. IN PWCHAR MachineName,
  983. OUT PWCHAR *OutPrincName,
  984. OUT handle_t *OutHandle,
  985. OUT ULONG *OutParentAuthLevel
  986. )
  987. /*++
  988. Routine Description:
  989. Bind to the NtFrs service on MachineName (this machine if NULL)
  990. using an authenticated, encrypted binding.
  991. Arguments:
  992. MachineName - Bind to the service on this computer. The computer
  993. name can be any RPC-bindable name. Usually, the
  994. NetBIOS or DNS name works just fine. The NetBIOS
  995. name can be found with GetComputerName() or
  996. hostname. The DNS name can be found with
  997. gethostbyname() or ipconfig /all. If NULL, the
  998. service on this computer is contacted. The service
  999. is contacted using Secure RPC.
  1000. OutPrincName - Principle name for MachineName
  1001. OutHandle - Bound, resolved, authenticated handle
  1002. OutParentAuthLevel - Authentication type and level
  1003. (Always CXTION_AUTH_KERBEROS_FULL)
  1004. Return Value:
  1005. Win32 Status
  1006. --*/
  1007. {
  1008. #undef DEBSUB
  1009. #define DEBSUB "NtFrsApi_Rpc_BindEx:"
  1010. DWORD WStatus, WStatus1;
  1011. PWCHAR InqPrincName = NULL;
  1012. handle_t Handle = NULL;
  1013. PWCHAR PrincName = NULL;
  1014. PWCHAR BindingString = NULL;
  1015. try {
  1016. //
  1017. // Return value
  1018. //
  1019. *OutHandle = NULL;
  1020. *OutPrincName = NULL;
  1021. *OutParentAuthLevel = CXTION_AUTH_KERBEROS_FULL;
  1022. //
  1023. // Create a binding string to NtFrs on some machine. Trim leading \\
  1024. //
  1025. FRS_TRIM_LEADING_2SLASH(MachineName);
  1026. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  1027. NULL, NULL, &BindingString);
  1028. CLEANUP1_WS(0, "++ ERROR - Composing binding to %ws;",
  1029. MachineName, WStatus, CLEANUP);
  1030. //
  1031. // Store the binding in the handle
  1032. //
  1033. WStatus = RpcBindingFromStringBinding(BindingString, &Handle);
  1034. CLEANUP1_WS(0, "++ ERROR - From binding for %ws;", MachineName, WStatus, CLEANUP);
  1035. //
  1036. // Resolve the binding to the dynamic endpoint
  1037. //
  1038. WStatus = RpcEpResolveBinding(Handle, frsrpc_ClientIfHandle);
  1039. CLEANUP1_WS(0, "++ ERROR - Resolving binding for %ws;",
  1040. MachineName, WStatus, CLEANUP);
  1041. //
  1042. // Find the principle name
  1043. //
  1044. WStatus = RpcMgmtInqServerPrincName(Handle,
  1045. RPC_C_AUTHN_GSS_NEGOTIATE,
  1046. &InqPrincName);
  1047. CLEANUP1_WS(0, "++ ERROR - Inq PrincName for %ws;", MachineName, WStatus, CLEANUP);
  1048. PrincName = FrsWcsDup(InqPrincName);
  1049. RpcStringFree(&InqPrincName);
  1050. InqPrincName = NULL;
  1051. //
  1052. // Set authentication info
  1053. //
  1054. if (MutualAuthenticationIsEnabled || MutualAuthenticationIsEnabledAndRequired) {
  1055. WStatus = RpcBindingSetAuthInfoEx(Handle,
  1056. PrincName,
  1057. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  1058. RPC_C_AUTHN_GSS_NEGOTIATE,
  1059. NULL,
  1060. RPC_C_AUTHZ_NONE,
  1061. &RpcSecurityQos);
  1062. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  1063. MachineName, PrincName, WStatus);
  1064. } else {
  1065. WStatus = ERROR_NOT_SUPPORTED;
  1066. }
  1067. //
  1068. // Fall back to manual mutual authentication
  1069. //
  1070. if (!MutualAuthenticationIsEnabledAndRequired && !WIN_SUCCESS(WStatus)) {
  1071. WStatus = RpcBindingSetAuthInfo(Handle,
  1072. PrincName,
  1073. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  1074. RPC_C_AUTHN_GSS_NEGOTIATE,
  1075. NULL,
  1076. RPC_C_AUTHZ_NONE);
  1077. }
  1078. CLEANUP1_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws);",
  1079. MachineName, WStatus, CLEANUP);
  1080. //
  1081. // SUCCESS
  1082. //
  1083. *OutHandle = Handle;
  1084. *OutPrincName = PrincName;
  1085. Handle = NULL;
  1086. PrincName = NULL;
  1087. WStatus = ERROR_SUCCESS;
  1088. DPRINT3(4, "++ NtFrsApi Bound to %ws (PrincName: %ws) Auth %d\n",
  1089. MachineName, *OutPrincName, *OutParentAuthLevel);
  1090. CLEANUP:;
  1091. } except (EXCEPTION_EXECUTE_HANDLER) {
  1092. //
  1093. // Exception (may be RPC)
  1094. //
  1095. GET_EXCEPTION_CODE(WStatus);
  1096. DPRINT_WS(0, "++ Error - Exception.", WStatus);
  1097. }
  1098. //
  1099. // Clean up any handles, events, memory, ...
  1100. //
  1101. try {
  1102. if (BindingString) {
  1103. WStatus1 = RpcStringFreeW(&BindingString);
  1104. DPRINT_WS(0, "++ WARN - RpcStringFreeW;", WStatus1);
  1105. }
  1106. if (PrincName) {
  1107. PrincName = FrsFree(PrincName);
  1108. }
  1109. if (Handle) {
  1110. WStatus1 = RpcBindingFree(&Handle);
  1111. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus1);
  1112. }
  1113. } except (EXCEPTION_EXECUTE_HANDLER) {
  1114. //
  1115. // Exception (may be RPC)
  1116. //
  1117. GET_EXCEPTION_CODE(WStatus);
  1118. DPRINT_WS(0, "++ Error - Cleanup Exception.", WStatus);
  1119. }
  1120. return WStatus;
  1121. }
  1122. GUID DummyGuid;
  1123. BOOL CommitDemotionInProgress;
  1124. DWORD
  1125. NtFrsApi_Rpc_StartDemotionW(
  1126. IN handle_t Handle,
  1127. IN PWCHAR ReplicaSetName
  1128. )
  1129. /*++
  1130. Routine Description:
  1131. Start demoting the sysvol. Basically, tombstone the replica set.
  1132. Arguments:
  1133. Handle
  1134. ReplicaSetName - Replica set name
  1135. Return Value:
  1136. Win32 Status
  1137. --*/
  1138. {
  1139. #undef DEBSUB
  1140. #define DEBSUB "NtFrsApi_Rpc_StartDemotionW:"
  1141. DWORD WStatus;
  1142. PWCHAR SysVolName;
  1143. BOOL UnLockGenTable = FALSE;
  1144. BOOL DeleteFromGenTable = FALSE;
  1145. try {
  1146. //
  1147. // Checkauthentication if the auth check is not disabled
  1148. // by setting the registry value:
  1149. // Access checks are [Enabled or Disabled]
  1150. // Each API has a different registry location so this
  1151. // can not be put in the rpc callback function.
  1152. //
  1153. WStatus = FrsRpcCheckAuthIfEnabled(Handle, ACX_DCPROMO);
  1154. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1155. WStatus, CLEANUP);
  1156. //
  1157. // Check if the caller has access.
  1158. //
  1159. WStatus = FrsRpcAccessChecks(Handle, ACX_DCPROMO);
  1160. CLEANUP_WS(0, "++ ERROR - FrsRpcAccessChecks failed;",
  1161. WStatus, CLEANUP);
  1162. //
  1163. // Check parameters
  1164. //
  1165. if (ReplicaSetName == NULL) {
  1166. DPRINT(0, "++ ERROR - Parameter is NULL\n");
  1167. WStatus = FRS_ERR_INVALID_SERVICE_PARAMETER;
  1168. goto CLEANUP;
  1169. }
  1170. //
  1171. // Display params
  1172. //
  1173. DPRINT1(0, ":S: Start Demotion: %ws\n", ReplicaSetName);
  1174. //
  1175. // Can't promote/demote the same sysvol at the same time!
  1176. //
  1177. UnLockGenTable = TRUE;
  1178. GTabLockTable(SysVolsBeingCreated);
  1179. SysVolName = GTabLookupNoLock(SysVolsBeingCreated, &DummyGuid, ReplicaSetName);
  1180. if (SysVolName) {
  1181. DPRINT1(0, "++ ERROR - Promoting/Demoting %ws twice\n", ReplicaSetName);
  1182. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  1183. goto CLEANUP;
  1184. }
  1185. if (CommitDemotionInProgress) {
  1186. DPRINT(0, "++ ERROR - Commit demotion in progress.\n");
  1187. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  1188. goto CLEANUP;
  1189. }
  1190. DeleteFromGenTable = TRUE;
  1191. GTabInsertEntryNoLock(SysVolsBeingCreated,
  1192. ReplicaSetName,
  1193. &DummyGuid,
  1194. ReplicaSetName);
  1195. UnLockGenTable = FALSE;
  1196. GTabUnLockTable(SysVolsBeingCreated);
  1197. //
  1198. // Delete the replica set
  1199. //
  1200. WStatus = FrsDsStartDemotion(ReplicaSetName);
  1201. if (!WIN_SUCCESS(WStatus)) {
  1202. DPRINT_WS(0, "++ ERROR - demoting;", WStatus);
  1203. WStatus = FRS_ERR_SYSVOL_DEMOTE;
  1204. goto CLEANUP;
  1205. }
  1206. //
  1207. // SUCCESS
  1208. //
  1209. WStatus = ERROR_SUCCESS;
  1210. DPRINT2(0, ":S: Success demoting %ws from %ws\n", ReplicaSetName, ComputerName);
  1211. CLEANUP:;
  1212. } except (EXCEPTION_EXECUTE_HANDLER) {
  1213. //
  1214. // Exception (may be RPC)
  1215. //
  1216. GET_EXCEPTION_CODE(WStatus);
  1217. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1218. }
  1219. try {
  1220. if (UnLockGenTable) {
  1221. GTabUnLockTable(SysVolsBeingCreated);
  1222. }
  1223. if (DeleteFromGenTable) {
  1224. GTabDelete(SysVolsBeingCreated, &DummyGuid, ReplicaSetName, NULL);
  1225. }
  1226. } except (EXCEPTION_EXECUTE_HANDLER) {
  1227. GET_EXCEPTION_CODE(WStatus);
  1228. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1229. }
  1230. return WStatus;
  1231. }
  1232. DWORD
  1233. NtFrsApi_Rpc_CommitDemotionW(
  1234. IN handle_t Handle
  1235. )
  1236. /*++
  1237. Routine Description:
  1238. The sysvols have been demoted. Mark them as "do not animate."
  1239. Arguments:
  1240. Handle
  1241. Return Value:
  1242. Win32 Status
  1243. --*/
  1244. {
  1245. #undef DEBSUB
  1246. #define DEBSUB "NtFrsApi_Rpc_CommitDemotionW:"
  1247. DWORD WStatus;
  1248. PWCHAR SysVolName;
  1249. PVOID Key;
  1250. BOOL UnLockGenTable = FALSE;
  1251. try {
  1252. //
  1253. // Display params
  1254. //
  1255. DPRINT(0, ":S: Commit Demotion:\n");
  1256. //
  1257. // Checkauthentication if the auth check is not disabled
  1258. // by setting the registry value:
  1259. // Access checks are [Enabled or Disabled]
  1260. // Each API has a different registry location so this
  1261. // can not be put in the rpc callback function.
  1262. //
  1263. WStatus = FrsRpcCheckAuthIfEnabledForCommitDemotion(Handle, ACX_DCPROMO);
  1264. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1265. WStatus, CLEANUP);
  1266. WStatus = FrsRpcAccessChecks(Handle, ACX_DCPROMO);
  1267. CLEANUP_WS(0, "++ ERROR - FrsRpcAccessChecks();", WStatus, CLEANUP);
  1268. //
  1269. // Can't promote/demote the same sysvol at the same time!
  1270. //
  1271. Key = NULL;
  1272. UnLockGenTable = TRUE;
  1273. GTabLockTable(SysVolsBeingCreated);
  1274. SysVolName = GTabNextDatumNoLock(SysVolsBeingCreated, &Key);
  1275. if (SysVolName) {
  1276. DPRINT(0, "++ ERROR - Promoting/Demoting during commit\n");
  1277. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  1278. goto CLEANUP;
  1279. }
  1280. CommitDemotionInProgress = TRUE;
  1281. UnLockGenTable = FALSE;
  1282. GTabUnLockTable(SysVolsBeingCreated);
  1283. //
  1284. // Create the replica set
  1285. //
  1286. WStatus = FrsDsCommitDemotion();
  1287. if (!WIN_SUCCESS(WStatus)) {
  1288. DPRINT_WS(0, "++ ERROR - Commit demotion;", WStatus);
  1289. WStatus = FRS_ERR_SYSVOL_DEMOTE;
  1290. goto CLEANUP;
  1291. }
  1292. //
  1293. // SUCCESS
  1294. //
  1295. WStatus = ERROR_SUCCESS;
  1296. DPRINT1(0, ":S: Success commit demotion on %ws.\n", ComputerName);
  1297. CLEANUP:;
  1298. } except (EXCEPTION_EXECUTE_HANDLER) {
  1299. //
  1300. // Exception (may be RPC)
  1301. //
  1302. GET_EXCEPTION_CODE(WStatus);
  1303. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1304. }
  1305. try {
  1306. CommitDemotionInProgress = FALSE;
  1307. if (UnLockGenTable) {
  1308. GTabUnLockTable(SysVolsBeingCreated);
  1309. }
  1310. } except (EXCEPTION_EXECUTE_HANDLER) {
  1311. //
  1312. // Exception (may be RPC)
  1313. //
  1314. GET_EXCEPTION_CODE(WStatus);
  1315. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1316. }
  1317. return WStatus;
  1318. }
  1319. DWORD
  1320. SERVER_FrsRpcVerifyPromotionParent(
  1321. IN handle_t Handle,
  1322. IN PWCHAR ParentAccount,
  1323. IN PWCHAR ParentPassword,
  1324. IN PWCHAR ReplicaSetName,
  1325. IN PWCHAR ReplicaSetType,
  1326. IN ULONG ParentAuthLevel,
  1327. IN ULONG GuidSize
  1328. )
  1329. /*++
  1330. Routine Description:
  1331. OBSOLETE API
  1332. Verify the account on the parent computer. The parent computer
  1333. supplies the initial copy of the indicated sysvol.
  1334. Arguments:
  1335. Handle
  1336. ParentAccount - Valid account on ParentComputer
  1337. ParentPassword - Valid password for ParentAccount
  1338. ReplicaSetName - Replica set name
  1339. ReplicaSetType - Replica set type
  1340. ParentAuthLevel - Authentication type and level
  1341. GuidSize - sizeof(GUID)
  1342. Return Value:
  1343. Win32 Status
  1344. --*/
  1345. {
  1346. #undef DEBSUB
  1347. #define DEBSUB "SERVER_FrsRpcVerifyPromotionParent:"
  1348. return ERROR_CALL_NOT_IMPLEMENTED;
  1349. }
  1350. DWORD
  1351. SERVER_FrsRpcVerifyPromotionParentEx(
  1352. IN handle_t Handle,
  1353. IN PWCHAR ParentAccount,
  1354. IN PWCHAR ParentPassword,
  1355. IN PWCHAR ReplicaSetName,
  1356. IN PWCHAR ReplicaSetType,
  1357. IN PWCHAR CxtionName,
  1358. IN PWCHAR PartnerName,
  1359. IN PWCHAR PartnerPrincName,
  1360. IN PWCHAR ParentPrincName,
  1361. IN ULONG PartnerAuthLevel,
  1362. IN ULONG GuidSize
  1363. )
  1364. /*++
  1365. Routine Description:
  1366. OBSOLETE API
  1367. Verify as much of the comm paths and parameters as possible so
  1368. that dcpromo fails early.
  1369. Arguments:
  1370. Handle
  1371. ParentAccount - Valid account on ParentComputer
  1372. ParentPassword - Valid password for ParentAccount
  1373. ReplicaSetName - Replica set name
  1374. ReplicaSetType - Replica set type
  1375. CxtionName - printable name for cxtion
  1376. PartnerName - RPC bindable name
  1377. PartnerPrincName - Server principle name for kerberos
  1378. ParentPrincName - Principle name used to bind to this computer
  1379. PartnerAuthLevel - Authentication type and level
  1380. GuidSize - sizeof array addressed by Guid
  1381. Return Value:
  1382. Win32 Status
  1383. --*/
  1384. {
  1385. #undef DEBSUB
  1386. #define DEBSUB "SERVER_FrsRpcVerifyPromotionParentEx:"
  1387. return ERROR_CALL_NOT_IMPLEMENTED;
  1388. }
  1389. DWORD
  1390. LOCAL_FrsRpcVerifyPromotionParent(
  1391. IN PWCHAR ReplicaSetName,
  1392. IN PWCHAR ReplicaSetType,
  1393. IN ULONG GuidSize
  1394. )
  1395. /*++
  1396. Routine Description:
  1397. Verify the account on the parent computer. The parent computer
  1398. supplies the initial copy of the indicated sysvol.
  1399. Arguments:
  1400. ReplicaSetName - Replica set name
  1401. ReplicaSetType - Replica set type
  1402. GuidSize - sizeof(GUID)
  1403. Return Value:
  1404. Win32 Status
  1405. --*/
  1406. {
  1407. #undef DEBSUB
  1408. #define DEBSUB "LOCAL_FrsRpcVerifyPromotionParent:"
  1409. DWORD WStatus;
  1410. try {
  1411. //
  1412. // Display params
  1413. //
  1414. DPRINT(0, ":S: SERVER Verify Promotion Parent:\n");
  1415. DPRINT1(0, ":S: \tSetName : %ws\n", ReplicaSetName);
  1416. DPRINT1(0, ":S: \tSetType : %ws\n", ReplicaSetType);
  1417. //
  1418. // Guid
  1419. //
  1420. if (GuidSize != sizeof(GUID)) {
  1421. DPRINT3(0, "++ ERROR - %ws: GuidSize is %d, not %d\n",
  1422. ReplicaSetName, GuidSize, sizeof(GUID));
  1423. goto ERR_INVALID_SERVICE_PARAMETER;
  1424. }
  1425. //
  1426. // Check parameters
  1427. //
  1428. if (!ReplicaSetName || !ReplicaSetType) {
  1429. DPRINT(0, "++ ERROR - Parameter is NULL\n");
  1430. goto ERR_INVALID_SERVICE_PARAMETER;
  1431. }
  1432. if (_wcsicmp(ReplicaSetType, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
  1433. _wcsicmp(ReplicaSetType, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
  1434. DPRINT1(0, "++ ERROR - ReplicaSetType is %ws\n", ReplicaSetType);
  1435. goto ERR_INVALID_SERVICE_PARAMETER;
  1436. }
  1437. //
  1438. // Verify the replica set
  1439. //
  1440. WStatus = FrsDsVerifyPromotionParent(ReplicaSetName, ReplicaSetType);
  1441. CLEANUP2_WS(0, "++ ERROR - verifying set %ws on parent %ws;",
  1442. ReplicaSetName, ComputerName, WStatus, ERR_SYSVOL_POPULATE);
  1443. //
  1444. // SUCCESS
  1445. //
  1446. DPRINT2(0, ":S: Success Verifying promotion parent %ws %ws\n",
  1447. ReplicaSetName, ReplicaSetType);
  1448. WStatus = ERROR_SUCCESS;
  1449. goto CLEANUP;
  1450. ERR_INVALID_SERVICE_PARAMETER:
  1451. WStatus = FRS_ERR_INVALID_SERVICE_PARAMETER;
  1452. goto CLEANUP;
  1453. ERR_SYSVOL_POPULATE:
  1454. WStatus = FRS_ERR_SYSVOL_POPULATE;
  1455. CLEANUP:;
  1456. } except (EXCEPTION_EXECUTE_HANDLER) {
  1457. //
  1458. // Exception (may be RPC)
  1459. //
  1460. GET_EXCEPTION_CODE(WStatus);
  1461. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1462. }
  1463. return WStatus;
  1464. }
  1465. DWORD
  1466. SERVER_FrsRpcStartPromotionParent(
  1467. IN handle_t Handle,
  1468. IN PWCHAR ParentAccount,
  1469. IN PWCHAR ParentPassword,
  1470. IN PWCHAR ReplicaSetName,
  1471. IN PWCHAR ReplicaSetType,
  1472. IN PWCHAR CxtionName,
  1473. IN PWCHAR PartnerName,
  1474. IN PWCHAR PartnerPrincName,
  1475. IN ULONG PartnerAuthLevel,
  1476. IN ULONG GuidSize,
  1477. IN UCHAR *CxtionGuid,
  1478. IN UCHAR *PartnerGuid,
  1479. OUT UCHAR *ParentGuid
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. Setup a volatile cxtion on the parent for seeding the indicated
  1484. sysvol on the caller.
  1485. Arguments:
  1486. Handle
  1487. ParentAccount - Valid account on ParentComputer
  1488. ParentPassword - Valid password for ParentAccount
  1489. ReplicaSetName - Replica set name
  1490. ReplicaSetType - Replica set type
  1491. CxtionName - printable name for cxtion
  1492. PartnerName - RPC bindable name
  1493. PartnerPrincName - Server principle name for kerberos
  1494. PartnerAuthLevel - Authentication type and level
  1495. GuidSize - sizeof array addressed by Guid
  1496. CxtionGuid - temporary: used for volatile cxtion
  1497. PartnerGuid - temporary: used to find set on partner
  1498. ParentGuid - Used as partner guid on inbound cxtion
  1499. Return Value:
  1500. Win32 Status
  1501. --*/
  1502. {
  1503. #undef DEBSUB
  1504. #define DEBSUB "SERVER_FrsRpcStartPromotionParent:"
  1505. DWORD WStatus;
  1506. PWCHAR AuthClient = NULL;
  1507. PWCHAR AuthSid = NULL;
  1508. try {
  1509. //
  1510. // Parent must be a DC
  1511. //
  1512. if (!IsADc) {
  1513. DPRINT(0, "++ ERROR - Parent is not a DC\n");
  1514. WStatus = ERROR_NO_SUCH_DOMAIN;
  1515. goto CLEANUP;
  1516. }
  1517. WStatus = RpcBindingInqAuthClient(Handle,
  1518. &AuthClient,
  1519. NULL,NULL,NULL,NULL);
  1520. CLEANUP_WS(0, "++ ERROR - RpcBindingInqAuthClient;",
  1521. WStatus, CLEANUP);
  1522. if(0 != _wcsicmp(AuthClient, PartnerPrincName)) {
  1523. // This is not a error as we no longer use the PartnerPrincName
  1524. // as security check.
  1525. DPRINT2(2, "++ WARN (can be ignored) - AuthClient (%ws) does not match PartnerPrincName (%ws)\n",
  1526. AuthClient,
  1527. PartnerPrincName
  1528. );
  1529. }
  1530. WStatus = UtilRpcServerHandleToAuthSidString(Handle,
  1531. AuthClient,
  1532. &AuthSid
  1533. );
  1534. CLEANUP_WS(0, "++ ERROR - UtilRpcServerHandleToAuthSidString;",
  1535. WStatus, CLEANUP);
  1536. //
  1537. // Our partner's computer object (or user object) should
  1538. // have the "I am a DC" flag set.
  1539. //
  1540. if (!FrsDsIsPartnerADc(AuthClient)) {
  1541. DPRINT(0, "++ ERROR - Partner is not a DC\n");
  1542. WStatus = ERROR_TRUSTED_DOMAIN_FAILURE;
  1543. goto CLEANUP;
  1544. }
  1545. //
  1546. // Display params
  1547. //
  1548. DPRINT(0, ":S: SERVER Start Promotion Parent:\n");
  1549. DPRINT1(0, ":S: \tPartner : %ws\n", PartnerName);
  1550. DPRINT1(0, ":S: \tPartnerPrinc : %ws\n", PartnerPrincName);
  1551. DPRINT1(0, ":S: \tAuthLevel : %d\n", PartnerAuthLevel);
  1552. DPRINT1(0, ":S: \tAccount : %ws\n", ParentAccount);
  1553. DPRINT1(0, ":S: \tSetName : %ws\n", ReplicaSetName);
  1554. DPRINT1(0, ":S: \tSetType : %ws\n", ReplicaSetType);
  1555. DPRINT1(0, ":S: \tCxtionName : %ws\n", CxtionName);
  1556. //
  1557. // Verify parameters
  1558. //
  1559. WStatus = LOCAL_FrsRpcVerifyPromotionParent(ReplicaSetName,
  1560. ReplicaSetType,
  1561. GuidSize);
  1562. CLEANUP_WS(0, "++ ERROR - verify;", WStatus, CLEANUP);
  1563. //
  1564. // Setup the outbound cxtion
  1565. //
  1566. WStatus = FrsDsStartPromotionSeeding(FALSE,
  1567. ReplicaSetName,
  1568. ReplicaSetType,
  1569. CxtionName,
  1570. PartnerName,
  1571. AuthClient,
  1572. AuthSid,
  1573. PartnerAuthLevel,
  1574. GuidSize,
  1575. CxtionGuid,
  1576. PartnerGuid,
  1577. ParentGuid);
  1578. CLEANUP_WS(0, "++ ERROR - ds start;", WStatus, CLEANUP);
  1579. //
  1580. // SUCCESS
  1581. //
  1582. DPRINT3(0, ":S: Success starting promotion parent %ws %ws %ws\n",
  1583. ParentAccount, ReplicaSetName, ReplicaSetType);
  1584. if(NeedNewPartnerTable) {
  1585. NeedNewPartnerTable = FALSE;
  1586. FrsDsCreateNewValidPartnerTableStruct();
  1587. }
  1588. WStatus = ERROR_SUCCESS;
  1589. CLEANUP:;
  1590. } except (EXCEPTION_EXECUTE_HANDLER) {
  1591. //
  1592. // Exception (may be RPC)
  1593. //
  1594. GET_EXCEPTION_CODE(WStatus);
  1595. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1596. }
  1597. if(AuthSid) {
  1598. FrsFree(AuthSid);
  1599. }
  1600. return WStatus;
  1601. }
  1602. BOOL
  1603. IsFacilityFrs(
  1604. IN DWORD WStatus
  1605. )
  1606. /*++
  1607. Routine Description:
  1608. Is this an FRS specific error status
  1609. Arguments:
  1610. WStatus - Win32 Error Status
  1611. Return Value:
  1612. TRUE - Is an FRS specific error status
  1613. FALSE -
  1614. --*/
  1615. {
  1616. #undef DEBSUB
  1617. #define DEBSUB "IsFacilityFrs:"
  1618. // TODO: replace these constants with symbollic values from winerror.h
  1619. return ( (WStatus >= 8000) && (WStatus < 8200) );
  1620. }
  1621. DWORD
  1622. NtFrsApi_Rpc_StartPromotionW(
  1623. IN handle_t Handle,
  1624. IN PWCHAR ParentComputer,
  1625. IN PWCHAR ParentAccount,
  1626. IN PWCHAR ParentPassword,
  1627. IN PWCHAR ReplicaSetName,
  1628. IN PWCHAR ReplicaSetType,
  1629. IN ULONG ReplicaSetPrimary,
  1630. IN PWCHAR ReplicaSetStage,
  1631. IN PWCHAR ReplicaSetRoot
  1632. )
  1633. /*++
  1634. Routine Description:
  1635. OBSOLETE API
  1636. Start the promotion process by seeding the indicated sysvol.
  1637. Arguments:
  1638. Handle
  1639. ParentComputer - DNS or NetBIOS name of the parent supplying the sysvol
  1640. ParentAccount - Valid account on ParentComputer
  1641. ParentPassword - Valid password for ParentAccount
  1642. ReplicaSetName - Replica set name
  1643. ReplicaSetType - Type of set (Enterprise or Domain)
  1644. ReplicaSetPrimary - 1=Primary; 0=not
  1645. ReplicaSetStage - Staging path
  1646. ReplicaSetRoot - Root path
  1647. Return Value:
  1648. Win32 Status
  1649. --*/
  1650. {
  1651. #undef DEBSUB
  1652. #define DEBSUB "NtFrsApi_Rpc_StartPromotionW:"
  1653. return ERROR_CALL_NOT_IMPLEMENTED;
  1654. }
  1655. DWORD
  1656. NtFrsApi_Rpc_VerifyPromotionW(
  1657. IN handle_t Handle,
  1658. IN PWCHAR ParentComputer,
  1659. IN PWCHAR ParentAccount,
  1660. IN PWCHAR ParentPassword,
  1661. IN PWCHAR ReplicaSetName,
  1662. IN PWCHAR ReplicaSetType,
  1663. IN ULONG ReplicaSetPrimary,
  1664. IN PWCHAR ReplicaSetStage,
  1665. IN PWCHAR ReplicaSetRoot
  1666. )
  1667. /*++
  1668. Routine Description:
  1669. OBSOLETE API
  1670. Verify that sysvol promotion is likely.
  1671. Arguments:
  1672. Handle
  1673. ParentComputer - DNS or NetBIOS name of the parent supplying the sysvol
  1674. ParentAccount - Valid account on ParentComputer
  1675. ParentPassword - Valid password for ParentAccount
  1676. ReplicaSetName - Replica set name
  1677. ReplicaSetType - Type of set (Enterprise or Domain)
  1678. ReplicaSetPrimary - 1=Primary; 0=not
  1679. ReplicaSetStage - Staging path
  1680. ReplicaSetRoot - Root path
  1681. Return Value:
  1682. Win32 Status
  1683. --*/
  1684. {
  1685. #undef DEBSUB
  1686. #define DEBSUB "NtFrsApi_Rpc_VerifyPromotionW:"
  1687. return ERROR_CALL_NOT_IMPLEMENTED;
  1688. }
  1689. DWORD
  1690. NtFrsApi_Rpc_PromotionStatusW(
  1691. IN handle_t Handle,
  1692. IN PWCHAR ReplicaSetName,
  1693. OUT ULONG *ServiceState,
  1694. OUT ULONG *ServiceWStatus,
  1695. OUT PWCHAR *ServiceDisplay OPTIONAL
  1696. )
  1697. /*++
  1698. Routine Description:
  1699. OBSOLETE API
  1700. Status of the seeding of the indicated sysvol
  1701. Arguments:
  1702. Handle
  1703. ReplicaSetName - Replica set name
  1704. ServiceState - State of the service
  1705. ServiceWStatus - Win32 Status if state is NTFRSAPI_SERVICE_ERROR
  1706. ServiceDisplay - Display string if state is NTFRSAPI_SERVICE_PROMOTING
  1707. Return Value:
  1708. Win32 Status
  1709. --*/
  1710. {
  1711. #undef DEBSUB
  1712. #define DEBSUB "NtFrsApi_Rpc_PromotionStatusW:"
  1713. return ERROR_CALL_NOT_IMPLEMENTED;
  1714. }
  1715. DWORD
  1716. NtFrsApi_Rpc_Get_DsPollingIntervalW(
  1717. IN handle_t Handle,
  1718. OUT ULONG *Interval,
  1719. OUT ULONG *LongInterval,
  1720. OUT ULONG *ShortInterval
  1721. )
  1722. /*++
  1723. Routine Description:
  1724. Get the current polling intervals in minutes.
  1725. Arguments:
  1726. Handle
  1727. Interval - Current interval in minutes
  1728. LongInterval - Long interval in minutes
  1729. ShortInterval - Short interval in minutes
  1730. Return Value:
  1731. Win32 Status
  1732. --*/
  1733. {
  1734. #undef DEBSUB
  1735. #define DEBSUB "NtFrsApi_Rpc_Get_DsPollingIntervalW"
  1736. DWORD WStatus;
  1737. try {
  1738. //
  1739. // Checkauthentication if the auth check is not disabled
  1740. // by setting the registry value:
  1741. // Access checks are [Enabled or Disabled]
  1742. // Each API has a different registry location so this
  1743. // can not be put in the rpc callback function.
  1744. //
  1745. WStatus = FrsRpcCheckAuthIfEnabled(Handle, ACX_GET_DS_POLL);
  1746. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1747. WStatus, CLEANUP);
  1748. WStatus = FrsRpcAccessChecks(Handle, ACX_GET_DS_POLL);
  1749. if (!WIN_SUCCESS(WStatus)) {
  1750. goto CLEANUP;
  1751. }
  1752. if ((Interval == NULL) || (LongInterval == NULL) || (ShortInterval == NULL)) {
  1753. goto CLEANUP;
  1754. }
  1755. WStatus = FrsDsGetDsPollingInterval(Interval, LongInterval, ShortInterval);
  1756. if (!WIN_SUCCESS(WStatus)) {
  1757. goto CLEANUP;
  1758. }
  1759. //
  1760. // SUCCESS
  1761. //
  1762. WStatus = ERROR_SUCCESS;
  1763. CLEANUP:;
  1764. } except (EXCEPTION_EXECUTE_HANDLER) {
  1765. GET_EXCEPTION_CODE(WStatus);
  1766. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1767. }
  1768. return WStatus;
  1769. }
  1770. DWORD
  1771. NtFrsApi_Rpc_Set_DsPollingIntervalW(
  1772. IN handle_t Handle,
  1773. IN ULONG UseShortInterval,
  1774. IN ULONG LongInterval,
  1775. IN ULONG ShortInterval
  1776. )
  1777. /*++
  1778. Routine Description:
  1779. Adjust the polling interval and kick off a new polling cycle.
  1780. The kick is ignored if a polling cycle is in progress.
  1781. The intervals are given in minutes.
  1782. Arguments:
  1783. Handle
  1784. UseShortInterval - If non-zero, use short interval. Otherwise, long.
  1785. LongInterval - Long interval in minutes
  1786. ShortInterval - Short interval in minutes
  1787. Return Value:
  1788. Win32 Status
  1789. --*/
  1790. {
  1791. #undef DEBSUB
  1792. #define DEBSUB "NtFrsApi_Rpc_Set_DsPollingIntervalW"
  1793. DWORD WStatus;
  1794. try {
  1795. //
  1796. // Checkauthentication if the auth check is not disabled
  1797. // by setting the registry value:
  1798. // Access checks are [Enabled or Disabled]
  1799. // Each API has a different registry location so this
  1800. // can not be put in the rpc callback function.
  1801. //
  1802. WStatus = FrsRpcCheckAuthIfEnabled(Handle,
  1803. (!LongInterval && !ShortInterval) ?
  1804. ACX_START_DS_POLL:
  1805. ACX_SET_DS_POLL);
  1806. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1807. WStatus, CLEANUP);
  1808. WStatus = FrsRpcAccessChecks(Handle,
  1809. (!LongInterval && !ShortInterval) ?
  1810. ACX_START_DS_POLL:
  1811. ACX_SET_DS_POLL);
  1812. if (!WIN_SUCCESS(WStatus)) {
  1813. goto CLEANUP;
  1814. }
  1815. WStatus = FrsDsSetDsPollingInterval(UseShortInterval,
  1816. LongInterval,
  1817. ShortInterval);
  1818. if (!WIN_SUCCESS(WStatus)) {
  1819. goto CLEANUP;
  1820. }
  1821. //
  1822. // SUCCESS
  1823. //
  1824. WStatus = ERROR_SUCCESS;
  1825. CLEANUP:;
  1826. } except (EXCEPTION_EXECUTE_HANDLER) {
  1827. GET_EXCEPTION_CODE(WStatus);
  1828. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1829. }
  1830. return WStatus;
  1831. }
  1832. DWORD
  1833. NtFrsApi_Rpc_WriterCommand(
  1834. IN handle_t Handle,
  1835. IN ULONG Command
  1836. )
  1837. /*++
  1838. Routine Description:
  1839. Arguments:
  1840. Handle
  1841. Command - freeze or thaw
  1842. Return Value:
  1843. Win32 Status
  1844. --*/
  1845. {
  1846. #undef DEBSUB
  1847. #define DEBSUB "NtFrsApi_Rpc_WriterCommand"
  1848. DWORD WStatus;
  1849. try {
  1850. //
  1851. // Checkauthentication if the auth check is not disabled
  1852. // by setting the registry value:
  1853. // Access checks are [Enabled or Disabled]
  1854. // Each API has a different registry location so this
  1855. // can not be put in the rpc callback function.
  1856. //
  1857. WStatus = FrsRpcCheckAuthIfEnabled(Handle,
  1858. ACX_DCPROMO);
  1859. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1860. WStatus, CLEANUP);
  1861. WStatus = FrsRpcAccessChecks(Handle,
  1862. ACX_DCPROMO);
  1863. if (!WIN_SUCCESS(WStatus)) {
  1864. goto CLEANUP;
  1865. }
  1866. switch (Command) {
  1867. case NTFRSAPI_WRITER_COMMAND_FREEZE :
  1868. WStatus = FrsFreezeForBackup();
  1869. CLEANUP_WS(0, "++ ERROR - FrsFreezeForBackup failed;",
  1870. WStatus, CLEANUP);
  1871. break;
  1872. case NTFRSAPI_WRITER_COMMAND_THAW :
  1873. WStatus = FrsThawAfterBackup();
  1874. CLEANUP_WS(0, "++ ERROR - FrsThawAfterBackup failed;",
  1875. WStatus, CLEANUP);
  1876. break;
  1877. default:
  1878. DPRINT1(2, "++ WARN - Unknown writer command %d\n", Command);
  1879. }
  1880. //
  1881. // SUCCESS
  1882. //
  1883. WStatus = ERROR_SUCCESS;
  1884. CLEANUP:;
  1885. } except (EXCEPTION_EXECUTE_HANDLER) {
  1886. GET_EXCEPTION_CODE(WStatus);
  1887. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1888. }
  1889. return WStatus;
  1890. }
  1891. DWORD
  1892. NtFrsApi_Rpc_InfoW(
  1893. IN handle_t Handle,
  1894. IN ULONG BlobSize,
  1895. IN OUT PBYTE Blob
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. Return internal info (see private\net\inc\ntfrsapi.h).
  1900. Arguments:
  1901. Handle
  1902. BlobSize - total bytes of Blob
  1903. Blob - details desired info and provides buffer for info
  1904. Return Value:
  1905. Win32 Status
  1906. --*/
  1907. {
  1908. #undef DEBSUB
  1909. #define DEBSUB "NtFrsApi_Rpc_InfoW:"
  1910. DWORD WStatus;
  1911. try {
  1912. //
  1913. // Checkauthentication if the auth check is not disabled
  1914. // by setting the registry value:
  1915. // Access checks are [Enabled or Disabled]
  1916. // Each API has a different registry location so this
  1917. // can not be put in the rpc callback function.
  1918. //
  1919. WStatus = FrsRpcCheckAuthIfEnabled(Handle, ACX_INTERNAL_INFO);
  1920. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  1921. WStatus, CLEANUP);
  1922. WStatus = FrsRpcAccessChecks(Handle, ACX_INTERNAL_INFO);
  1923. if (!WIN_SUCCESS(WStatus)) {
  1924. goto CLEANUP;
  1925. }
  1926. WStatus = Info(BlobSize, Blob);
  1927. if (!WIN_SUCCESS(WStatus)) {
  1928. goto CLEANUP;
  1929. }
  1930. //
  1931. // SUCCESS
  1932. //
  1933. WStatus = ERROR_SUCCESS;
  1934. CLEANUP:;
  1935. } except (EXCEPTION_EXECUTE_HANDLER) {
  1936. GET_EXCEPTION_CODE(WStatus);
  1937. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1938. }
  1939. return WStatus;
  1940. }
  1941. VOID
  1942. RegisterRpcProtseqs(
  1943. )
  1944. /*++
  1945. Routine Description:
  1946. Register the RPC protocol sequences and the authentication
  1947. that FRS supports. Currently, this is only TCP/IP authenticated
  1948. with kerberos.
  1949. Arguments:
  1950. None.
  1951. Return Value:
  1952. None.
  1953. --*/
  1954. {
  1955. #undef DEBSUB
  1956. #define DEBSUB "RegisterRpcProtseqs:"
  1957. DWORD WStatus;
  1958. RPC_STATUS Status;
  1959. PWCHAR InqPrincName = NULL;
  1960. RPC_POLICY RpcPolicy;
  1961. WCHAR PortStr[40];
  1962. RpcPolicy.Length = sizeof(RPC_POLICY);
  1963. RpcPolicy.EndpointFlags = RPC_C_DONT_FAIL;
  1964. RpcPolicy.NICFlags = 0;
  1965. //
  1966. // Register TCP/IP Protocol Sequence
  1967. //
  1968. if (RpcPortAssignment != 0) {
  1969. //
  1970. // Use customer specified port.
  1971. //
  1972. _ultow(RpcPortAssignment, PortStr, 10);
  1973. Status = RpcServerUseProtseqEpEx(PROTSEQ_TCP_IP, MaxRpcServerThreads, PortStr, NULL, &RpcPolicy );
  1974. DPRINT1_WS(0, "++ ERROR - RpcServerUseProtSeqEpEx(%ws);", PROTSEQ_TCP_IP, Status);
  1975. } else {
  1976. //
  1977. // Use dynamic RPC port assignment.
  1978. //
  1979. Status = RpcServerUseProtseqEx(PROTSEQ_TCP_IP, MaxRpcServerThreads, NULL, &RpcPolicy );
  1980. DPRINT1_WS(0, "++ ERROR - RpcServerUseProtSeqEx(%ws);", PROTSEQ_TCP_IP, Status);
  1981. }
  1982. if (!RPC_SUCCESS(Status)) {
  1983. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1984. }
  1985. //
  1986. // Perfmon APIs come over the local rpc.
  1987. //
  1988. Status = RpcServerUseProtseq(PROTSEQ_LRPC, MaxRpcServerThreads, NULL);
  1989. DPRINT1_WS(0, "++ ERROR - RpcServerUseProtSeq(%ws);", PROTSEQ_LRPC, Status);
  1990. if (!RPC_SUCCESS(Status)) {
  1991. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1992. }
  1993. //
  1994. // For hardwired -- Eventually DS Free configs.
  1995. // Don't bother with kerberos if emulating multiple machines
  1996. //
  1997. if (ServerGuid) {
  1998. return;
  1999. }
  2000. //
  2001. // Get our principle name
  2002. //
  2003. if (ServerPrincName) {
  2004. ServerPrincName = FrsFree(ServerPrincName);
  2005. }
  2006. Status = RpcServerInqDefaultPrincName(RPC_C_AUTHN_GSS_NEGOTIATE, &InqPrincName);
  2007. DPRINT1_WS(4, ":S: RpcServerInqDefaultPrincname(%d);", RPC_C_AUTHN_GSS_NEGOTIATE, Status);
  2008. //
  2009. // No principle name; KERBEROS may not be available
  2010. //
  2011. if (!RPC_SUCCESS(Status)) {
  2012. //
  2013. // Don't use any authentication if this server is not part of a domain.
  2014. //
  2015. DSROLE_PRIMARY_DOMAIN_INFO_BASIC *DsRole;
  2016. //
  2017. // Is this a member server?
  2018. //
  2019. WStatus = DsRoleGetPrimaryDomainInformation(NULL,
  2020. DsRolePrimaryDomainInfoBasic,
  2021. (PBYTE *)&DsRole);
  2022. if (!WIN_SUCCESS(WStatus)) {
  2023. DPRINT_WS(0, "++ ERROR - Can't get Ds role info;", WStatus);
  2024. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  2025. return;
  2026. }
  2027. //
  2028. // Standalone server; ignore authentication for now
  2029. // Hmmm, it seems we become a member server early
  2030. // in the dcpromo process. Oh, well...
  2031. //
  2032. // Hmmm, it seems that a NT4 to NT5 PDC doesn't
  2033. // have kerberos during dcpromo. This is getting
  2034. // old...
  2035. //
  2036. // if (DsRole->MachineRole == DsRole_RoleStandaloneServer ||
  2037. // DsRole->MachineRole == DsRole_RoleMemberServer) {
  2038. DsRoleFreeMemory(DsRole);
  2039. ServerPrincName = FrsWcsDup(ComputerName);
  2040. KerberosIsNotAvailable = TRUE;
  2041. DPRINT(0, ":S: WARN - KERBEROS IS NOT ENABLED!\n");
  2042. DPRINT1(4, ":S: Server Principal Name (no kerberos) is %ws\n",
  2043. ServerPrincName);
  2044. return;
  2045. // }
  2046. DsRoleFreeMemory(DsRole);
  2047. DPRINT1_WS(0, ":S: ERROR - RpcServerInqDefaultPrincName(%ws) failed;", ComputerName, Status);
  2048. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  2049. } else {
  2050. DPRINT2(4, ":S: RpcServerInqDefaultPrincname(%d, %ws) success\n",
  2051. RPC_C_AUTHN_GSS_NEGOTIATE, InqPrincName);
  2052. ServerPrincName = FrsWcsDup(InqPrincName);
  2053. RpcStringFree(&InqPrincName);
  2054. InqPrincName = NULL;
  2055. }
  2056. #ifdef DS_FREE
  2057. KerberosIsNotAvailable = TRUE;
  2058. #else DS_FREE
  2059. //
  2060. // Register with the KERBEROS authentication service
  2061. //
  2062. //
  2063. // Enable GSS_KERBEROS for pre-Beta3 compatability. When can we remove??
  2064. //
  2065. KerberosIsNotAvailable = FALSE;
  2066. DPRINT1(4, ":S: Server Principal Name is %ws\n", ServerPrincName);
  2067. Status = RpcServerRegisterAuthInfo(ServerPrincName,
  2068. RPC_C_AUTHN_GSS_KERBEROS,
  2069. NULL,
  2070. NULL);
  2071. if (!RPC_SUCCESS(Status)) {
  2072. DPRINT1_WS(0, "++ ERROR - RpcServerRegisterAuthInfo(KERBEROS, %ws) failed;",
  2073. ComputerName, Status);
  2074. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  2075. } else {
  2076. DPRINT2(4, ":S: RpcServerRegisterAuthInfo(%ws, %d) success\n",
  2077. ServerPrincName, RPC_C_AUTHN_GSS_KERBEROS);
  2078. }
  2079. #endif DS_FREE
  2080. //
  2081. // Enable GSS_NEGOTIATE for future usage
  2082. //
  2083. Status = RpcServerRegisterAuthInfo(ServerPrincName,
  2084. RPC_C_AUTHN_GSS_NEGOTIATE,
  2085. NULL,
  2086. NULL);
  2087. DPRINT2_WS(4, ":S: RpcServerRegisterAuthInfo(%ws, %d);",
  2088. ServerPrincName, RPC_C_AUTHN_GSS_NEGOTIATE, Status);
  2089. DPRINT1_WS(0, "++ WARN - RpcServerRegisterAuthInfo(NEGOTIATE, %ws) failed;",
  2090. ComputerName, Status);
  2091. }
  2092. RPC_STATUS
  2093. FrsRpcSecurityCallback(
  2094. IN RPC_IF_HANDLE *Interface,
  2095. IN void *Context
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Security callback function for RPC.
  2100. When a server application specifies a security-callback function for its
  2101. interface(s), the RPC run time automatically rejects unauthenticated calls
  2102. to that interface. In addition, the run-time records the interfaces that
  2103. each client has used. When a client makes an RPC to an interface that it
  2104. has not used during the current communication session, the RPC run-time
  2105. library will call the interface's security-callback function.
  2106. In some cases, the RPC run time may call the security-callback function
  2107. more than once per client-per interface.
  2108. Arguments:
  2109. Interface - UUID and version of the interface.
  2110. Context - Pointer to an RPC_IF_ID server binding handle representing the
  2111. client. In the function declaration, this must be of type
  2112. RPC_IF_HANDLE, but it is an RPC_IF_ID and can be safely cast to it.
  2113. Return Value:
  2114. RPC_S_OK if we will allow the call to go through..
  2115. RPC_S_ACCESS_DENIED otherwise.
  2116. --*/
  2117. {
  2118. DWORD WStatus = ERROR_ACCESS_DENIED;
  2119. RPC_STATUS RpcStatus = RPC_S_ACCESS_DENIED;
  2120. WStatus = CheckAuth(Context);
  2121. if(WStatus == ERROR_SUCCESS) {
  2122. RpcStatus = RPC_S_OK;
  2123. } else {
  2124. RpcStatus = RPC_S_ACCESS_DENIED;
  2125. }
  2126. return RpcStatus;
  2127. }
  2128. RPC_STATUS
  2129. FrsRpcSecurityCallbackForPerfmonAPIs(
  2130. IN RPC_IF_HANDLE *Interface,
  2131. IN void *Context
  2132. )
  2133. /*++
  2134. Routine Description:
  2135. Security callback function for the perfmon calls RPC.
  2136. When a server application specifies a security-callback function for its
  2137. interface(s), the RPC run time automatically rejects unauthenticated calls
  2138. to that interface. In addition, the run-time records the interfaces that
  2139. each client has used. When a client makes an RPC to an interface that it
  2140. has not used during the current communication session, the RPC run-time
  2141. library will call the interface's security-callback function.
  2142. In some cases, the RPC run time may call the security-callback function
  2143. more than once per client-per interface.
  2144. Arguments:
  2145. Interface - UUID and version of the interface.
  2146. Context - Pointer to an RPC_IF_ID server binding handle representing the
  2147. client. In the function declaration, this must be of type
  2148. RPC_IF_HANDLE, but it is an RPC_IF_ID and can be safely cast to it.
  2149. Return Value:
  2150. RPC_S_OK if we will allow the call to go through..
  2151. RPC_S_ACCESS_DENIED otherwise.
  2152. --*/
  2153. {
  2154. DWORD WStatus = ERROR_ACCESS_DENIED;
  2155. //
  2156. // Check authentication based on the registry key value
  2157. // for perfmon APIs. Check the FrsRpcCheckAuthIfEnabled
  2158. // function header for more info.
  2159. //
  2160. WStatus = FrsRpcCheckAuthIfEnabled(Context, ACX_COLLECT_PERFMON_DATA);
  2161. if(WIN_SUCCESS(WStatus)) {
  2162. return RPC_S_OK;
  2163. } else {
  2164. return RPC_S_ACCESS_DENIED;
  2165. }
  2166. }
  2167. DWORD
  2168. FrsRpcCheckAuthIfEnabled(
  2169. IN HANDLE ServerHandle,
  2170. IN DWORD RpcApiIndex
  2171. )
  2172. /*++
  2173. Routine Description:
  2174. Arguments:
  2175. First check if the access checks are disabled. If they are
  2176. disabled then skip authentication.
  2177. Access checks are controlled by a registry key.
  2178. This implies that if the server has the registry set to
  2179. disable access checks then it will accept unauthenticated
  2180. calls.
  2181. There is a seperate key for each API. The input parameter
  2182. RpcApiIndex determines which key to check.
  2183. E.g.
  2184. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
  2185. Services\ntfrs\Parameters\Access Checks\Get Perfmon Data
  2186. Access checks are [Enabled or Disabled]
  2187. Interface - UUID and version of the interface.
  2188. RpcApiIndex - identifies key in registry
  2189. Return Value:
  2190. ERROR_SUCCESS if we will allow the call to go through..
  2191. ERROR_ACCESS_DENIED if authentication fails.
  2192. --*/
  2193. {
  2194. FRS_REG_KEY_CODE EnableKey;
  2195. PWCHAR ApiName;
  2196. PWCHAR WStr = NULL, TrimStr;
  2197. DWORD WStatus = ERROR_ACCESS_DENIED;
  2198. // Check if RpcApiIndex is within range.
  2199. if (RpcApiIndex >= ACX_MAX) {
  2200. goto CHECK_AUTH;
  2201. }
  2202. //
  2203. // Get the key and the api name for this index from
  2204. // the global table.
  2205. //
  2206. EnableKey = RpcApiKeys[RpcApiIndex].Enable;
  2207. ApiName = RpcApiKeys[RpcApiIndex].KeyName;
  2208. WStatus = CfgRegReadString(EnableKey, NULL, 0, &WStr);
  2209. if (WStr == NULL) {
  2210. DPRINT1_WS(0, "++ ERROR - API Access enable check for API (%ws) failed.", ApiName, WStatus);
  2211. if (WIN_SUCCESS(WStatus)) {
  2212. WStatus = ERROR_GEN_FAILURE;
  2213. }
  2214. goto CLEANUP;
  2215. }
  2216. //
  2217. // If access checks are disabled then we're done.
  2218. //
  2219. TrimStr = FrsWcsTrim(WStr, L' ');
  2220. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DISABLED) ||
  2221. WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)) {
  2222. WStatus = ERROR_SUCCESS;
  2223. goto CLEANUP;
  2224. }
  2225. CHECK_AUTH:
  2226. if (RpcApiIndex == ACX_COLLECT_PERFMON_DATA) {
  2227. //
  2228. // Access checks are not disabled. Check authentication.
  2229. // Perfmon APIs can only be called over local RPC and
  2230. // they allow NTLM so call a different API for them.
  2231. //
  2232. WStatus = CheckAuthForLocalRpc(ServerHandle);
  2233. } else if ((RpcApiIndex == ACX_START_DS_POLL) ||
  2234. (RpcApiIndex == ACX_SET_DS_POLL) ||
  2235. (RpcApiIndex == ACX_GET_DS_POLL) ||
  2236. (RpcApiIndex == ACX_INTERNAL_INFO)) {
  2237. //
  2238. // Access checks are not disabled. Check authentication.
  2239. // When info APIs are called from local machine they
  2240. // use NTLM so allow NTLM for info APIs.
  2241. //
  2242. WStatus = CheckAuthForInfoAPIs(ServerHandle);
  2243. } else {
  2244. WStatus = CheckAuth(ServerHandle);
  2245. }
  2246. CLEANUP:
  2247. return WStatus;
  2248. }
  2249. DWORD
  2250. FrsRpcCheckAuthIfEnabledForCommitDemotion(
  2251. IN HANDLE ServerHandle,
  2252. IN DWORD RpcApiIndex
  2253. )
  2254. /*++
  2255. Routine Description:
  2256. Arguments:
  2257. First check if the access checks are disabled. If they are
  2258. disabled then skip authentication.
  2259. Access checks are controlled by a registry key.
  2260. This implies that if the server has the registry set to
  2261. disable access checks then it will accept unauthenticated
  2262. calls.
  2263. There is a seperate key for each API. The input parameter
  2264. RpcApiIndex determines which key to check.
  2265. E.g.
  2266. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\
  2267. Services\ntfrs\Parameters\Access Checks\Get Perfmon Data
  2268. Access checks are [Enabled or Disabled]
  2269. Interface - UUID and version of the interface.
  2270. RpcApiIndex - identifies key in registry
  2271. Return Value:
  2272. ERROR_SUCCESS if we will allow the call to go through..
  2273. ERROR_ACCESS_DENIED if authentication fails.
  2274. --*/
  2275. {
  2276. FRS_REG_KEY_CODE EnableKey;
  2277. PWCHAR ApiName;
  2278. PWCHAR WStr = NULL, TrimStr;
  2279. DWORD WStatus = ERROR_ACCESS_DENIED;
  2280. // Check if RpcApiIndex is within range.
  2281. if (RpcApiIndex >= ACX_MAX) {
  2282. goto CHECK_AUTH;
  2283. }
  2284. //
  2285. // Get the key and the api name for this index from
  2286. // the global table.
  2287. //
  2288. EnableKey = RpcApiKeys[RpcApiIndex].Enable;
  2289. ApiName = RpcApiKeys[RpcApiIndex].KeyName;
  2290. WStatus = CfgRegReadString(EnableKey, NULL, 0, &WStr);
  2291. if (WStr == NULL) {
  2292. DPRINT1_WS(0, "++ ERROR - API Access enable check for API (%ws) failed.", ApiName, WStatus);
  2293. if (WIN_SUCCESS(WStatus)) {
  2294. WStatus = ERROR_GEN_FAILURE;
  2295. }
  2296. goto CLEANUP;
  2297. }
  2298. //
  2299. // If access checks are disabled then we're done.
  2300. //
  2301. TrimStr = FrsWcsTrim(WStr, L' ');
  2302. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DISABLED) ||
  2303. WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)) {
  2304. WStatus = ERROR_SUCCESS;
  2305. goto CLEANUP;
  2306. }
  2307. CHECK_AUTH:
  2308. //
  2309. // Access checks are not disabled. Check authentication.
  2310. // Commit of DC demotion can only be called over local RPC
  2311. // using NTLM.
  2312. //
  2313. WStatus = CheckAuthForLocalRpc(ServerHandle);
  2314. CLEANUP:
  2315. return WStatus;
  2316. }
  2317. VOID
  2318. RegisterRpcInterface(
  2319. )
  2320. /*++
  2321. Routine Description:
  2322. Register the frsrpc interface for the RPC protocol sequences
  2323. previously registered.
  2324. Arguments:
  2325. None.
  2326. Return Value:
  2327. None.
  2328. --*/
  2329. {
  2330. #undef DEBSUB
  2331. #define DEBSUB "RegisterRpcInterface:"
  2332. RPC_STATUS Status;
  2333. //
  2334. // Service RPC
  2335. //
  2336. #ifdef DS_FREE
  2337. //
  2338. // In ds_free mode we bind without authentication so we
  2339. // don't want a security callback.
  2340. //
  2341. Status = RpcServerRegisterIfEx(SERVER_frsrpc_ServerIfHandle,
  2342. NULL,
  2343. NULL,
  2344. 0,
  2345. MaxRpcServerThreads,
  2346. NULL);
  2347. #else
  2348. Status = RpcServerRegisterIfEx(SERVER_frsrpc_ServerIfHandle,
  2349. NULL,
  2350. NULL,
  2351. RPC_IF_ALLOW_SECURE_ONLY,
  2352. MaxRpcServerThreads,
  2353. FrsRpcSecurityCallback);
  2354. #endif DS_FREE
  2355. if (!RPC_SUCCESS(Status)) {
  2356. DPRINT_WS(0, "++ ERROR - Can't register NtFrs Service;", Status);
  2357. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  2358. }
  2359. //
  2360. // API RPC
  2361. //
  2362. Status = RpcServerRegisterIfEx(NtFrsApi_ServerIfHandle,
  2363. NULL,
  2364. NULL,
  2365. 0,
  2366. MaxRpcServerThreads,
  2367. NULL);
  2368. if (!RPC_SUCCESS(Status)) {
  2369. DPRINT_WS(0, "++ ERROR - Can't register NtFrs API;", Status);
  2370. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  2371. }
  2372. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  2373. //
  2374. // PERFMON RPC
  2375. //
  2376. #ifdef DS_FREE
  2377. //
  2378. // The FrsRpcSecurityCallbackForPerfmonAPIs checks the registry
  2379. // setting before granting access so we can leave that on in
  2380. // ds_free environments.
  2381. //
  2382. Status = RpcServerRegisterIfEx(PerfFrs_ServerIfHandle,
  2383. NULL,
  2384. NULL,
  2385. 0,
  2386. MaxRpcServerThreads,
  2387. FrsRpcSecurityCallbackForPerfmonAPIs);
  2388. #else
  2389. Status = RpcServerRegisterIfEx(PerfFrs_ServerIfHandle,
  2390. NULL,
  2391. NULL,
  2392. RPC_IF_ALLOW_SECURE_ONLY,
  2393. MaxRpcServerThreads,
  2394. FrsRpcSecurityCallbackForPerfmonAPIs);
  2395. #endif DS_FREE
  2396. if (!RPC_SUCCESS(Status)) {
  2397. DPRINT_WS(0, "++ ERROR - Can't register PERFMON SERVICE;", Status);
  2398. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  2399. }
  2400. }
  2401. }
  2402. VOID
  2403. StartServerRpc(
  2404. )
  2405. /*++
  2406. Routine Description:
  2407. Register the endpoints for each of the protocol sequences that
  2408. the frsrpc interface supports and then listen for client requests.
  2409. Arguments:
  2410. None.
  2411. Return Value:
  2412. None.
  2413. --*/
  2414. {
  2415. #undef DEBSUB
  2416. #define DEBSUB "StartServerRpc:"
  2417. RPC_STATUS Status, Status1;
  2418. UUID_VECTOR Uuids;
  2419. UUID_VECTOR *pUuids = NULL;
  2420. RPC_BINDING_VECTOR *BindingVector = NULL;
  2421. //
  2422. // The protocol sequences that frsrpc is registered for
  2423. //
  2424. Status = RpcServerInqBindings(&BindingVector);
  2425. if (!RPC_SUCCESS(Status)) {
  2426. DPRINT_WS(0, "++ ERROR - Can't get binding vector;", Status);
  2427. FrsRaiseException(FRS_ERROR_INQ_BINDINGS, Status);
  2428. }
  2429. //
  2430. // Register endpoints with the endpoint mapper (RPCSS)
  2431. //
  2432. if (ServerGuid) {
  2433. //
  2434. // For hardwired -- Eventually DS Free configs.
  2435. //
  2436. Uuids.Count = 1;
  2437. Uuids.Uuid[0] = ServerGuid;
  2438. pUuids = &Uuids;
  2439. }
  2440. //
  2441. // Service RPC
  2442. //
  2443. Status = RpcEpRegister(SERVER_frsrpc_ServerIfHandle,
  2444. BindingVector,
  2445. pUuids,
  2446. L"NtFrs Service");
  2447. if (!RPC_SUCCESS(Status)) {
  2448. DPRINT_WS(0, "++ ERROR - Can't register NtFrs Service Ep;", Status);
  2449. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  2450. }
  2451. //
  2452. // API RPC
  2453. //
  2454. Status = RpcEpRegister(NtFrsApi_ServerIfHandle,
  2455. BindingVector,
  2456. NULL,
  2457. L"NtFrs API");
  2458. if (!RPC_SUCCESS(Status)) {
  2459. DPRINT_WS(0, "++ ERROR - Can't register NtFrs API Ep;", Status);
  2460. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  2461. }
  2462. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  2463. //
  2464. // PERFMON RPC
  2465. //
  2466. Status = RpcEpRegister(PerfFrs_ServerIfHandle,
  2467. BindingVector,
  2468. NULL,
  2469. L"PERFMON SERVICE");
  2470. if (!RPC_SUCCESS(Status)) {
  2471. DPRINT1(0, "++ ERROR - Can't register PERFMON SERVICE Ep; RStatus %d\n",
  2472. Status);
  2473. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  2474. }
  2475. }
  2476. //
  2477. // Listen for client requests
  2478. //
  2479. Status = RpcServerListen(1, MaxRpcServerThreads, TRUE);
  2480. if (!RPC_SUCCESS(Status)) {
  2481. DPRINT_WS(0, "++ ERROR - Can't listen;", Status);
  2482. FrsRaiseException(FRS_ERROR_LISTEN, Status);
  2483. }
  2484. Status1 = RpcBindingVectorFree(&BindingVector);
  2485. DPRINT_WS(0, "++ WARN - RpcBindingVectorFree;", Status1);
  2486. }
  2487. PWCHAR
  2488. FrsRpcDns2Machine(
  2489. IN PWCHAR DnsName
  2490. )
  2491. /*++
  2492. Routine Description:
  2493. Convert a DNS name(machine....) into a computer name.
  2494. Arguments:
  2495. DnsName
  2496. Return Value:
  2497. Computer name
  2498. --*/
  2499. {
  2500. #undef DEBSUB
  2501. #define DEBSUB "FrsRpcDns2Machine:"
  2502. PWCHAR Machine;
  2503. ULONG Period;
  2504. //
  2505. // Find the period
  2506. //
  2507. if (DnsName) {
  2508. Period = wcscspn(DnsName, L".");
  2509. } else {
  2510. return FrsWcsDup(DnsName);
  2511. }
  2512. if (DnsName[Period] != L'.') {
  2513. return FrsWcsDup(DnsName);
  2514. }
  2515. Machine = FrsAlloc((Period + 1) * sizeof(WCHAR));
  2516. CopyMemory(Machine, DnsName, Period * sizeof(WCHAR));
  2517. Machine[Period] = L'\0';
  2518. DPRINT2(4, ":S: Dns %ws to Machine %ws\n", DnsName, Machine);
  2519. return Machine;
  2520. }
  2521. DWORD
  2522. FrsRpcBindToServerGuid(
  2523. IN PGNAME Name,
  2524. OUT handle_t *Handle
  2525. )
  2526. /*++
  2527. Routine Description:
  2528. Set up the bindings to our inbound/outbound partner.
  2529. Arguments:
  2530. Name
  2531. Handle
  2532. Return Value:
  2533. Win32 Status
  2534. --*/
  2535. {
  2536. #undef DEBSUB
  2537. #define DEBSUB "FrsRpcBindToServerGuid:"
  2538. DWORD WStatus;
  2539. LONG DeltaBinds;
  2540. PWCHAR GuidStr = NULL;
  2541. PWCHAR BindingString = NULL;
  2542. PWCHAR MachineName;
  2543. FRS_ASSERT(RPC_S_OK == ERROR_SUCCESS);
  2544. FRS_ASSERT(ServerGuid);
  2545. //
  2546. // Emulating multiple machines with hardwired config
  2547. //
  2548. if (Name->Guid != NULL) {
  2549. WStatus = UuidToString(Name->Guid, &GuidStr);
  2550. CLEANUP_WS(0, "++ ERROR - Translating Guid to string;", WStatus, CLEANUP);
  2551. }
  2552. //
  2553. // Basically, bind to the server's RPC name on this machine. Trim leading \\
  2554. //
  2555. MachineName = Name->Name;
  2556. FRS_TRIM_LEADING_2SLASH(MachineName);
  2557. WStatus = RpcStringBindingCompose(GuidStr, PROTSEQ_TCP_IP, MachineName,
  2558. NULL, NULL, &BindingString);
  2559. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  2560. //
  2561. // Store the binding in the handle
  2562. //
  2563. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  2564. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  2565. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  2566. //
  2567. // Some simple stats for debugging
  2568. //
  2569. DeltaBinds = ++RpcBinds - RpcUnBinds;
  2570. if (DeltaBinds > RpcMaxBinds) {
  2571. RpcMaxBinds = DeltaBinds;
  2572. }
  2573. // Fall through
  2574. CLEANUP:
  2575. if (BindingString) {
  2576. RpcStringFreeW(&BindingString);
  2577. }
  2578. if (GuidStr) {
  2579. RpcStringFree(&GuidStr);
  2580. }
  2581. //
  2582. // We are now ready to talk to the server using the frsrpc interfaces
  2583. //
  2584. return WStatus;
  2585. }
  2586. DWORD
  2587. FrsRpcBindToServerNotService(
  2588. IN PGNAME Name,
  2589. IN PWCHAR PrincName,
  2590. IN ULONG AuthLevel,
  2591. OUT handle_t *Handle
  2592. )
  2593. /*++
  2594. Routine Description:
  2595. Set up the bindings to our inbound/outbound partner.
  2596. Arguments:
  2597. Name
  2598. PrincName
  2599. AuthLevel
  2600. Handle
  2601. Return Value:
  2602. Win32 Status
  2603. --*/
  2604. {
  2605. #undef DEBSUB
  2606. #define DEBSUB "FrsRpcBindToServerNotSevice:"
  2607. DWORD WStatus;
  2608. LONG DeltaBinds;
  2609. PWCHAR InqPrincName = NULL;
  2610. PWCHAR BindingString = NULL;
  2611. PWCHAR MachineName;
  2612. //
  2613. // Basically, bind to the server's RPC name on this machine. Trim leading \\
  2614. //
  2615. MachineName = Name->Name;
  2616. FRS_TRIM_LEADING_2SLASH(MachineName);
  2617. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  2618. NULL, NULL, &BindingString);
  2619. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  2620. //
  2621. // Store the binding in the handle
  2622. //
  2623. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  2624. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  2625. //
  2626. // Not authenticating
  2627. //
  2628. if (KerberosIsNotAvailable ||
  2629. AuthLevel == CXTION_AUTH_NONE) {
  2630. goto done;
  2631. }
  2632. //
  2633. // When not running as a service, we can't predict our
  2634. // principle name so simply resolve the binding.
  2635. //
  2636. WStatus = RpcEpResolveBinding(*Handle, frsrpc_ClientIfHandle);
  2637. CLEANUP_WS(4, "++ ERROR: resolving binding;", WStatus, CLEANUP);
  2638. WStatus = RpcMgmtInqServerPrincName(*Handle,
  2639. RPC_C_AUTHN_GSS_NEGOTIATE,
  2640. &InqPrincName);
  2641. CLEANUP_WS(0, "++ ERROR: resolving PrincName;", WStatus, CLEANUP);
  2642. DPRINT1(4, ":S: Inq PrincName is %ws\n", InqPrincName);
  2643. //
  2644. // Put our authentication info into the handle
  2645. //
  2646. if (MutualAuthenticationIsEnabled || MutualAuthenticationIsEnabledAndRequired) {
  2647. WStatus = RpcBindingSetAuthInfoEx(*Handle,
  2648. InqPrincName,
  2649. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2650. RPC_C_AUTHN_GSS_NEGOTIATE,
  2651. NULL,
  2652. RPC_C_AUTHZ_NONE,
  2653. &RpcSecurityQos);
  2654. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  2655. Name->Name, InqPrincName, WStatus);
  2656. } else {
  2657. WStatus = ERROR_NOT_SUPPORTED;
  2658. }
  2659. //
  2660. // Fall back to manual mutual authentication
  2661. //
  2662. if (!MutualAuthenticationIsEnabledAndRequired && !WIN_SUCCESS(WStatus)) {
  2663. WStatus = RpcBindingSetAuthInfo(*Handle,
  2664. InqPrincName,
  2665. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2666. RPC_C_AUTHN_GSS_NEGOTIATE,
  2667. NULL,
  2668. RPC_C_AUTHZ_NONE);
  2669. }
  2670. CLEANUP2_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws, %ws);",
  2671. Name->Name, InqPrincName, WStatus, CLEANUP);
  2672. //
  2673. // SUCCESS
  2674. //
  2675. WStatus = ERROR_SUCCESS;
  2676. done:
  2677. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  2678. //
  2679. // Some simple stats for debugging
  2680. //
  2681. DeltaBinds = ++RpcBinds - RpcUnBinds;
  2682. if (DeltaBinds > RpcMaxBinds) {
  2683. RpcMaxBinds = DeltaBinds;
  2684. }
  2685. // Fall through
  2686. CLEANUP:
  2687. if (BindingString) {
  2688. RpcStringFreeW(&BindingString);
  2689. }
  2690. if (InqPrincName) {
  2691. RpcStringFree(&InqPrincName);
  2692. }
  2693. //
  2694. // We are now ready to talk to the server using the frsrpc interfaces
  2695. //
  2696. return WStatus;
  2697. }
  2698. DWORD
  2699. FrsRpcBindToServer(
  2700. IN PGNAME Name,
  2701. IN PWCHAR PrincName,
  2702. IN ULONG AuthLevel,
  2703. OUT handle_t *Handle
  2704. )
  2705. /*++
  2706. Routine Description:
  2707. Set up the bindings to our inbound/outbound partner.
  2708. Arguments:
  2709. Name
  2710. PrincName
  2711. AuthLevel
  2712. Handle
  2713. Return Value:
  2714. Win32 Status
  2715. --*/
  2716. {
  2717. #undef DEBSUB
  2718. #define DEBSUB "FrsRpcBindToServer:"
  2719. DWORD WStatus;
  2720. LONG DeltaBinds;
  2721. PWCHAR BindingString = NULL;
  2722. PWCHAR MachineName;
  2723. FRS_ASSERT(RPC_S_OK == ERROR_SUCCESS);
  2724. //
  2725. // Emulating multiple machines with hardwired config
  2726. // For hardwired -- Eventually DS Free configs.
  2727. //
  2728. if (ServerGuid) {
  2729. return (FrsRpcBindToServerGuid(Name, Handle));
  2730. }
  2731. //
  2732. // Not running as a service; relax binding constraints
  2733. //
  2734. if (!RunningAsAService) {
  2735. return (FrsRpcBindToServerNotService(Name, PrincName, AuthLevel, Handle));
  2736. }
  2737. //
  2738. // Basically, bind to the NtFrs running on Name. Trim leading \\
  2739. //
  2740. MachineName = Name->Name;
  2741. FRS_TRIM_LEADING_2SLASH(MachineName);
  2742. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  2743. NULL, NULL, &BindingString);
  2744. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  2745. //
  2746. // Store the binding in the handle
  2747. //
  2748. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  2749. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  2750. //
  2751. // Not authenticating
  2752. //
  2753. if (KerberosIsNotAvailable ||
  2754. AuthLevel == CXTION_AUTH_NONE) {
  2755. DPRINT1(4, ":S: Not authenticating %ws\n", Name->Name);
  2756. goto done;
  2757. }
  2758. //
  2759. // Put our authentication info into the handle
  2760. //
  2761. if (MutualAuthenticationIsEnabled || MutualAuthenticationIsEnabledAndRequired) {
  2762. WStatus = RpcBindingSetAuthInfoEx(*Handle,
  2763. PrincName,
  2764. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2765. RPC_C_AUTHN_GSS_NEGOTIATE,
  2766. NULL,
  2767. RPC_C_AUTHZ_NONE,
  2768. &RpcSecurityQos);
  2769. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  2770. Name->Name, PrincName, WStatus);
  2771. } else {
  2772. WStatus = ERROR_NOT_SUPPORTED;
  2773. }
  2774. //
  2775. // Fall back to manual mutual authentication
  2776. //
  2777. if (!MutualAuthenticationIsEnabledAndRequired && !WIN_SUCCESS(WStatus)) {
  2778. WStatus = RpcBindingSetAuthInfo(*Handle,
  2779. PrincName,
  2780. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2781. RPC_C_AUTHN_GSS_NEGOTIATE,
  2782. NULL,
  2783. RPC_C_AUTHZ_NONE);
  2784. }
  2785. CLEANUP2_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws, %ws);",
  2786. Name->Name, PrincName, WStatus, CLEANUP);
  2787. //
  2788. // SUCCESS
  2789. //
  2790. WStatus = ERROR_SUCCESS;
  2791. done:
  2792. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  2793. //
  2794. // Some simple stats for debugging
  2795. //
  2796. DeltaBinds = ++RpcBinds - RpcUnBinds;
  2797. if (DeltaBinds > RpcMaxBinds) {
  2798. RpcMaxBinds = DeltaBinds;
  2799. }
  2800. // Fall through
  2801. CLEANUP:
  2802. if (BindingString) {
  2803. RpcStringFreeW(&BindingString);
  2804. }
  2805. //
  2806. // We are now ready to talk to the server using the frsrpc interfaces
  2807. //
  2808. return WStatus;
  2809. }
  2810. VOID
  2811. FrsRpcUnBindFromServer(
  2812. handle_t *Handle
  2813. )
  2814. /*++
  2815. Routine Description:
  2816. Unbind from the server.
  2817. Arguments:
  2818. None.
  2819. Return Value:
  2820. None.
  2821. --*/
  2822. {
  2823. #undef DEBSUB
  2824. #define DEBSUB "FrsRpcUnBindFromServer:"
  2825. DWORD WStatus;
  2826. //
  2827. // Simple stats for debugging
  2828. //
  2829. ++RpcUnBinds;
  2830. try {
  2831. if (Handle) {
  2832. WStatus = RpcBindingFree(Handle);
  2833. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus);
  2834. *Handle = NULL;
  2835. }
  2836. } except (FrsException(GetExceptionInformation())) {
  2837. }
  2838. }
  2839. VOID
  2840. FrsRpcInitializeAccessChecks(
  2841. VOID
  2842. )
  2843. /*++
  2844. Routine Description:
  2845. Create the registry keys that are used to check for access to
  2846. the RPC calls that are exported for applications. The access checks
  2847. have no affect on the RPC calls used for replication.
  2848. The access checks for a given RPC call can be enabled or disabled
  2849. by setting a registry value. If enabled, the RPC call impersonates
  2850. the caller and attempts to open the registry key with the access
  2851. required for that RPC call. The required access is a registry value.
  2852. For example, the following registry hierarchy shows that the
  2853. "Set Ds Polling Interval" has access checks enabled and requires
  2854. write access while "Get Ds Polling Interval" has no access checks.
  2855. NtFrs\Parameters\Access Checks\Set Ds Polling Interval
  2856. Access checks are [enabled | disabled] REG_SZ enabled
  2857. Access checks require [read | write] REG_SZ write
  2858. NtFrs\Parameters\Access Checks\Get Ds Polling Interval
  2859. Access checks are [enabled | disabled] REG_SZ disabled
  2860. The initial set of RPC calls are: (see key context entries in config.c)
  2861. dcpromo - enabled, write
  2862. Set Ds Polling Interval - enabled, write
  2863. Start Ds Polling - enabled, read
  2864. Get Ds Polling Interval - enabled, read
  2865. Get Internal Information - enabled, write
  2866. Get Perfmon Data - enabled, read
  2867. Arguments:
  2868. None.
  2869. Return Value:
  2870. None.
  2871. --*/
  2872. {
  2873. #undef DEBSUB
  2874. #define DEBSUB "FrsRpcInitializeAccessChecks:"
  2875. DWORD WStatus;
  2876. DWORD i;
  2877. PWCHAR AccessChecksAre = NULL;
  2878. PWCHAR AccessChecksRequire = NULL;
  2879. FRS_REG_KEY_CODE FrsRkc;
  2880. PWCHAR ApiName;
  2881. for (i = 0; i < ACX_MAX; ++i) {
  2882. FrsRkc = RpcApiKeys[i].Enable;
  2883. ApiName = RpcApiKeys[i].KeyName;
  2884. //
  2885. // Read the current string Access Check Enable string.
  2886. //
  2887. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksAre);
  2888. if ((AccessChecksAre == NULL) ||
  2889. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)||
  2890. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_ENABLED)) {
  2891. //
  2892. // The key is in the default state so we can clobber it with a
  2893. // new default.
  2894. //
  2895. WStatus = CfgRegWriteString(FrsRkc, NULL, FRS_RKF_FORCE_DEFAULT_VALUE, NULL);
  2896. DPRINT1_WS(0, "++ WARN - Cannot create Enable key for %ws;", ApiName, WStatus);
  2897. AccessChecksAre = FrsFree(AccessChecksAre);
  2898. //
  2899. // Now reread the key for the new default.
  2900. //
  2901. WStatus = CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksAre);
  2902. }
  2903. DPRINT4(4, ":S: AccessChecks: ...\\%ws\\%ws\\%ws = %ws\n",
  2904. ACCESS_CHECKS_KEY, ApiName, ACCESS_CHECKS_ARE, AccessChecksAre);
  2905. if (AccessChecksAre &&
  2906. (WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_DISABLED) ||
  2907. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DISABLED))) {
  2908. //
  2909. // Put a notice in the event log that the access check is disabled.
  2910. //
  2911. EPRINT2(EVENT_FRS_ACCESS_CHECKS_DISABLED, ApiName, ACCESS_CHECKS_ARE);
  2912. }
  2913. AccessChecksAre = FrsFree(AccessChecksAre);
  2914. //
  2915. // Create the Access Rights value. This determines what rights the caller
  2916. // must have in order to use the API. These rights are used when we
  2917. // open the API key after impersonating the RPC caller. If the key
  2918. // open works then the API call can proceed else we return insufficient
  2919. // privilege status (FRS_ERR_INSUFFICENT_PRIV).
  2920. //
  2921. FrsRkc = RpcApiKeys[i].Rights;
  2922. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksRequire);
  2923. if ((AccessChecksRequire == NULL)||
  2924. WSTR_EQ(AccessChecksRequire, ACCESS_CHECKS_REQUIRE_DEFAULT_READ)||
  2925. WSTR_EQ(AccessChecksRequire, ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE)) {
  2926. //
  2927. // The key is in the default state so we can clobber it with a
  2928. // new default.
  2929. //
  2930. WStatus = CfgRegWriteString(FrsRkc, NULL, FRS_RKF_FORCE_DEFAULT_VALUE, NULL);
  2931. DPRINT1_WS(0, "++ WARN - Cannot set access rights key for %ws;", ApiName, WStatus);
  2932. AccessChecksRequire = FrsFree(AccessChecksRequire);
  2933. //
  2934. // Now reread the key for the new default.
  2935. //
  2936. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksRequire);
  2937. }
  2938. DPRINT4(4, ":S: AccessChecks: ...\\%ws\\%ws\\%ws = %ws\n",
  2939. ACCESS_CHECKS_KEY, ApiName, ACCESS_CHECKS_REQUIRE, AccessChecksRequire);
  2940. AccessChecksRequire = FrsFree(AccessChecksRequire);
  2941. } // end for
  2942. FrsFree(AccessChecksAre);
  2943. FrsFree(AccessChecksRequire);
  2944. }
  2945. VOID
  2946. ShutDownRpc(
  2947. )
  2948. /*++
  2949. Routine Description:
  2950. Shutdown the client and server side of RPC.
  2951. Arguments:
  2952. None.
  2953. Return Value:
  2954. None.
  2955. --*/
  2956. {
  2957. #undef DEBSUB
  2958. #define DEBSUB "ShutDownRpc:"
  2959. RPC_STATUS WStatus;
  2960. RPC_BINDING_VECTOR *BindingVector = NULL;
  2961. //
  2962. // Server side
  2963. //
  2964. // Stop listening for new calls
  2965. //
  2966. try {
  2967. WStatus = RpcMgmtStopServerListening(0) ;
  2968. DPRINT_WS(0, "++ WARN - RpcMgmtStopServerListening;", WStatus);
  2969. } except (FrsException(GetExceptionInformation())) {
  2970. }
  2971. try {
  2972. //
  2973. // Get our registered interfaces
  2974. //
  2975. WStatus = RpcServerInqBindings(&BindingVector);
  2976. DPRINT_WS(0, "++ WARN - RpcServerInqBindings;", WStatus);
  2977. if (RPC_SUCCESS(WStatus)) {
  2978. //
  2979. // And unexport the interfaces together with their dynamic endpoints
  2980. //
  2981. WStatus = RpcEpUnregister(SERVER_frsrpc_ServerIfHandle, BindingVector, 0);
  2982. DPRINT_WS(0, "++ WARN - RpcEpUnregister SERVER_frsrpc_ServerIfHandle;", WStatus);
  2983. WStatus = RpcEpUnregister(NtFrsApi_ServerIfHandle, BindingVector, 0);
  2984. DPRINT_WS(0, "++ WARN - RpcEpUnregister NtFrsApi_ServerIfHandle;", WStatus);
  2985. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  2986. //
  2987. // PERFMON RPC
  2988. //
  2989. WStatus = RpcEpUnregister(PerfFrs_ServerIfHandle, BindingVector, 0);
  2990. DPRINT_WS(0, "++ WARN - RpcEpUnregister PerfFrs_ServerIfHandle;", WStatus);
  2991. }
  2992. WStatus = RpcBindingVectorFree(&BindingVector);
  2993. DPRINT_WS(0, "++ WARN - RpcBindingVectorFree;", WStatus);
  2994. }
  2995. //
  2996. // Wait for any outstanding RPCs to finish.
  2997. //
  2998. WStatus = RpcMgmtWaitServerListen();
  2999. DPRINT_WS(0, "++ WARN - RpcMgmtWaitServerListen;", WStatus);
  3000. } except (FrsException(GetExceptionInformation())) {
  3001. }
  3002. }
  3003. VOID
  3004. FrsRpcUnInitialize(
  3005. VOID
  3006. )
  3007. /*++
  3008. Routine Description:
  3009. Free up memory once all of the threads in the system have been
  3010. shut down.
  3011. Arguments:
  3012. None.
  3013. Return Value:
  3014. None.
  3015. --*/
  3016. {
  3017. #undef DEBSUB
  3018. #define DEBSUB "FrsRpcUnInitialize:"
  3019. DPRINT(4, ":S: Free sysvol name table.\n");
  3020. DEBUG_FLUSH();
  3021. SysVolsBeingCreated = GTabFreeTable(SysVolsBeingCreated, NULL);
  3022. if (ServerPrincName) {
  3023. if (KerberosIsNotAvailable) {
  3024. DPRINT(4, ":S: Free ServerPrincName (no kerberos).\n");
  3025. DEBUG_FLUSH();
  3026. ServerPrincName = FrsFree(ServerPrincName);
  3027. } else {
  3028. DPRINT(4, ":S: Free ServerPrincName (kerberos).\n");
  3029. DEBUG_FLUSH();
  3030. ServerPrincName = FrsFree(ServerPrincName);
  3031. }
  3032. }
  3033. DPRINT(4, ":S: Done uninitializing RPC.\n");
  3034. DEBUG_FLUSH();
  3035. }
  3036. BOOL
  3037. FrsRpcInitialize(
  3038. VOID
  3039. )
  3040. /*++
  3041. Routine Description:
  3042. Initializting This thread is kicked off by the main thread. This thread sets up
  3043. the server and client side of RPC for the frsrpc interface.
  3044. Arguments:
  3045. Arg - Needed to set status for our parent.
  3046. Return Value:
  3047. TRUE - RPC has started
  3048. FALSE - RPC could not be started
  3049. --*/
  3050. {
  3051. #undef DEBSUB
  3052. #define DEBSUB "FrsRpcInitialize:"
  3053. BOOL StartedOK = FALSE;
  3054. try {
  3055. //
  3056. // Get the maximum number of concurrent RPC calls out of registry.
  3057. //
  3058. CfgRegReadDWord(FKC_MAX_RPC_SERVER_THREADS, NULL, 0, &MaxRpcServerThreads);
  3059. DPRINT1(0,":S: Max RPC threads is %d\n", MaxRpcServerThreads);
  3060. //
  3061. // Get user specified port assignment for RPC.
  3062. //
  3063. CfgRegReadDWord(FKC_RPC_PORT_ASSIGNMENT, NULL, 0, &RpcPortAssignment);
  3064. DPRINT1(0,":S: RPC port assignment is %d\n", RpcPortAssignment);
  3065. //
  3066. // Register protocol sequences
  3067. //
  3068. RegisterRpcProtseqs();
  3069. DPRINT(0, ":S: FRS RPC protocol sequences registered\n");
  3070. //
  3071. // Register frsrpc interface
  3072. //
  3073. RegisterRpcInterface();
  3074. DPRINT(0, ":S: FRS RPC interface registered\n");
  3075. //
  3076. // Start listening for clients
  3077. //
  3078. StartServerRpc();
  3079. DPRINT(0, ":S: FRS RPC server interface installed\n");
  3080. //
  3081. // Table of sysvols being created
  3082. //
  3083. if (!SysVolsBeingCreated) {
  3084. SysVolsBeingCreated = GTabAllocTable();
  3085. }
  3086. StartedOK = TRUE;
  3087. } except (FrsException(GetExceptionInformation())) {
  3088. DPRINT(0, ":S: Can't start RPC\n");
  3089. }
  3090. //
  3091. // Cleanup
  3092. //
  3093. try {
  3094. if (!StartedOK) {
  3095. ShutDownRpc();
  3096. }
  3097. } except (FrsException(GetExceptionInformation())) {
  3098. DPRINT(0, ":S: Can't shutdown RPC\n");
  3099. }
  3100. //
  3101. // DONE
  3102. //
  3103. //
  3104. // Free up the rpc initialization memory
  3105. //
  3106. SetProcessWorkingSetSize(ProcessHandle, (SIZE_T)-1, (SIZE_T)-1);
  3107. return StartedOK;
  3108. }
  3109. DWORD
  3110. FrsIsPathInReplica(
  3111. IN PWCHAR Path,
  3112. IN PREPLICA Replica,
  3113. OUT BOOL *Replicated
  3114. )
  3115. {
  3116. #undef DEBSUB
  3117. #define DEBSUB "FrsIsPathInReplica:"
  3118. DWORD WStatus = ERROR_SUCCESS;
  3119. PWCHAR ReplicaRoot = NULL;
  3120. PWCHAR TraversedPath = NULL;
  3121. if(Replicated == NULL) {
  3122. return ERROR_INVALID_PARAMETER;
  3123. }
  3124. *Replicated = FALSE;
  3125. WStatus = FrsTraverseReparsePoints(Replica->Root, &ReplicaRoot);
  3126. if ( !WIN_SUCCESS(WStatus) ) {
  3127. DPRINT2(0,"ERROR - FrsTraverseReparsePoints for %ws, WStatus = %d\n", Replica->Root, WStatus);
  3128. goto Exit;
  3129. }
  3130. WStatus = FrsTraverseReparsePoints(Path, &TraversedPath);
  3131. if ( !WIN_SUCCESS(WStatus) ) {
  3132. DPRINT2(0,"ERROR - FrsTraverseReparsePoints for %ws, WStatus = %d\n", Path, WStatus);
  3133. goto Exit;
  3134. }
  3135. if (ReplicaRoot && TraversedPath && (-1 == FrsIsParent(ReplicaRoot, TraversedPath))) {
  3136. *Replicated = TRUE;
  3137. }
  3138. Exit:
  3139. FrsFree(ReplicaRoot);
  3140. FrsFree(TraversedPath);
  3141. return WStatus;
  3142. }
  3143. DWORD
  3144. NtFrsApi_Rpc_IsPathReplicated(
  3145. IN handle_t Handle,
  3146. IN PWCHAR Path,
  3147. IN ULONG ReplicaSetTypeOfInterest,
  3148. OUT ULONG *Replicated,
  3149. OUT ULONG *Primary,
  3150. OUT ULONG *Root,
  3151. OUT GUID *ReplicaSetGuid
  3152. )
  3153. /*++
  3154. Routine Description:
  3155. Checks if the Path given is part of a replica set of type
  3156. ReplicaSetTypeOfInterest. If ReplicaSetTypeOfInterest is 0, will match for
  3157. any replica set type.On successful execution the OUT parameters are set as
  3158. follows:
  3159. Replicated == TRUE iff Path is part of a replica set of type
  3160. ReplicaSetTypeOfInterest
  3161. Primary == 0 if this machine is not the primary for the replica set
  3162. 1 if this machine is the primary for the replica set
  3163. 2 if there is no primary for the replica set
  3164. Root == TRUE iff Path is the root path for the replica
  3165. Arguments:
  3166. Handle -
  3167. Path - the local path to check
  3168. ReplicaSetTypeOfInterest - The type of replica set to match against. Set to
  3169. 0 to match any replica set.
  3170. Replicated - set TRUE iff Path is part of a replica set of type
  3171. ReplicaSetTypeOfInterest.
  3172. If Replicated is FALSE, the other OUT parameters are not set.
  3173. Primary - set to 0 if this machine is not the primary for the replica set
  3174. 1 if this machine is the primary for the replica set
  3175. 2 if there is no primary for the replica set
  3176. Root - set TRUE iff Path is the root path for the replica.
  3177. ReplicaGuid - GUID for the matching replica set.
  3178. GuidSize - MUST be sizeof(GUID)
  3179. Return Value:
  3180. Win32 Status
  3181. --*/
  3182. {
  3183. #undef DEBSUB
  3184. #define DEBSUB "NtFrsApi_Rpc_IsPathReplicated"
  3185. DWORD WStatus;
  3186. try {
  3187. //
  3188. // Checkauthentication if the auth check is not disabled
  3189. // by setting the registry value:
  3190. // Access checks are [Enabled or Disabled]
  3191. // Each API has a different registry location so this
  3192. // can not be put in the rpc callback function.
  3193. //
  3194. WStatus = FrsRpcCheckAuthIfEnabled(Handle, ACX_IS_PATH_REPLICATED);
  3195. CLEANUP_WS(0, "++ ERROR - FrsRpcCheckAuthIfEnabled failed;",
  3196. WStatus, CLEANUP);
  3197. WStatus = FrsRpcAccessChecks(Handle, ACX_IS_PATH_REPLICATED);
  3198. if (!WIN_SUCCESS(WStatus)) {
  3199. goto CLEANUP;
  3200. }
  3201. //
  3202. // Validate parameters
  3203. //
  3204. if((Replicated == NULL) ||
  3205. (Primary == NULL) ||
  3206. (Root == NULL) ||
  3207. (Path == NULL) ||
  3208. (ReplicaSetGuid == NULL)) {
  3209. return FRS_ERR_INVALID_SERVICE_PARAMETER;
  3210. }
  3211. WStatus = FrsIsPathReplicated(Path, ReplicaSetTypeOfInterest, Replicated, Primary, Root, ReplicaSetGuid);
  3212. if (!WIN_SUCCESS(WStatus)) {
  3213. goto CLEANUP;
  3214. }
  3215. //
  3216. // SUCCESS
  3217. //
  3218. WStatus = ERROR_SUCCESS;
  3219. CLEANUP:;
  3220. } except (EXCEPTION_EXECUTE_HANDLER) {
  3221. GET_EXCEPTION_CODE(WStatus);
  3222. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  3223. }
  3224. return WStatus;
  3225. }
  3226. DWORD
  3227. FrsIsPathReplicated(
  3228. IN PWCHAR Path,
  3229. IN ULONG ReplicaSetTypeOfInterest,
  3230. OUT ULONG *Replicated,
  3231. OUT ULONG *Primary,
  3232. OUT ULONG *Root,
  3233. OUT GUID *ReplicaSetGuid
  3234. )
  3235. /*++
  3236. Routine Description:
  3237. Checks if the Path given is part of a replica set of type
  3238. ReplicaSetTypeOfInterest. If ReplicaSetTypeOfInterest is 0, will match for
  3239. any replica set type.On successful execution the OUT parameters are set as
  3240. follows:
  3241. Replicated == TRUE iff Path is part of a replica set of type
  3242. ReplicaSetTypeOfInterest
  3243. Primary == 0 if this machine is not the primary for the replica set
  3244. 1 if this machine is the primary for the replica set
  3245. 2 if there is no primary for the replica set
  3246. Root == TRUE iff Path is the root path for the replica
  3247. Arguments:
  3248. Path - the local path to check
  3249. ReplicaSetTypeOfInterest - The type of replica set to match against. Set to
  3250. 0 to match any replica set.
  3251. Replicated - set TRUE iff Path is part of a replica set of type
  3252. ReplicaSetTypeOfInterest.
  3253. If Replicated is FALSE, the other OUT parameters are not set.
  3254. Primary - set to 0 if this machine is not the primary for the replica set
  3255. 1 if this machine is the primary for the replica set
  3256. 2 if there is no primary for the replica set
  3257. Root - set TRUE iff Path is the root path for the replica.
  3258. ReplicaSetGuid - GUID of the matching replica set
  3259. Return Value:
  3260. Win32 Status
  3261. --*/
  3262. {
  3263. #undef DEBSUB
  3264. #define DEBSUB "FrsIsPathReplicated:"
  3265. DWORD WStatus = ERROR_SUCCESS;
  3266. *Replicated = FALSE;
  3267. //
  3268. // Check active each replica
  3269. //
  3270. ForEachListEntry( &ReplicaListHead, REPLICA, ReplicaList,
  3271. // Loop iterator pE is type PREPLICA.
  3272. if(((ReplicaSetTypeOfInterest == 0) ||
  3273. (ReplicaSetTypeOfInterest == pE->ReplicaSetType))) {
  3274. //
  3275. // Ignoring return code.
  3276. // Even if this check gives an error we still go on to the next
  3277. //
  3278. FrsIsPathInReplica(Path, pE, Replicated);
  3279. if(Replicated) {
  3280. *Primary = (BooleanFlagOn(pE->CnfFlags, CONFIG_FLAG_PRIMARY)?1:0);
  3281. *Root = !_wcsicmp(Path, pE->Root);
  3282. *ReplicaSetGuid = *(pE->SetName->Guid);
  3283. goto Exit;
  3284. }
  3285. }
  3286. );
  3287. //
  3288. // also need to check replicas in error states
  3289. //
  3290. ForEachListEntry( &ReplicaFaultListHead, REPLICA, ReplicaList,
  3291. // Loop iterator pE is type PREPLICA.
  3292. if(((ReplicaSetTypeOfInterest == 0) ||
  3293. (ReplicaSetTypeOfInterest == pE->ReplicaSetType))) {
  3294. //
  3295. // Ignoring return code.
  3296. // Even if this check gives an error we still go on to the next
  3297. //
  3298. FrsIsPathInReplica(Path, pE, Replicated);
  3299. if(Replicated) {
  3300. *Primary = (BooleanFlagOn(pE->CnfFlags, CONFIG_FLAG_PRIMARY)?1:0);
  3301. *Root = !_wcsicmp(Path, pE->Root);
  3302. *ReplicaSetGuid = *(pE->SetName->Guid);
  3303. goto Exit;
  3304. }
  3305. }
  3306. );
  3307. //
  3308. // Don't check stopped replicas. They have probably been deleted.
  3309. //
  3310. Exit:
  3311. return WStatus;
  3312. }