Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2959 lines
78 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. //
  23. // KERBEROS is not available on a server that isn't a member of
  24. // a domain. It is possible for the non-member server to be a
  25. // client of a KERBEROS RPC server but that doesn't help NtFrs;
  26. // NtFrs requires server-to-server RPC.
  27. //
  28. BOOL KerberosIsNotAvailable;
  29. ULONG MaxRpcServerThreads; // Maximum number of concurrent server RPC calls
  30. //
  31. // Binding Stats
  32. //
  33. ULONG RpcBinds;
  34. ULONG RpcUnBinds;
  35. ULONG RpcAgedBinds;
  36. LONG RpcMaxBinds;
  37. //
  38. // Table of sysvols being created
  39. //
  40. PGEN_TABLE SysVolsBeingCreated;
  41. //
  42. // This table translates the FRS API access check code number to registry key table
  43. // code for the enable/disable registry key check and the rights registry key check.
  44. // The FRS_API_ACCESS_CHECKS enum in config.h defines the indices for the
  45. // this table. The order of the entries here must match the order of the entries
  46. // in the ENUM.
  47. //
  48. typedef struct _RPC_API_KEYS_ {
  49. FRS_REG_KEY_CODE Enable; // FRS Registry Key Code for the Access Check enable string
  50. FRS_REG_KEY_CODE Rights; // FRS Registry Key Code for the Access Check rights string
  51. PWCHAR KeyName; // Key name for the API.
  52. } RPC_API_KEYS, *PRPC_API_KEYS;
  53. RPC_API_KEYS RpcApiKeys[ACX_MAX] = {
  54. {FKC_ACCCHK_STARTDS_POLL_ENABLE, FKC_ACCCHK_STARTDS_POLL_RIGHTS, ACK_START_DS_POLL},
  55. {FKC_ACCCHK_SETDS_POLL_ENABLE, FKC_ACCCHK_SETDS_POLL_RIGHTS, ACK_SET_DS_POLL},
  56. {FKC_ACCCHK_GETDS_POLL_ENABLE, FKC_ACCCHK_GETDS_POLL_RIGHTS, ACK_GET_DS_POLL},
  57. {FKC_ACCCHK_GET_INFO_ENABLE, FKC_ACCCHK_GET_INFO_RIGHTS, ACK_INTERNAL_INFO},
  58. {FKC_ACCCHK_PERFMON_ENABLE, FKC_ACCCHK_PERFMON_RIGHTS, ACK_COLLECT_PERFMON_DATA},
  59. {FKC_ACCESS_CHK_DCPROMO_ENABLE, FKC_ACCESS_CHK_DCPROMO_RIGHTS, ACK_DCPROMO}
  60. };
  61. //
  62. // Used by all calls to RpcBindingSetAuthInfoEx()
  63. //
  64. // Version set to value indicated by docs
  65. // Mutual authentication
  66. // Client doesn't change credentials
  67. // Impersonation but not delegation
  68. //
  69. RPC_SECURITY_QOS RpcSecurityQos = {
  70. RPC_C_SECURITY_QOS_VERSION, // static version
  71. RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH, // requires mutual auth
  72. RPC_C_QOS_IDENTITY_STATIC, // client credentials don't change
  73. RPC_C_IMP_LEVEL_IMPERSONATE // server cannot delegate
  74. };
  75. #define DPRINT_USER_NAME(Sev) DPrintUserName(Sev)
  76. ULONG
  77. RcsSubmitCommPktToRcsQueue(
  78. IN handle_t ServerHandle,
  79. IN PCOMM_PACKET CommPkt,
  80. IN PWCHAR AuthClient,
  81. IN PWCHAR AuthName,
  82. IN DWORD AuthLevel,
  83. IN DWORD AuthN,
  84. IN DWORD AuthZ
  85. );
  86. DWORD
  87. FrsDsIsPartnerADc(
  88. IN PWCHAR PartnerName
  89. );
  90. DWORD
  91. FrsDsVerifyPromotionParent(
  92. IN PWCHAR ReplicaSetName,
  93. IN PWCHAR ReplicaSetType
  94. );
  95. DWORD
  96. FrsDsStartPromotionSeeding(
  97. IN BOOL Inbound,
  98. IN PWCHAR ReplicaSetName,
  99. IN PWCHAR ReplicaSetType,
  100. IN PWCHAR CxtionName,
  101. IN PWCHAR PartnerName,
  102. IN PWCHAR PartnerPrincName,
  103. IN ULONG PartnerAuthLevel,
  104. IN ULONG GuidSize,
  105. IN UCHAR *CxtionGuid,
  106. IN UCHAR *PartnerGuid,
  107. OUT UCHAR *ParentGuid
  108. );
  109. VOID
  110. FrsPrintRpcStats(
  111. IN ULONG Severity,
  112. IN PNTFRSAPI_INFO Info, OPTIONAL
  113. IN DWORD Tabs
  114. )
  115. /*++
  116. Routine Description:
  117. Print the rpc stats into the info buffer or using DPRINT (Info == NULL).
  118. Arguments:
  119. Severity - for DPRINT
  120. Info - for IPRINT (use DPRINT if NULL)
  121. Tabs - indentation for prettyprint
  122. Return Value:
  123. None.
  124. --*/
  125. {
  126. #undef DEBSUB
  127. #define DEBSUB "FrsPrintRpcStats:"
  128. WCHAR TabW[MAX_TAB_WCHARS + 1];
  129. InfoTabs(Tabs, TabW);
  130. IDPRINT0(Severity, Info, "\n");
  131. IDPRINT1(Severity, Info, ":S: %wsNTFRS RPC BINDS:\n", TabW);
  132. IDPRINT2(Severity, Info, ":S: %ws Binds : %6d\n", TabW, RpcBinds);
  133. IDPRINT3(Severity, Info, ":S: %ws UnBinds : %6d (%d aged)\n",
  134. TabW, RpcUnBinds, RpcAgedBinds);
  135. IDPRINT2(Severity, Info, ":S: %ws Max Binds : %6d\n", TabW, RpcMaxBinds);
  136. IDPRINT0(Severity, Info, "\n");
  137. }
  138. PVOID
  139. MIDL_user_allocate(
  140. IN size_t Bytes
  141. )
  142. /*++
  143. Routine Description:
  144. Allocate memory for RPC.
  145. XXX This should be using davidor's routines.
  146. Arguments:
  147. Bytes - Number of bytes to allocate.
  148. Return Value:
  149. NULL - memory could not be allocated.
  150. !NULL - address of allocated memory.
  151. --*/
  152. {
  153. #undef DEBSUB
  154. #define DEBSUB "MIDL_user_allocate:"
  155. PVOID VA;
  156. //
  157. // Need to check if Bytes == 0 as FrsAlloc asserts if called with 0 as the first parameter (prefix fix).
  158. //
  159. if (Bytes == 0) {
  160. return NULL;
  161. }
  162. VA = FrsAlloc(Bytes);
  163. return VA;
  164. }
  165. VOID
  166. MIDL_user_free(
  167. IN PVOID Buffer
  168. )
  169. /*++
  170. Routine Description:
  171. Free memory for RPC.
  172. XXX This should be using davidor's routines.
  173. Arguments:
  174. Buffer - Address of memory allocated with MIDL_user_allocate().
  175. Return Value:
  176. None.
  177. --*/
  178. {
  179. #undef DEBSUB
  180. #define DEBSUB "MIDL_user_free:"
  181. FrsFree(Buffer);
  182. }
  183. VOID
  184. DPrintUserName(
  185. IN DWORD Sev
  186. )
  187. /*++
  188. Routine Description:
  189. Print our user name
  190. Arguments:
  191. Sev
  192. Return Value:
  193. None.
  194. --*/
  195. {
  196. #undef DEBSUB
  197. #define DEBSUB "DPrintUserName:"
  198. WCHAR Uname[MAX_PATH + 1];
  199. ULONG Unamesize = MAX_PATH + 1;
  200. if (GetUserName(Uname, &Unamesize)) {
  201. DPRINT1(Sev, "++ User name is %ws\n", Uname);
  202. } else {
  203. DPRINT_WS(0, "++ ERROR - Getting user name;", GetLastError());
  204. }
  205. }
  206. RPC_STATUS
  207. DummyRpcCallback (
  208. IN RPC_IF_ID *Interface,
  209. IN PVOID Context
  210. )
  211. /*++
  212. Routine Description:
  213. Dummy callback routine. By registering this routine, RPC will automatically
  214. refuse requests from clients that don't include authentication info.
  215. WARN: Disabled for now because frs needs to run in dcpromo environments
  216. that do not have any form of authentication.
  217. Arguments:
  218. Ignored
  219. Return Value:
  220. RPC_S_OK
  221. --*/
  222. {
  223. #undef DEBSUB
  224. #define DEBSUB "DummyRpcCallback:"
  225. return RPC_S_OK;
  226. }
  227. DWORD
  228. SERVER_FrsNOP(
  229. handle_t Handle
  230. )
  231. /*++
  232. Routine Description:
  233. The frsrpc interface includes a NOP function for pinging
  234. the server.
  235. Arguments:
  236. None.
  237. Return Value:
  238. None.
  239. --*/
  240. {
  241. #undef DEBSUB
  242. #define DEBSUB "SERVER_FrsNOP:"
  243. return ERROR_SUCCESS;
  244. }
  245. DWORD
  246. SERVER_FrsRpcSendCommPkt(
  247. handle_t Handle,
  248. PCOMM_PACKET CommPkt
  249. )
  250. /*++
  251. Routine Description:
  252. Receiving a command packet
  253. Arguments:
  254. None.
  255. Return Value:
  256. ERROR_SUCCESS - everything was okay
  257. Anything else - the error code says it all
  258. --*/
  259. {
  260. #undef DEBSUB
  261. #define DEBSUB "SERVER_FrsRpcSendCommPkt:"
  262. DWORD WStatus = 0;
  263. DWORD AuthLevel = 0;
  264. DWORD AuthN = 0;
  265. DWORD AuthZ = 0;
  266. PWCHAR AuthName = NULL;
  267. PWCHAR AuthClient = NULL;
  268. //
  269. // Don't send or receive during shutdown
  270. //
  271. if (FrsIsShuttingDown) {
  272. return ERROR_SUCCESS;
  273. }
  274. try {
  275. if (!CommCheckPkt(CommPkt)) {
  276. WStatus = ERROR_NOT_SUPPORTED;
  277. COMMAND_RCV_AUTH_TRACE(0, CommPkt, WStatus, 0, 0,
  278. NULL, NULL, "RcvFailAuth - bad packet");
  279. //
  280. // Increment the Packets Received in Error Counter
  281. //
  282. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvdError, 1);
  283. goto CLEANUP;
  284. }
  285. if (!ServerGuid) {
  286. WStatus = RpcBindingInqAuthClient(Handle,
  287. &AuthClient,
  288. &AuthName,
  289. &AuthLevel,
  290. &AuthN,
  291. &AuthZ);
  292. DPRINT_WS(4, "++ IGNORED - RpcBindingInqAuthClient;", WStatus);
  293. COMMAND_RCV_AUTH_TRACE(4, CommPkt, WStatus, AuthLevel, AuthN,
  294. AuthClient, AuthName, "RcvAuth");
  295. } else {
  296. //
  297. // For hardwired -- Eventually DS Free configs.
  298. //
  299. COMMAND_RCV_AUTH_TRACE(4, CommPkt, WStatus, 0, 0,
  300. NULL, NULL, "RcvAuth - hardwired)");
  301. }
  302. //
  303. // Increment the Packets Received and
  304. // Packets Received in bytes counters
  305. //
  306. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvd, 1);
  307. PM_INC_CTR_SERVICE(PMTotalInst, PacketsRcvdBytes, CommPkt->PktLen);
  308. switch(CommPkt->CsId) {
  309. case CS_RS:
  310. WStatus = RcsSubmitCommPktToRcsQueue(Handle,
  311. CommPkt,
  312. AuthClient,
  313. AuthName,
  314. AuthLevel,
  315. AuthN,
  316. AuthZ);
  317. break;
  318. default:
  319. WStatus = ERROR_INVALID_OPERATION;
  320. COMMAND_RCV_AUTH_TRACE(0, CommPkt, WStatus, 0, 0,
  321. NULL, NULL, "RcvFailAuth - bad csid");
  322. }
  323. CLEANUP:;
  324. } except (EXCEPTION_EXECUTE_HANDLER) {
  325. GET_EXCEPTION_CODE(WStatus);
  326. COMMAND_RCV_AUTH_TRACE(0, CommPkt, WStatus, 0, 0,
  327. NULL, NULL, "RcvFailAuth - exception");
  328. }
  329. try {
  330. if (AuthName) {
  331. RpcStringFree(&AuthName);
  332. }
  333. } except (EXCEPTION_EXECUTE_HANDLER) {
  334. GET_EXCEPTION_CODE(WStatus);
  335. COMMAND_RCV_AUTH_TRACE(0, CommPkt, WStatus, 0, 0,
  336. NULL, NULL, "RcvFailAuth - cleanup exception");
  337. }
  338. return WStatus;
  339. }
  340. DWORD
  341. SERVER_FrsEnumerateReplicaPathnames(
  342. handle_t Handle
  343. )
  344. /*++
  345. Routine Description:
  346. NOT IMPLEMENTED - Enumerate the replica sets
  347. Arguments:
  348. None.
  349. Return Value:
  350. None.
  351. --*/
  352. {
  353. #undef DEBSUB
  354. #define DEBSUB "SERVER_FrsEnumerateReplicaPathnames:"
  355. return ERROR_CALL_NOT_IMPLEMENTED;
  356. }
  357. DWORD
  358. SERVER_FrsFreeReplicaPathnames(
  359. handle_t Handle
  360. )
  361. /*++
  362. Routine Description:
  363. NOT IMPLEMENTED - Just a placeholder, it won't really be part of
  364. the RPC interface but rather a function in the client-side dll.
  365. Arguments:
  366. None.
  367. Return Value:
  368. None.
  369. --*/
  370. {
  371. #undef DEBSUB
  372. #define DEBSUB "SERVER_FrsFreeReplicaPathnames:"
  373. return ERROR_CALL_NOT_IMPLEMENTED;
  374. }
  375. DWORD
  376. SERVER_FrsPrepareForBackup(
  377. handle_t Handle
  378. )
  379. /*++
  380. Routine Description:
  381. NOT IMPLEMENTED - Prepare for backup
  382. Arguments:
  383. None.
  384. Return Value:
  385. None.
  386. --*/
  387. {
  388. #undef DEBSUB
  389. #define DEBSUB "SERVER_FrsPrepareForBackup:"
  390. return ERROR_CALL_NOT_IMPLEMENTED;
  391. }
  392. DWORD
  393. SERVER_FrsBackupComplete(
  394. handle_t Handle
  395. )
  396. /*++
  397. Routine Description:
  398. NOT IMPLEMENTED - backup is complete; reset state
  399. Arguments:
  400. None.
  401. Return Value:
  402. None.
  403. --*/
  404. {
  405. #undef DEBSUB
  406. #define DEBSUB "SERVER_FrsBackupComplete:"
  407. return ERROR_CALL_NOT_IMPLEMENTED;
  408. }
  409. DWORD
  410. SERVER_FrsPrepareForRestore(
  411. handle_t Handle
  412. )
  413. /*++
  414. Routine Description:
  415. NOT IMPLEMENTED - Prepare for restore
  416. Arguments:
  417. None.
  418. Return Value:
  419. None.
  420. --*/
  421. {
  422. #undef DEBSUB
  423. #define DEBSUB "SERVER_FrsPrepareForRestore:"
  424. return ERROR_CALL_NOT_IMPLEMENTED;
  425. }
  426. DWORD
  427. SERVER_FrsRestoreComplete(
  428. handle_t Handle
  429. )
  430. /*++
  431. Routine Description:
  432. NOT IMPLEMENTED - restore is complete; reset state
  433. Arguments:
  434. None.
  435. Return Value:
  436. None.
  437. --*/
  438. {
  439. #undef DEBSUB
  440. #define DEBSUB "SERVER_FrsRestoreComplete:"
  441. return ERROR_CALL_NOT_IMPLEMENTED;
  442. }
  443. DWORD
  444. FrsRpcAccessChecks(
  445. IN HANDLE ServerHandle,
  446. IN DWORD RpcApiIndex
  447. )
  448. /*++
  449. Routine Description:
  450. Check if the caller has access to this rpc api call.
  451. Arguments:
  452. ServerHandle - From the rpc runtime
  453. RpcApiIndex - identifies key in registry
  454. Return Value:
  455. Win32 Status
  456. --*/
  457. {
  458. #undef DEBSUB
  459. #define DEBSUB "FrsRpcAccessChecks:"
  460. DWORD WStatus;
  461. PWCHAR WStr = NULL, TrimStr;
  462. FRS_REG_KEY_CODE EnableKey, RightsKey;
  463. DWORD ValueSize;
  464. BOOL RequireRead;
  465. BOOL Impersonated = FALSE;
  466. HKEY HRpcApiKey = 0;
  467. PWCHAR ApiName;
  468. WCHAR ValueBuf[MAX_PATH + 1];
  469. if (RpcApiIndex >= ACX_MAX) {
  470. DPRINT1(0, "++ ERROR - ApiIndex out of range. (%d)\n", RpcApiIndex);
  471. FRS_ASSERT(!"RpcApiIndexout of range");
  472. return ERROR_INVALID_PARAMETER;
  473. }
  474. EnableKey = RpcApiKeys[RpcApiIndex].Enable;
  475. RightsKey = RpcApiKeys[RpcApiIndex].Rights;
  476. ApiName = RpcApiKeys[RpcApiIndex].KeyName;
  477. //
  478. // First go fetch the enable/disable string.
  479. //
  480. WStatus = CfgRegReadString(EnableKey, NULL, 0, &WStr);
  481. if (WStr == NULL) {
  482. DPRINT1_WS(0, "++ ERROR - API Access enable check for API (%ws) failed.", ApiName, WStatus);
  483. WStatus = ERROR_NO_TOKEN;
  484. goto CLEANUP;
  485. }
  486. //
  487. // If access checks are disabled then we're done.
  488. //
  489. TrimStr = FrsWcsTrim(WStr, L' ');
  490. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DISABLED) ||
  491. WSTR_EQ(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)) {
  492. WStatus = ERROR_SUCCESS;
  493. goto CLEANUP;
  494. }
  495. if (WSTR_NE(TrimStr, ACCESS_CHECKS_ARE_ENABLED) &&
  496. WSTR_NE(TrimStr, ACCESS_CHECKS_ARE_DEFAULT_ENABLED)) {
  497. DPRINT2(0, "++ ERROR - Invalid parameter API Access enable check for API (%ws) :%ws\n",
  498. ApiName, TrimStr );
  499. WStatus = ERROR_CANTREAD;
  500. goto CLEANUP;
  501. }
  502. //
  503. // Fetch the access rights string that tells us if we need to check for
  504. // read or write access.
  505. //
  506. WStr = FrsFree(WStr);
  507. WStatus = CfgRegReadString(RightsKey, NULL, 0, &WStr);
  508. if (WStr == NULL) {
  509. DPRINT1_WS(0, "++ ERROR - API Access rights check for API (%ws) failed.", ApiName, WStatus);
  510. WStatus = ERROR_NO_TOKEN;
  511. goto CLEANUP;
  512. }
  513. TrimStr = FrsWcsTrim(WStr, L' ');
  514. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_READ) ||
  515. WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_DEFAULT_READ)) {
  516. RequireRead = TRUE;
  517. } else
  518. if (WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_WRITE) ||
  519. WSTR_EQ(TrimStr, ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE)) {
  520. RequireRead = FALSE;
  521. } else {
  522. DPRINT2(0, "++ ERROR - Invalid parameter API Access rights check for API (%ws) :%ws\n",
  523. ApiName, TrimStr );
  524. WStatus = ERROR_CANTREAD;
  525. goto CLEANUP;
  526. }
  527. //
  528. // Impersonate the caller
  529. //
  530. if (ServerHandle != NULL) {
  531. WStatus = RpcImpersonateClient(ServerHandle);
  532. CLEANUP1_WS(0, "++ ERROR - Can't impersonate caller for API Access check for API (%ws).",
  533. ApiName, WStatus, CLEANUP);
  534. Impersonated = TRUE;
  535. }
  536. //
  537. // Open the key, with the selected access so the system can check if the
  538. // ACL on the key (presumably set by the admin) gives this user sufficient
  539. // rights. If the test succeeds then we allow API call to proceed.
  540. //
  541. WStatus = CfgRegOpenKey(RightsKey,
  542. NULL,
  543. (RequireRead) ? FRS_RKF_KEY_ACCCHK_READ :
  544. FRS_RKF_KEY_ACCCHK_WRITE,
  545. &HRpcApiKey);
  546. CLEANUP2_WS(0, "++ ERROR - API Access check failed for API (%ws) :%ws",
  547. ApiName, TrimStr, WStatus, CLEANUP);
  548. //
  549. // Access is allowed.
  550. //
  551. DPRINT2(4, "++ Access Check Okay: %s access for API (%ws)\n",
  552. (RequireRead) ? "read" : "write", ApiName);
  553. WStatus = ERROR_SUCCESS;
  554. CLEANUP:
  555. if (HANDLE_IS_VALID(HRpcApiKey)) {
  556. RegCloseKey(HRpcApiKey);
  557. }
  558. //
  559. // Access checks failed, register event
  560. //
  561. if (!WIN_SUCCESS(WStatus)) {
  562. WStatus = FRS_ERR_INSUFFICIENT_PRIV;
  563. //
  564. // Include user name if impersonation succeeded
  565. //
  566. if (Impersonated) {
  567. ValueSize = MAX_PATH;
  568. if (GetUserName(ValueBuf, &ValueSize)) {
  569. EPRINT3(EVENT_FRS_ACCESS_CHECKS_FAILED_USER,
  570. ApiName, ACCESS_CHECKS_ARE, ValueBuf);
  571. } else {
  572. EPRINT2(EVENT_FRS_ACCESS_CHECKS_FAILED_UNKNOWN,
  573. ApiName, ACCESS_CHECKS_ARE);
  574. }
  575. } else {
  576. EPRINT2(EVENT_FRS_ACCESS_CHECKS_FAILED_UNKNOWN,
  577. ApiName, ACCESS_CHECKS_ARE);
  578. }
  579. }
  580. if (Impersonated) {
  581. RpcRevertToSelf();
  582. }
  583. FrsFree(WStr);
  584. return WStatus;
  585. }
  586. DWORD
  587. CheckAuth(
  588. IN HANDLE ServerHandle
  589. )
  590. /*++
  591. Routine Description:
  592. Check if the caller has the correct authentication
  593. Arguments:
  594. ServerHandle
  595. Return Value:
  596. Win32 Status
  597. --*/
  598. {
  599. #undef DEBSUB
  600. #define DEBSUB "CheckAuth:"
  601. DWORD WStatus;
  602. DWORD AuthLevel;
  603. DWORD AuthN;
  604. WStatus = RpcBindingInqAuthClient(ServerHandle, NULL, NULL, &AuthLevel,
  605. &AuthN, NULL);
  606. if (!WIN_SUCCESS(WStatus)) {
  607. DPRINT_WS(0, "++ ERROR - RpcBindingInqAuthClient", WStatus);
  608. return WStatus;
  609. }
  610. //
  611. // Encrypted packet
  612. //
  613. if (AuthLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) {
  614. DPRINT1(4, "++ Authlevel is %d; not RPC_C_AUTHN_LEVEL_PKT_PRIVACE\n", AuthLevel);
  615. return ERROR_NOT_AUTHENTICATED;
  616. }
  617. //
  618. // KERBEROS
  619. //
  620. if (AuthN != RPC_C_AUTHN_GSS_KERBEROS &&
  621. AuthN != RPC_C_AUTHN_GSS_NEGOTIATE) {
  622. DPRINT1(4, "++ AuthN is %d; not RPC_C_AUTHN_GSS_KERBEROS/NEGOTIATE\n", AuthN);
  623. return ERROR_NOT_AUTHENTICATED;
  624. }
  625. //
  626. // SUCCESS; RPC is authenticated, encrypted kerberos
  627. //
  628. return ERROR_SUCCESS;
  629. }
  630. DWORD
  631. NtFrsApi_Rpc_Bind(
  632. IN PWCHAR MachineName,
  633. OUT PWCHAR *OutPrincName,
  634. OUT handle_t *OutHandle,
  635. OUT ULONG *OutParentAuthLevel
  636. )
  637. /*++
  638. Routine Description:
  639. Bind to the NtFrs service on MachineName (this machine if NULL)
  640. using an unauthencated, un-encrypted binding.
  641. Arguments:
  642. MachineName - Bind to the service on this computer. The computer
  643. name can be any RPC-bindable name. Usually, the
  644. NetBIOS or DNS name works just fine. The NetBIOS
  645. name can be found with GetComputerName() or
  646. hostname. The DNS name can be found with
  647. gethostbyname() or ipconfig /all. If NULL, the
  648. service on this computer is contacted. The service
  649. is contacted using Secure RPC.
  650. OutPrincName - Principle name for MachineName
  651. OutHandle - Bound, resolved, authenticated handle
  652. OutParentAuthLevel - Authentication type and level
  653. (Always CXTION_AUTH_NONE)
  654. Return Value:
  655. Win32 Status
  656. --*/
  657. {
  658. #undef DEBSUB
  659. #define DEBSUB "NtFrsApi_Rpc_Bind:"
  660. DWORD WStatus, WStatus1;
  661. handle_t Handle = NULL;
  662. PWCHAR BindingString = NULL;
  663. try {
  664. //
  665. // Return value
  666. //
  667. *OutHandle = NULL;
  668. *OutPrincName = NULL;
  669. *OutParentAuthLevel = CXTION_AUTH_NONE;
  670. //
  671. // Create a binding string to NtFrs on some machine. Trim leading \\
  672. //
  673. FRS_TRIM_LEADING_2SLASH(MachineName);
  674. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  675. NULL, NULL, &BindingString);
  676. CLEANUP1_WS(0, "++ ERROR - Composing binding to %ws;",
  677. MachineName, WStatus, CLEANUP);
  678. //
  679. // Store the binding in the handle
  680. //
  681. WStatus = RpcBindingFromStringBinding(BindingString, &Handle);
  682. CLEANUP1_WS(0, "++ ERROR - From binding for %ws;", MachineName, WStatus, CLEANUP);
  683. //
  684. // Resolve the binding to the dynamic endpoint
  685. //
  686. WStatus = RpcEpResolveBinding(Handle, frsrpc_ClientIfHandle);
  687. CLEANUP1_WS(0, "++ ERROR - Resolving binding for %ws;",
  688. MachineName, WStatus, CLEANUP);
  689. //
  690. // SUCCESS
  691. //
  692. *OutHandle = Handle;
  693. *OutPrincName = FrsWcsDup(MachineName);
  694. Handle = NULL;
  695. WStatus = ERROR_SUCCESS;
  696. DPRINT3(4, "++ NtFrsApi Bound to %ws (PrincName: %ws) Auth %d\n",
  697. MachineName, *OutPrincName, *OutParentAuthLevel);
  698. CLEANUP:;
  699. } except (EXCEPTION_EXECUTE_HANDLER) {
  700. //
  701. // Exception (may be RPC)
  702. //
  703. GET_EXCEPTION_CODE(WStatus);
  704. DPRINT_WS(0, "++ ERROR - Exception -", WStatus);
  705. }
  706. //
  707. // Clean up any handles, events, memory, ...
  708. //
  709. try {
  710. if (BindingString) {
  711. WStatus1 = RpcStringFreeW(&BindingString);
  712. DPRINT_WS(0, "++ WARN - RpcStringFreeW;", WStatus1);
  713. }
  714. if (Handle) {
  715. WStatus1 = RpcBindingFree(&Handle);
  716. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus1);
  717. }
  718. } except (EXCEPTION_EXECUTE_HANDLER) {
  719. //
  720. // Exception (may be RPC)
  721. //
  722. GET_EXCEPTION_CODE(WStatus);
  723. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  724. }
  725. return WStatus;
  726. }
  727. DWORD
  728. NtFrsApi_Rpc_BindEx(
  729. IN PWCHAR MachineName,
  730. OUT PWCHAR *OutPrincName,
  731. OUT handle_t *OutHandle,
  732. OUT ULONG *OutParentAuthLevel
  733. )
  734. /*++
  735. Routine Description:
  736. Bind to the NtFrs service on MachineName (this machine if NULL)
  737. using an authenticated, encrypted binding.
  738. Arguments:
  739. MachineName - Bind to the service on this computer. The computer
  740. name can be any RPC-bindable name. Usually, the
  741. NetBIOS or DNS name works just fine. The NetBIOS
  742. name can be found with GetComputerName() or
  743. hostname. The DNS name can be found with
  744. gethostbyname() or ipconfig /all. If NULL, the
  745. service on this computer is contacted. The service
  746. is contacted using Secure RPC.
  747. OutPrincName - Principle name for MachineName
  748. OutHandle - Bound, resolved, authenticated handle
  749. OutParentAuthLevel - Authentication type and level
  750. (Always CXTION_AUTH_KERBEROS_FULL)
  751. Return Value:
  752. Win32 Status
  753. --*/
  754. {
  755. #undef DEBSUB
  756. #define DEBSUB "NtFrsApi_Rpc_BindEx:"
  757. DWORD WStatus, WStatus1;
  758. PWCHAR InqPrincName = NULL;
  759. handle_t Handle = NULL;
  760. PWCHAR PrincName = NULL;
  761. PWCHAR BindingString = NULL;
  762. try {
  763. //
  764. // Return value
  765. //
  766. *OutHandle = NULL;
  767. *OutPrincName = NULL;
  768. *OutParentAuthLevel = CXTION_AUTH_KERBEROS_FULL;
  769. //
  770. // Create a binding string to NtFrs on some machine. Trim leading \\
  771. //
  772. FRS_TRIM_LEADING_2SLASH(MachineName);
  773. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  774. NULL, NULL, &BindingString);
  775. CLEANUP1_WS(0, "++ ERROR - Composing binding to %ws;",
  776. MachineName, WStatus, CLEANUP);
  777. //
  778. // Store the binding in the handle
  779. //
  780. WStatus = RpcBindingFromStringBinding(BindingString, &Handle);
  781. CLEANUP1_WS(0, "++ ERROR - From binding for %ws;", MachineName, WStatus, CLEANUP);
  782. //
  783. // Resolve the binding to the dynamic endpoint
  784. //
  785. WStatus = RpcEpResolveBinding(Handle, frsrpc_ClientIfHandle);
  786. CLEANUP1_WS(0, "++ ERROR - Resolving binding for %ws;",
  787. MachineName, WStatus, CLEANUP);
  788. //
  789. // Find the principle name
  790. //
  791. WStatus = RpcMgmtInqServerPrincName(Handle,
  792. RPC_C_AUTHN_GSS_NEGOTIATE,
  793. &InqPrincName);
  794. CLEANUP1_WS(0, "++ ERROR - Inq PrincName for %ws;", MachineName, WStatus, CLEANUP);
  795. PrincName = FrsWcsDup(InqPrincName);
  796. RpcStringFree(&InqPrincName);
  797. InqPrincName = NULL;
  798. //
  799. // Set authentication info
  800. //
  801. if (MutualAuthenticationIsEnabled) {
  802. WStatus = RpcBindingSetAuthInfoEx(Handle,
  803. PrincName,
  804. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  805. RPC_C_AUTHN_GSS_NEGOTIATE,
  806. NULL,
  807. RPC_C_AUTHZ_NONE,
  808. &RpcSecurityQos);
  809. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  810. MachineName, PrincName, WStatus);
  811. } else {
  812. WStatus = ERROR_NOT_SUPPORTED;
  813. }
  814. //
  815. // Fall back to manual mutual authentication
  816. //
  817. if (!WIN_SUCCESS(WStatus)) {
  818. WStatus = RpcBindingSetAuthInfo(Handle,
  819. PrincName,
  820. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  821. RPC_C_AUTHN_GSS_NEGOTIATE,
  822. NULL,
  823. RPC_C_AUTHZ_NONE);
  824. }
  825. CLEANUP1_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws);",
  826. MachineName, WStatus, CLEANUP);
  827. //
  828. // SUCCESS
  829. //
  830. *OutHandle = Handle;
  831. *OutPrincName = PrincName;
  832. Handle = NULL;
  833. PrincName = NULL;
  834. WStatus = ERROR_SUCCESS;
  835. DPRINT3(4, "++ NtFrsApi Bound to %ws (PrincName: %ws) Auth %d\n",
  836. MachineName, *OutPrincName, *OutParentAuthLevel);
  837. CLEANUP:;
  838. } except (EXCEPTION_EXECUTE_HANDLER) {
  839. //
  840. // Exception (may be RPC)
  841. //
  842. GET_EXCEPTION_CODE(WStatus);
  843. DPRINT_WS(0, "++ Error - Exception.", WStatus);
  844. }
  845. //
  846. // Clean up any handles, events, memory, ...
  847. //
  848. try {
  849. if (BindingString) {
  850. WStatus1 = RpcStringFreeW(&BindingString);
  851. DPRINT_WS(0, "++ WARN - RpcStringFreeW;", WStatus1);
  852. }
  853. if (PrincName) {
  854. PrincName = FrsFree(PrincName);
  855. }
  856. if (Handle) {
  857. WStatus1 = RpcBindingFree(&Handle);
  858. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus1);
  859. }
  860. } except (EXCEPTION_EXECUTE_HANDLER) {
  861. //
  862. // Exception (may be RPC)
  863. //
  864. GET_EXCEPTION_CODE(WStatus);
  865. DPRINT_WS(0, "++ Error - Cleanup Exception.", WStatus);
  866. }
  867. return WStatus;
  868. }
  869. GUID DummyGuid;
  870. BOOL CommitDemotionInProgress;
  871. DWORD
  872. NtFrsApi_Rpc_StartDemotionW(
  873. IN handle_t Handle,
  874. IN PWCHAR ReplicaSetName
  875. )
  876. /*++
  877. Routine Description:
  878. Start demoting the sysvol. Basically, tombstone the replica set.
  879. Arguments:
  880. Handle
  881. ReplicaSetName - Replica set name
  882. Return Value:
  883. Win32 Status
  884. --*/
  885. {
  886. #undef DEBSUB
  887. #define DEBSUB "NtFrsApi_Rpc_StartDemotionW:"
  888. DWORD WStatus;
  889. PWCHAR SysVolName;
  890. BOOL UnLockGenTable = FALSE;
  891. BOOL DeleteFromGenTable = FALSE;
  892. try {
  893. //
  894. // Display params
  895. //
  896. DPRINT1(0, ":S: Start Demotion: %ws\n", ReplicaSetName);
  897. //
  898. // Check parameters
  899. //
  900. if (!ReplicaSetName) {
  901. DPRINT(0, "++ ERROR - Parameter is NULL\n");
  902. WStatus = FRS_ERR_INVALID_SERVICE_PARAMETER;
  903. goto CLEANUP;
  904. }
  905. WStatus = FrsRpcAccessChecks(Handle, ACX_DCPROMO);
  906. CLEANUP1_WS(0, "++ ERROR - FrsRpcAccessChecks(%ws);",
  907. ReplicaSetName, WStatus, CLEANUP);
  908. //
  909. // Can't promote/demote the same sysvol at the same time!
  910. //
  911. UnLockGenTable = TRUE;
  912. GTabLockTable(SysVolsBeingCreated);
  913. SysVolName = GTabLookupNoLock(SysVolsBeingCreated, &DummyGuid, ReplicaSetName);
  914. if (SysVolName) {
  915. DPRINT1(0, "++ ERROR - Promoting/Demoting %ws twice\n", ReplicaSetName);
  916. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  917. goto CLEANUP;
  918. }
  919. if (CommitDemotionInProgress) {
  920. DPRINT(0, "++ ERROR - Commit demotion in progress.\n");
  921. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  922. goto CLEANUP;
  923. }
  924. DeleteFromGenTable = TRUE;
  925. GTabInsertEntryNoLock(SysVolsBeingCreated,
  926. ReplicaSetName,
  927. &DummyGuid,
  928. ReplicaSetName);
  929. UnLockGenTable = FALSE;
  930. GTabUnLockTable(SysVolsBeingCreated);
  931. //
  932. // Delete the replica set
  933. //
  934. WStatus = FrsDsStartDemotion(ReplicaSetName);
  935. if (!WIN_SUCCESS(WStatus)) {
  936. DPRINT_WS(0, "++ ERROR - demoting;", WStatus);
  937. WStatus = FRS_ERR_SYSVOL_DEMOTE;
  938. goto CLEANUP;
  939. }
  940. //
  941. // SUCCESS
  942. //
  943. WStatus = ERROR_SUCCESS;
  944. DPRINT2(0, ":S: Success demoting %ws from %ws\n", ReplicaSetName, ComputerName);
  945. CLEANUP:;
  946. } except (EXCEPTION_EXECUTE_HANDLER) {
  947. //
  948. // Exception (may be RPC)
  949. //
  950. GET_EXCEPTION_CODE(WStatus);
  951. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  952. }
  953. try {
  954. if (UnLockGenTable) {
  955. GTabUnLockTable(SysVolsBeingCreated);
  956. }
  957. if (DeleteFromGenTable) {
  958. GTabDelete(SysVolsBeingCreated, &DummyGuid, ReplicaSetName, NULL);
  959. }
  960. } except (EXCEPTION_EXECUTE_HANDLER) {
  961. GET_EXCEPTION_CODE(WStatus);
  962. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  963. }
  964. return WStatus;
  965. }
  966. DWORD
  967. NtFrsApi_Rpc_CommitDemotionW(
  968. IN handle_t Handle
  969. )
  970. /*++
  971. Routine Description:
  972. The sysvols have been demoted. Mark them as "do not animate."
  973. Arguments:
  974. Handle
  975. Return Value:
  976. Win32 Status
  977. --*/
  978. {
  979. #undef DEBSUB
  980. #define DEBSUB "NtFrsApi_Rpc_CommitDemotionW:"
  981. DWORD WStatus;
  982. PWCHAR SysVolName;
  983. PVOID Key;
  984. BOOL UnLockGenTable = FALSE;
  985. try {
  986. //
  987. // Display params
  988. //
  989. DPRINT(0, ":S: Commit Demotion:\n");
  990. WStatus = FrsRpcAccessChecks(Handle, ACX_DCPROMO);
  991. CLEANUP_WS(0, "++ ERROR - FrsRpcAccessChecks();", WStatus, CLEANUP);
  992. //
  993. // Can't promote/demote the same sysvol at the same time!
  994. //
  995. Key = NULL;
  996. UnLockGenTable = TRUE;
  997. GTabLockTable(SysVolsBeingCreated);
  998. SysVolName = GTabNextDatumNoLock(SysVolsBeingCreated, &Key);
  999. if (SysVolName) {
  1000. DPRINT(0, "++ ERROR - Promoting/Demoting during commit\n");
  1001. WStatus = FRS_ERR_SYSVOL_IS_BUSY;
  1002. goto CLEANUP;
  1003. }
  1004. CommitDemotionInProgress = TRUE;
  1005. UnLockGenTable = FALSE;
  1006. GTabUnLockTable(SysVolsBeingCreated);
  1007. //
  1008. // Create the replica set
  1009. //
  1010. WStatus = FrsDsCommitDemotion();
  1011. if (!WIN_SUCCESS(WStatus)) {
  1012. DPRINT_WS(0, "++ ERROR - Commit demotion;", WStatus);
  1013. WStatus = FRS_ERR_SYSVOL_DEMOTE;
  1014. goto CLEANUP;
  1015. }
  1016. //
  1017. // SUCCESS
  1018. //
  1019. WStatus = ERROR_SUCCESS;
  1020. DPRINT1(0, ":S: Success commit demotion on %ws.\n", ComputerName);
  1021. CLEANUP:;
  1022. } except (EXCEPTION_EXECUTE_HANDLER) {
  1023. //
  1024. // Exception (may be RPC)
  1025. //
  1026. GET_EXCEPTION_CODE(WStatus);
  1027. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1028. }
  1029. try {
  1030. CommitDemotionInProgress = FALSE;
  1031. if (UnLockGenTable) {
  1032. GTabUnLockTable(SysVolsBeingCreated);
  1033. }
  1034. } except (EXCEPTION_EXECUTE_HANDLER) {
  1035. //
  1036. // Exception (may be RPC)
  1037. //
  1038. GET_EXCEPTION_CODE(WStatus);
  1039. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1040. }
  1041. return WStatus;
  1042. }
  1043. DWORD
  1044. SERVER_FrsRpcVerifyPromotionParent(
  1045. IN handle_t Handle,
  1046. IN PWCHAR ParentAccount,
  1047. IN PWCHAR ParentPassword,
  1048. IN PWCHAR ReplicaSetName,
  1049. IN PWCHAR ReplicaSetType,
  1050. IN ULONG ParentAuthLevel,
  1051. IN ULONG GuidSize
  1052. )
  1053. /*++
  1054. Routine Description:
  1055. OBSOLETE API
  1056. Verify the account on the parent computer. The parent computer
  1057. supplies the initial copy of the indicated sysvol.
  1058. Arguments:
  1059. Handle
  1060. ParentAccount - Valid account on ParentComputer
  1061. ParentPassword - Valid password for ParentAccount
  1062. ReplicaSetName - Replica set name
  1063. ReplicaSetType - Replica set type
  1064. ParentAuthLevel - Authentication type and level
  1065. GuidSize - sizeof(GUID)
  1066. Return Value:
  1067. Win32 Status
  1068. --*/
  1069. {
  1070. #undef DEBSUB
  1071. #define DEBSUB "SERVER_FrsRpcVerifyPromotionParent:"
  1072. return ERROR_CALL_NOT_IMPLEMENTED;
  1073. }
  1074. DWORD
  1075. SERVER_FrsRpcVerifyPromotionParentEx(
  1076. IN handle_t Handle,
  1077. IN PWCHAR ParentAccount,
  1078. IN PWCHAR ParentPassword,
  1079. IN PWCHAR ReplicaSetName,
  1080. IN PWCHAR ReplicaSetType,
  1081. IN PWCHAR CxtionName,
  1082. IN PWCHAR PartnerName,
  1083. IN PWCHAR PartnerPrincName,
  1084. IN PWCHAR ParentPrincName,
  1085. IN ULONG PartnerAuthLevel,
  1086. IN ULONG GuidSize
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. OBSOLETE API
  1091. Verify as much of the comm paths and parameters as possible so
  1092. that dcpromo fails early.
  1093. Arguments:
  1094. Handle
  1095. ParentAccount - Valid account on ParentComputer
  1096. ParentPassword - Valid password for ParentAccount
  1097. ReplicaSetName - Replica set name
  1098. ReplicaSetType - Replica set type
  1099. CxtionName - printable name for cxtion
  1100. PartnerName - RPC bindable name
  1101. PartnerPrincName - Server principle name for kerberos
  1102. ParentPrincName - Principle name used to bind to this computer
  1103. PartnerAuthLevel - Authentication type and level
  1104. GuidSize - sizeof array addressed by Guid
  1105. Return Value:
  1106. Win32 Status
  1107. --*/
  1108. {
  1109. #undef DEBSUB
  1110. #define DEBSUB "SERVER_FrsRpcVerifyPromotionParentEx:"
  1111. DWORD WStatus, WStatus1;
  1112. GNAME GName;
  1113. handle_t PartnerHandle = NULL;
  1114. return ERROR_CALL_NOT_IMPLEMENTED;
  1115. }
  1116. DWORD
  1117. LOCAL_FrsRpcVerifyPromotionParent(
  1118. IN handle_t Handle,
  1119. IN PWCHAR ParentAccount,
  1120. IN PWCHAR ParentPassword,
  1121. IN PWCHAR ReplicaSetName,
  1122. IN PWCHAR ReplicaSetType,
  1123. IN ULONG ParentAuthLevel,
  1124. IN ULONG GuidSize
  1125. )
  1126. /*++
  1127. Routine Description:
  1128. Verify the account on the parent computer. The parent computer
  1129. supplies the initial copy of the indicated sysvol.
  1130. Arguments:
  1131. Handle
  1132. ParentAccount - Valid account on ParentComputer
  1133. ParentPassword - Valid password for ParentAccount
  1134. ReplicaSetName - Replica set name
  1135. ReplicaSetType - Replica set type
  1136. ParentAuthLevel - Authentication type and level
  1137. GuidSize - sizeof(GUID)
  1138. Return Value:
  1139. Win32 Status
  1140. --*/
  1141. {
  1142. #undef DEBSUB
  1143. #define DEBSUB "LOCAL_FrsRpcVerifyPromotionParent:"
  1144. DWORD WStatus;
  1145. try {
  1146. //
  1147. // Display params
  1148. //
  1149. DPRINT(0, ":S: SERVER Verify Promotion Parent:\n");
  1150. DPRINT1(0, ":S: \tAccount : %ws\n", ParentAccount);
  1151. DPRINT1(0, ":S: \tSetName : %ws\n", ReplicaSetName);
  1152. DPRINT1(0, ":S: \tSetType : %ws\n", ReplicaSetType);
  1153. DPRINT1(0, ":S: \tAuthLevel: %d\n", ParentAuthLevel);
  1154. //
  1155. // Check Authentication
  1156. //
  1157. if (ParentAuthLevel == CXTION_AUTH_KERBEROS_FULL) {
  1158. //
  1159. // Parent must be a DC
  1160. //
  1161. if (!IsADc) {
  1162. DPRINT(0, "++ ERROR - Parent is not a DC\n");
  1163. goto ERR_PARENT_AUTHENTICATION;
  1164. }
  1165. //
  1166. // Must be encrypted
  1167. //
  1168. WStatus = CheckAuth(Handle);
  1169. CLEANUP_WS(0, "++ ERROR - auth;", WStatus, ERR_PARENT_AUTHENTICATION);
  1170. } else {
  1171. goto ERR_INVALID_SERVICE_PARAMETER;
  1172. }
  1173. //
  1174. // Guid
  1175. //
  1176. if (GuidSize != sizeof(GUID)) {
  1177. DPRINT3(0, "++ ERROR - %ws: GuidSize is %d, not %d\n",
  1178. ReplicaSetName, GuidSize, sizeof(GUID));
  1179. goto ERR_INVALID_SERVICE_PARAMETER;
  1180. }
  1181. //
  1182. // Check parameters
  1183. //
  1184. if (!ReplicaSetName || !ReplicaSetType) {
  1185. DPRINT(0, "++ ERROR - Parameter is NULL\n");
  1186. goto ERR_INVALID_SERVICE_PARAMETER;
  1187. }
  1188. if (_wcsicmp(ReplicaSetType, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
  1189. _wcsicmp(ReplicaSetType, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
  1190. DPRINT1(0, "++ ERROR - ReplicaSetType is %ws\n", ReplicaSetType);
  1191. goto ERR_INVALID_SERVICE_PARAMETER;
  1192. }
  1193. //
  1194. // Verify the replica set
  1195. //
  1196. WStatus = FrsDsVerifyPromotionParent(ReplicaSetName, ReplicaSetType);
  1197. CLEANUP2_WS(0, "++ ERROR - verifying set %ws on parent %ws;",
  1198. ReplicaSetName, ComputerName, WStatus, ERR_SYSVOL_POPULATE);
  1199. //
  1200. // SUCCESS
  1201. //
  1202. DPRINT3(0, ":S: Success Verifying promotion parent %ws %ws %ws\n",
  1203. ParentAccount, ReplicaSetName, ReplicaSetType);
  1204. WStatus = ERROR_SUCCESS;
  1205. goto CLEANUP;
  1206. ERR_INVALID_SERVICE_PARAMETER:
  1207. WStatus = FRS_ERR_INVALID_SERVICE_PARAMETER;
  1208. goto CLEANUP;
  1209. ERR_PARENT_AUTHENTICATION:
  1210. WStatus = FRS_ERR_PARENT_AUTHENTICATION;
  1211. goto CLEANUP;
  1212. ERR_SYSVOL_POPULATE:
  1213. WStatus = FRS_ERR_SYSVOL_POPULATE;
  1214. CLEANUP:;
  1215. } except (EXCEPTION_EXECUTE_HANDLER) {
  1216. //
  1217. // Exception (may be RPC)
  1218. //
  1219. GET_EXCEPTION_CODE(WStatus);
  1220. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1221. }
  1222. return WStatus;
  1223. }
  1224. DWORD
  1225. SERVER_FrsRpcStartPromotionParent(
  1226. IN handle_t Handle,
  1227. IN PWCHAR ParentAccount,
  1228. IN PWCHAR ParentPassword,
  1229. IN PWCHAR ReplicaSetName,
  1230. IN PWCHAR ReplicaSetType,
  1231. IN PWCHAR CxtionName,
  1232. IN PWCHAR PartnerName,
  1233. IN PWCHAR PartnerPrincName,
  1234. IN ULONG PartnerAuthLevel,
  1235. IN ULONG GuidSize,
  1236. IN UCHAR *CxtionGuid,
  1237. IN UCHAR *PartnerGuid,
  1238. OUT UCHAR *ParentGuid
  1239. )
  1240. /*++
  1241. Routine Description:
  1242. Setup a volatile cxtion on the parent for seeding the indicated
  1243. sysvol on the caller.
  1244. Arguments:
  1245. Handle
  1246. ParentAccount - Valid account on ParentComputer
  1247. ParentPassword - Valid password for ParentAccount
  1248. ReplicaSetName - Replica set name
  1249. ReplicaSetType - Replica set type
  1250. CxtionName - printable name for cxtion
  1251. PartnerName - RPC bindable name
  1252. PartnerPrincName - Server principle name for kerberos
  1253. PartnerAuthLevel - Authentication type and level
  1254. GuidSize - sizeof array addressed by Guid
  1255. CxtionGuid - temporary: used for volatile cxtion
  1256. PartnerGuid - temporary: used to find set on partner
  1257. ParentGuid - Used as partner guid on inbound cxtion
  1258. Return Value:
  1259. Win32 Status
  1260. --*/
  1261. {
  1262. #undef DEBSUB
  1263. #define DEBSUB "SERVER_FrsRpcStartPromotionParent:"
  1264. DWORD WStatus;
  1265. try {
  1266. //
  1267. // Display params
  1268. //
  1269. DPRINT(0, ":S: SERVER Start Promotion Parent:\n");
  1270. DPRINT1(0, ":S: \tPartner : %ws\n", PartnerName);
  1271. DPRINT1(0, ":S: \tPartnerPrinc : %ws\n", PartnerPrincName);
  1272. DPRINT1(0, ":S: \tAuthLevel : %d\n", PartnerAuthLevel);
  1273. DPRINT1(0, ":S: \tAccount : %ws\n", ParentAccount);
  1274. DPRINT1(0, ":S: \tSetName : %ws\n", ReplicaSetName);
  1275. DPRINT1(0, ":S: \tSetType : %ws\n", ReplicaSetType);
  1276. DPRINT1(0, ":S: \tCxtionName : %ws\n", CxtionName);
  1277. //
  1278. // Verify parameters
  1279. //
  1280. WStatus = LOCAL_FrsRpcVerifyPromotionParent(Handle,
  1281. ParentAccount,
  1282. ParentPassword,
  1283. ReplicaSetName,
  1284. ReplicaSetType,
  1285. PartnerAuthLevel,
  1286. GuidSize);
  1287. CLEANUP_WS(0, "++ ERROR - verify;", WStatus, CLEANUP);
  1288. //
  1289. // Check Authentication
  1290. //
  1291. if (PartnerAuthLevel == CXTION_AUTH_KERBEROS_FULL) {
  1292. //
  1293. // Parent must be a DC
  1294. //
  1295. if (!IsADc) {
  1296. DPRINT(0, "++ ERROR - Parent is not a DC\n");
  1297. WStatus = ERROR_NO_SUCH_DOMAIN;
  1298. goto CLEANUP;
  1299. }
  1300. //
  1301. // Our partner's computer object (or user object) should
  1302. // have the "I am a DC" flag set.
  1303. //
  1304. if (!FrsDsIsPartnerADc(PartnerName)) {
  1305. DPRINT(0, "++ ERROR - Partner is not a DC\n");
  1306. WStatus = ERROR_TRUSTED_DOMAIN_FAILURE;
  1307. goto CLEANUP;
  1308. }
  1309. } else {
  1310. WStatus = FRS_ERR_INVALID_SERVICE_PARAMETER;
  1311. goto CLEANUP;
  1312. }
  1313. //
  1314. // Setup the outbound cxtion
  1315. //
  1316. WStatus = FrsDsStartPromotionSeeding(FALSE,
  1317. ReplicaSetName,
  1318. ReplicaSetType,
  1319. CxtionName,
  1320. PartnerName,
  1321. PartnerPrincName,
  1322. PartnerAuthLevel,
  1323. GuidSize,
  1324. CxtionGuid,
  1325. PartnerGuid,
  1326. ParentGuid);
  1327. CLEANUP_WS(0, "++ ERROR - ds start;", WStatus, CLEANUP);
  1328. //
  1329. // SUCCESS
  1330. //
  1331. DPRINT3(0, ":S: Success starting promotion parent %ws %ws %ws\n",
  1332. ParentAccount, ReplicaSetName, ReplicaSetType);
  1333. WStatus = ERROR_SUCCESS;
  1334. CLEANUP:;
  1335. } except (EXCEPTION_EXECUTE_HANDLER) {
  1336. //
  1337. // Exception (may be RPC)
  1338. //
  1339. GET_EXCEPTION_CODE(WStatus);
  1340. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1341. }
  1342. return WStatus;
  1343. }
  1344. BOOL
  1345. IsFacilityFrs(
  1346. IN DWORD WStatus
  1347. )
  1348. /*++
  1349. Routine Description:
  1350. Is this an FRS specific error status
  1351. Arguments:
  1352. WStatus - Win32 Error Status
  1353. Return Value:
  1354. TRUE - Is an FRS specific error status
  1355. FALSE -
  1356. --*/
  1357. {
  1358. #undef DEBSUB
  1359. #define DEBSUB "IsFacilityFrs:"
  1360. // TODO: replace these constants with symbollic values from winerror.h
  1361. return ( (WStatus >= 8000) && (WStatus < 8200) );
  1362. }
  1363. DWORD
  1364. NtFrsApi_Rpc_StartPromotionW(
  1365. IN handle_t Handle,
  1366. IN PWCHAR ParentComputer,
  1367. IN PWCHAR ParentAccount,
  1368. IN PWCHAR ParentPassword,
  1369. IN PWCHAR ReplicaSetName,
  1370. IN PWCHAR ReplicaSetType,
  1371. IN ULONG ReplicaSetPrimary,
  1372. IN PWCHAR ReplicaSetStage,
  1373. IN PWCHAR ReplicaSetRoot
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. OBSOLETE API
  1378. Start the promotion process by seeding the indicated sysvol.
  1379. Arguments:
  1380. Handle
  1381. ParentComputer - DNS or NetBIOS name of the parent supplying the sysvol
  1382. ParentAccount - Valid account on ParentComputer
  1383. ParentPassword - Valid password for ParentAccount
  1384. ReplicaSetName - Replica set name
  1385. ReplicaSetType - Type of set (Enterprise or Domain)
  1386. ReplicaSetPrimary - 1=Primary; 0=not
  1387. ReplicaSetStage - Staging path
  1388. ReplicaSetRoot - Root path
  1389. Return Value:
  1390. Win32 Status
  1391. --*/
  1392. {
  1393. #undef DEBSUB
  1394. #define DEBSUB "NtFrsApi_Rpc_StartPromotionW:"
  1395. DWORD WStatus, WStatus1;
  1396. GUID PlaceHolderGuid;
  1397. GUID ParentGuid;
  1398. PWCHAR SysVolName;
  1399. ULONG ParentAuthLevel;
  1400. PWCHAR ParentPrincName = NULL;
  1401. handle_t ParentHandle = NULL;
  1402. BOOL DeleteFromGenTable = FALSE;
  1403. BOOL UnLockGenTable = FALSE;
  1404. return ERROR_CALL_NOT_IMPLEMENTED;
  1405. }
  1406. DWORD
  1407. NtFrsApi_Rpc_VerifyPromotionW(
  1408. IN handle_t Handle,
  1409. IN PWCHAR ParentComputer,
  1410. IN PWCHAR ParentAccount,
  1411. IN PWCHAR ParentPassword,
  1412. IN PWCHAR ReplicaSetName,
  1413. IN PWCHAR ReplicaSetType,
  1414. IN ULONG ReplicaSetPrimary,
  1415. IN PWCHAR ReplicaSetStage,
  1416. IN PWCHAR ReplicaSetRoot
  1417. )
  1418. /*++
  1419. Routine Description:
  1420. OBSOLETE API
  1421. Verify that sysvol promotion is likely.
  1422. Arguments:
  1423. Handle
  1424. ParentComputer - DNS or NetBIOS name of the parent supplying the sysvol
  1425. ParentAccount - Valid account on ParentComputer
  1426. ParentPassword - Valid password for ParentAccount
  1427. ReplicaSetName - Replica set name
  1428. ReplicaSetType - Type of set (Enterprise or Domain)
  1429. ReplicaSetPrimary - 1=Primary; 0=not
  1430. ReplicaSetStage - Staging path
  1431. ReplicaSetRoot - Root path
  1432. Return Value:
  1433. Win32 Status
  1434. --*/
  1435. {
  1436. #undef DEBSUB
  1437. #define DEBSUB "NtFrsApi_Rpc_VerifyPromotionW:"
  1438. DWORD WStatus, WStatus1;
  1439. ULONG ParentAuthLevel;
  1440. PWCHAR ParentPrincName = NULL;
  1441. handle_t ParentHandle = NULL;
  1442. return ERROR_CALL_NOT_IMPLEMENTED;
  1443. }
  1444. DWORD
  1445. NtFrsApi_Rpc_PromotionStatusW(
  1446. IN handle_t Handle,
  1447. IN PWCHAR ReplicaSetName,
  1448. OUT ULONG *ServiceState,
  1449. OUT ULONG *ServiceWStatus,
  1450. OUT PWCHAR *ServiceDisplay OPTIONAL
  1451. )
  1452. /*++
  1453. Routine Description:
  1454. OBSOLETE API
  1455. Status of the seeding of the indicated sysvol
  1456. Arguments:
  1457. Handle
  1458. ReplicaSetName - Replica set name
  1459. ServiceState - State of the service
  1460. ServiceWStatus - Win32 Status if state is NTFRSAPI_SERVICE_ERROR
  1461. ServiceDisplay - Display string if state is NTFRSAPI_SERVICE_PROMOTING
  1462. Return Value:
  1463. Win32 Status
  1464. --*/
  1465. {
  1466. #undef DEBSUB
  1467. #define DEBSUB "NtFrsApi_Rpc_PromotionStatusW:"
  1468. DWORD WStatus;
  1469. PREPLICA Replica;
  1470. return ERROR_CALL_NOT_IMPLEMENTED;
  1471. }
  1472. DWORD
  1473. NtFrsApi_Rpc_Get_DsPollingIntervalW(
  1474. IN handle_t Handle,
  1475. OUT ULONG *Interval,
  1476. OUT ULONG *LongInterval,
  1477. OUT ULONG *ShortInterval
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. Get the current polling intervals in minutes.
  1482. Arguments:
  1483. Handle
  1484. Interval - Current interval in minutes
  1485. LongInterval - Long interval in minutes
  1486. ShortInterval - Short interval in minutes
  1487. Return Value:
  1488. Win32 Status
  1489. --*/
  1490. {
  1491. #undef DEBSUB
  1492. #define DEBSUB "NtFrsApi_Rpc_Get_DsPollingIntervalW"
  1493. DWORD WStatus;
  1494. try {
  1495. WStatus = FrsRpcAccessChecks(Handle, ACX_GET_DS_POLL);
  1496. if (!WIN_SUCCESS(WStatus)) {
  1497. goto CLEANUP;
  1498. }
  1499. WStatus = FrsDsGetDsPollingInterval(Interval, LongInterval, ShortInterval);
  1500. if (!WIN_SUCCESS(WStatus)) {
  1501. goto CLEANUP;
  1502. }
  1503. //
  1504. // SUCCESS
  1505. //
  1506. WStatus = ERROR_SUCCESS;
  1507. CLEANUP:;
  1508. } except (EXCEPTION_EXECUTE_HANDLER) {
  1509. GET_EXCEPTION_CODE(WStatus);
  1510. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1511. }
  1512. //
  1513. // Cleanup memory, handles, ...
  1514. //
  1515. try {
  1516. } except (EXCEPTION_EXECUTE_HANDLER) {
  1517. GET_EXCEPTION_CODE(WStatus);
  1518. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1519. }
  1520. return WStatus;
  1521. }
  1522. DWORD
  1523. NtFrsApi_Rpc_Set_DsPollingIntervalW(
  1524. IN handle_t Handle,
  1525. IN ULONG UseShortInterval,
  1526. IN ULONG LongInterval,
  1527. IN ULONG ShortInterval
  1528. )
  1529. /*++
  1530. Routine Description:
  1531. Adjust the polling interval and kick off a new polling cycle.
  1532. The kick is ignored if a polling cycle is in progress.
  1533. The intervals are given in minutes.
  1534. Arguments:
  1535. Handle
  1536. UseShortInterval - If non-zero, use short interval. Otherwise, long.
  1537. LongInterval - Long interval in minutes
  1538. ShortInterval - Short interval in minutes
  1539. Return Value:
  1540. Win32 Status
  1541. --*/
  1542. {
  1543. #undef DEBSUB
  1544. #define DEBSUB "NtFrsApi_Rpc_Set_DsPollingIntervalW"
  1545. DWORD WStatus;
  1546. try {
  1547. WStatus = FrsRpcAccessChecks(Handle,
  1548. (!LongInterval && !ShortInterval) ?
  1549. ACX_START_DS_POLL:
  1550. ACX_SET_DS_POLL);
  1551. if (!WIN_SUCCESS(WStatus)) {
  1552. goto CLEANUP;
  1553. }
  1554. WStatus = FrsDsSetDsPollingInterval(UseShortInterval,
  1555. LongInterval,
  1556. ShortInterval);
  1557. if (!WIN_SUCCESS(WStatus)) {
  1558. goto CLEANUP;
  1559. }
  1560. //
  1561. // SUCCESS
  1562. //
  1563. WStatus = ERROR_SUCCESS;
  1564. CLEANUP:;
  1565. } except (EXCEPTION_EXECUTE_HANDLER) {
  1566. GET_EXCEPTION_CODE(WStatus);
  1567. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1568. }
  1569. //
  1570. // Cleanup memory, handles, ...
  1571. //
  1572. try {
  1573. } except (EXCEPTION_EXECUTE_HANDLER) {
  1574. GET_EXCEPTION_CODE(WStatus);
  1575. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1576. }
  1577. return WStatus;
  1578. }
  1579. DWORD
  1580. NtFrsApi_Rpc_InfoW(
  1581. IN handle_t Handle,
  1582. IN ULONG BlobSize,
  1583. IN OUT PBYTE Blob
  1584. )
  1585. /*++
  1586. Routine Description:
  1587. Return internal info (see private\net\inc\ntfrsapi.h).
  1588. Arguments:
  1589. Handle
  1590. BlobSize - total bytes of Blob
  1591. Blob - details desired info and provides buffer for info
  1592. Return Value:
  1593. Win32 Status
  1594. --*/
  1595. {
  1596. #undef DEBSUB
  1597. #define DEBSUB "NtFrsApi_Rpc_InfoW:"
  1598. DWORD WStatus;
  1599. try {
  1600. WStatus = FrsRpcAccessChecks(Handle, ACX_INTERNAL_INFO);
  1601. if (!WIN_SUCCESS(WStatus)) {
  1602. goto CLEANUP;
  1603. }
  1604. WStatus = Info(BlobSize, Blob);
  1605. if (!WIN_SUCCESS(WStatus)) {
  1606. goto CLEANUP;
  1607. }
  1608. //
  1609. // SUCCESS
  1610. //
  1611. WStatus = ERROR_SUCCESS;
  1612. CLEANUP:;
  1613. } except (EXCEPTION_EXECUTE_HANDLER) {
  1614. GET_EXCEPTION_CODE(WStatus);
  1615. DPRINT_WS(0, "++ ERROR - Exception.", WStatus);
  1616. }
  1617. //
  1618. // Cleanup memory, handles, ...
  1619. //
  1620. try {
  1621. } except (EXCEPTION_EXECUTE_HANDLER) {
  1622. GET_EXCEPTION_CODE(WStatus);
  1623. DPRINT_WS(0, "++ ERROR - Cleanup Exception.", WStatus);
  1624. }
  1625. return WStatus;
  1626. }
  1627. VOID
  1628. RegisterRpcProtseqs(
  1629. )
  1630. /*++
  1631. Routine Description:
  1632. Register the RPC protocol sequences and the authentication
  1633. that FRS supports. Currently, this is only TCP/IP authenticated
  1634. with kerberos.
  1635. Arguments:
  1636. None.
  1637. Return Value:
  1638. None.
  1639. --*/
  1640. {
  1641. #undef DEBSUB
  1642. #define DEBSUB "RegisterRpcProtseqs:"
  1643. DWORD WStatus;
  1644. RPC_STATUS Status;
  1645. PWCHAR InqPrincName = NULL;
  1646. //
  1647. // Register TCP/IP Protocol Sequence
  1648. //
  1649. Status = RpcServerUseProtseq(PROTSEQ_TCP_IP, MaxRpcServerThreads, NULL);
  1650. if (!RPC_SUCCESS(Status)) {
  1651. DPRINT1_WS(0, "++ ERROR - RpcServerUseProtSeq(%ws);", PROTSEQ_TCP_IP, Status);
  1652. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1653. }
  1654. //
  1655. // Register named pipe Protocol Sequence
  1656. //
  1657. Status = RpcServerUseProtseq(PROTSEQ_NAMED_PIPE, MaxRpcServerThreads, NULL);
  1658. DPRINT1_WS(0, "++ WARN - RpcServerUseProtSeq(%ws);", PROTSEQ_NAMED_PIPE, Status);
  1659. //
  1660. // For hardwired -- Eventually DS Free configs.
  1661. // Don't bother with kerberos if emulating multiple machines
  1662. //
  1663. if (ServerGuid) {
  1664. return;
  1665. }
  1666. //
  1667. // Get our principle name
  1668. //
  1669. if (ServerPrincName) {
  1670. ServerPrincName = FrsFree(ServerPrincName);
  1671. }
  1672. Status = RpcServerInqDefaultPrincName(RPC_C_AUTHN_GSS_NEGOTIATE, &InqPrincName);
  1673. DPRINT1_WS(4, ":S: RpcServerInqDefaultPrincname(%d);", RPC_C_AUTHN_GSS_NEGOTIATE, Status);
  1674. //
  1675. // No principle name; KERBEROS may not be available
  1676. //
  1677. if (!RPC_SUCCESS(Status)) {
  1678. //
  1679. // Don't use any authentication if this server is not part of a domain.
  1680. //
  1681. DSROLE_PRIMARY_DOMAIN_INFO_BASIC *DsRole;
  1682. //
  1683. // Is this a member server?
  1684. //
  1685. WStatus = DsRoleGetPrimaryDomainInformation(NULL,
  1686. DsRolePrimaryDomainInfoBasic,
  1687. (PBYTE *)&DsRole);
  1688. if (!WIN_SUCCESS(WStatus)) {
  1689. DPRINT_WS(0, "++ ERROR - Can't get Ds role info;", WStatus);
  1690. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1691. return;
  1692. }
  1693. //
  1694. // Standalone server; ignore authentication for now
  1695. // Hmmm, it seems we become a member server early
  1696. // in the dcpromo process. Oh, well...
  1697. //
  1698. // Hmmm, it seems that a NT4 to NT5 PDC doesn't
  1699. // have kerberos during dcpromo. This is getting
  1700. // old...
  1701. //
  1702. // if (DsRole->MachineRole == DsRole_RoleStandaloneServer ||
  1703. // DsRole->MachineRole == DsRole_RoleMemberServer) {
  1704. DsRoleFreeMemory(DsRole);
  1705. ServerPrincName = FrsWcsDup(ComputerName);
  1706. KerberosIsNotAvailable = TRUE;
  1707. DPRINT(0, ":S: WARN - KERBEROS IS NOT ENABLED!\n");
  1708. DPRINT1(4, ":S: Server Principal Name (no kerberos) is %ws\n",
  1709. ServerPrincName);
  1710. return;
  1711. // }
  1712. DsRoleFreeMemory(DsRole);
  1713. DPRINT1_WS(0, ":S: ERROR - RpcServerInqDefaultPrincName(%ws) failed;", ComputerName, Status);
  1714. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1715. } else {
  1716. DPRINT2(4, ":S: RpcServerInqDefaultPrincname(%d, %ws) success\n",
  1717. RPC_C_AUTHN_GSS_NEGOTIATE, InqPrincName);
  1718. ServerPrincName = FrsWcsDup(InqPrincName);
  1719. RpcStringFree(&InqPrincName);
  1720. InqPrincName = NULL;
  1721. }
  1722. //
  1723. // Register with the KERBEROS authentication service
  1724. //
  1725. //
  1726. // Enable GSS_KERBEROS for pre-Beta3 compatability. When can we remove??
  1727. //
  1728. KerberosIsNotAvailable = FALSE;
  1729. DPRINT1(4, ":S: Server Principal Name is %ws\n", ServerPrincName);
  1730. Status = RpcServerRegisterAuthInfo(ServerPrincName,
  1731. RPC_C_AUTHN_GSS_KERBEROS,
  1732. NULL,
  1733. NULL);
  1734. if (!RPC_SUCCESS(Status)) {
  1735. DPRINT1_WS(0, "++ ERROR - RpcServerRegisterAuthInfo(KERBEROS, %ws) failed;",
  1736. ComputerName, Status);
  1737. FrsRaiseException(FRS_ERROR_PROTSEQ, Status);
  1738. } else {
  1739. DPRINT2(4, ":S: RpcServerRegisterAuthInfo(%ws, %d) success\n",
  1740. ServerPrincName, RPC_C_AUTHN_GSS_KERBEROS);
  1741. }
  1742. //
  1743. // Enable GSS_NEGOTIATE for future usage
  1744. //
  1745. Status = RpcServerRegisterAuthInfo(ServerPrincName,
  1746. RPC_C_AUTHN_GSS_NEGOTIATE,
  1747. NULL,
  1748. NULL);
  1749. DPRINT2_WS(4, ":S: RpcServerRegisterAuthInfo(%ws, %d);",
  1750. ServerPrincName, RPC_C_AUTHN_GSS_NEGOTIATE, Status);
  1751. DPRINT1_WS(0, "++ WARN - RpcServerRegisterAuthInfo(NEGOTIATE, %ws) failed;",
  1752. ComputerName, Status);
  1753. }
  1754. VOID
  1755. RegisterRpcInterface(
  1756. )
  1757. /*++
  1758. Routine Description:
  1759. Register the frsrpc interface for the RPC protocol sequences
  1760. previously registered.
  1761. Arguments:
  1762. None.
  1763. Return Value:
  1764. None.
  1765. --*/
  1766. {
  1767. #undef DEBSUB
  1768. #define DEBSUB "RegisterRpcInterface:"
  1769. RPC_STATUS Status;
  1770. //
  1771. // Service RPC
  1772. //
  1773. Status = RpcServerRegisterIfEx(SERVER_frsrpc_ServerIfHandle,
  1774. NULL,
  1775. NULL,
  1776. 0,
  1777. MaxRpcServerThreads,
  1778. NULL);
  1779. if (!RPC_SUCCESS(Status)) {
  1780. DPRINT_WS(0, "++ ERROR - Can't register NtFrs Service;", Status);
  1781. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  1782. }
  1783. //
  1784. // API RPC
  1785. //
  1786. Status = RpcServerRegisterIfEx(NtFrsApi_ServerIfHandle,
  1787. NULL,
  1788. NULL,
  1789. 0,
  1790. MaxRpcServerThreads,
  1791. NULL);
  1792. if (!RPC_SUCCESS(Status)) {
  1793. DPRINT_WS(0, "++ ERROR - Can't register NtFrs API;", Status);
  1794. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  1795. }
  1796. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  1797. //
  1798. // PERFMON RPC
  1799. //
  1800. Status = RpcServerRegisterIfEx(PerfFrs_ServerIfHandle,
  1801. NULL,
  1802. NULL,
  1803. 0,
  1804. MaxRpcServerThreads,
  1805. NULL);
  1806. if (!RPC_SUCCESS(Status)) {
  1807. DPRINT_WS(0, "++ ERROR - Can't register PERFMON SERVICE;", Status);
  1808. FrsRaiseException(FRS_ERROR_REGISTERIF, Status);
  1809. }
  1810. }
  1811. }
  1812. VOID
  1813. StartServerRpc(
  1814. )
  1815. /*++
  1816. Routine Description:
  1817. Register the endpoints for each of the protocol sequences that
  1818. the frsrpc interface supports and then listen for client requests.
  1819. Arguments:
  1820. None.
  1821. Return Value:
  1822. None.
  1823. --*/
  1824. {
  1825. #undef DEBSUB
  1826. #define DEBSUB "StartServerRpc:"
  1827. RPC_STATUS Status, Status1;
  1828. UUID_VECTOR Uuids;
  1829. UUID_VECTOR *pUuids = NULL;
  1830. RPC_BINDING_VECTOR *BindingVector = NULL;
  1831. //
  1832. // The protocol sequences that frsrpc is registered for
  1833. //
  1834. Status = RpcServerInqBindings(&BindingVector);
  1835. if (!RPC_SUCCESS(Status)) {
  1836. DPRINT_WS(0, "++ ERROR - Can't get binding vector;", Status);
  1837. FrsRaiseException(FRS_ERROR_INQ_BINDINGS, Status);
  1838. }
  1839. //
  1840. // Register endpoints with the endpoint mapper (RPCSS)
  1841. //
  1842. if (ServerGuid) {
  1843. //
  1844. // For hardwired -- Eventually DS Free configs.
  1845. //
  1846. Uuids.Count = 1;
  1847. Uuids.Uuid[0] = ServerGuid;
  1848. pUuids = &Uuids;
  1849. }
  1850. //
  1851. // Service RPC
  1852. //
  1853. Status = RpcEpRegister(SERVER_frsrpc_ServerIfHandle,
  1854. BindingVector,
  1855. pUuids,
  1856. L"NtFrs Service");
  1857. if (!RPC_SUCCESS(Status)) {
  1858. DPRINT_WS(0, "++ ERROR - Can't register NtFrs Service Ep;", Status);
  1859. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  1860. }
  1861. //
  1862. // API RPC
  1863. //
  1864. Status = RpcEpRegister(NtFrsApi_ServerIfHandle,
  1865. BindingVector,
  1866. NULL,
  1867. L"NtFrs API");
  1868. if (!RPC_SUCCESS(Status)) {
  1869. DPRINT_WS(0, "++ ERROR - Can't register NtFrs API Ep;", Status);
  1870. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  1871. }
  1872. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  1873. //
  1874. // PERFMON RPC
  1875. //
  1876. Status = RpcEpRegister(PerfFrs_ServerIfHandle,
  1877. BindingVector,
  1878. NULL,
  1879. L"PERFMON SERVICE");
  1880. if (!RPC_SUCCESS(Status)) {
  1881. DPRINT1(0, "++ ERROR - Can't register PERFMON SERVICE Ep; RStatus %d\n",
  1882. Status);
  1883. FrsRaiseException(FRS_ERROR_REGISTEREP, Status);
  1884. }
  1885. }
  1886. //
  1887. // Listen for client requests
  1888. //
  1889. Status = RpcServerListen(1, MaxRpcServerThreads, TRUE);
  1890. if (!RPC_SUCCESS(Status)) {
  1891. DPRINT_WS(0, "++ ERROR - Can't listen;", Status);
  1892. FrsRaiseException(FRS_ERROR_LISTEN, Status);
  1893. }
  1894. Status1 = RpcBindingVectorFree(&BindingVector);
  1895. DPRINT_WS(0, "++ WARN - RpcBindingVectorFree;", Status1);
  1896. }
  1897. PWCHAR
  1898. FrsRpcDns2Machine(
  1899. IN PWCHAR DnsName
  1900. )
  1901. /*++
  1902. Routine Description:
  1903. Convert a DNS name(machine....) into a computer name.
  1904. Arguments:
  1905. DnsName
  1906. Return Value:
  1907. Computer name
  1908. --*/
  1909. {
  1910. #undef DEBSUB
  1911. #define DEBSUB "FrsRpcDns2Machine:"
  1912. PWCHAR Machine;
  1913. ULONG Period;
  1914. //
  1915. // Find the period
  1916. //
  1917. if (DnsName) {
  1918. Period = wcscspn(DnsName, L".");
  1919. } else {
  1920. return FrsWcsDup(DnsName);
  1921. }
  1922. if (DnsName[Period] != L'.') {
  1923. return FrsWcsDup(DnsName);
  1924. }
  1925. Machine = FrsAlloc((Period + 1) * sizeof(WCHAR));
  1926. CopyMemory(Machine, DnsName, Period * sizeof(WCHAR));
  1927. Machine[Period] = L'\0';
  1928. DPRINT2(4, ":S: Dns %ws to Machine %ws\n", DnsName, Machine);
  1929. return Machine;
  1930. }
  1931. DWORD
  1932. FrsRpcBindToServerGuid(
  1933. IN PGNAME Name,
  1934. OUT handle_t *Handle
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. Set up the bindings to our inbound/outbound partner.
  1939. Arguments:
  1940. Name
  1941. Handle
  1942. Return Value:
  1943. Win32 Status
  1944. --*/
  1945. {
  1946. #undef DEBSUB
  1947. #define DEBSUB "FrsRpcBindToServerGuid:"
  1948. DWORD WStatus;
  1949. LONG DeltaBinds;
  1950. PWCHAR GuidStr = NULL;
  1951. PWCHAR BindingString = NULL;
  1952. PWCHAR MachineName;
  1953. FRS_ASSERT(RPC_S_OK == ERROR_SUCCESS);
  1954. FRS_ASSERT(ServerGuid);
  1955. //
  1956. // Emulating multiple machines with hardwired config
  1957. //
  1958. if (Name->Guid != NULL) {
  1959. WStatus = UuidToString(Name->Guid, &GuidStr);
  1960. CLEANUP_WS(0, "++ ERROR - Translating Guid to string;", WStatus, CLEANUP);
  1961. }
  1962. //
  1963. // Basically, bind to the server's RPC name on this machine. Trim leading \\
  1964. //
  1965. MachineName = Name->Name;
  1966. FRS_TRIM_LEADING_2SLASH(MachineName);
  1967. WStatus = RpcStringBindingCompose(GuidStr, PROTSEQ_TCP_IP, MachineName,
  1968. NULL, NULL, &BindingString);
  1969. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  1970. //
  1971. // Store the binding in the handle
  1972. //
  1973. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  1974. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  1975. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  1976. //
  1977. // Some simple stats for debugging
  1978. //
  1979. DeltaBinds = ++RpcBinds - RpcUnBinds;
  1980. if (DeltaBinds > RpcMaxBinds) {
  1981. RpcMaxBinds = DeltaBinds;
  1982. }
  1983. // Fall through
  1984. CLEANUP:
  1985. if (BindingString) {
  1986. RpcStringFreeW(&BindingString);
  1987. }
  1988. if (GuidStr) {
  1989. RpcStringFree(&GuidStr);
  1990. }
  1991. //
  1992. // We are now ready to talk to the server using the frsrpc interfaces
  1993. //
  1994. return WStatus;
  1995. }
  1996. DWORD
  1997. FrsRpcBindToServerNotService(
  1998. IN PGNAME Name,
  1999. IN PWCHAR PrincName,
  2000. IN ULONG AuthLevel,
  2001. OUT handle_t *Handle
  2002. )
  2003. /*++
  2004. Routine Description:
  2005. Set up the bindings to our inbound/outbound partner.
  2006. Arguments:
  2007. Name
  2008. PrincName
  2009. AuthLevel
  2010. Handle
  2011. Return Value:
  2012. Win32 Status
  2013. --*/
  2014. {
  2015. #undef DEBSUB
  2016. #define DEBSUB "FrsRpcBindToServerNotSevice:"
  2017. DWORD WStatus;
  2018. LONG DeltaBinds;
  2019. PWCHAR InqPrincName = NULL;
  2020. PWCHAR BindingString = NULL;
  2021. PWCHAR MachineName;
  2022. //
  2023. // Basically, bind to the server's RPC name on this machine. Trim leading \\
  2024. //
  2025. MachineName = Name->Name;
  2026. FRS_TRIM_LEADING_2SLASH(MachineName);
  2027. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  2028. NULL, NULL, &BindingString);
  2029. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  2030. //
  2031. // Store the binding in the handle
  2032. //
  2033. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  2034. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  2035. //
  2036. // Not authenticating
  2037. //
  2038. if (KerberosIsNotAvailable ||
  2039. AuthLevel == CXTION_AUTH_NONE) {
  2040. goto done;
  2041. }
  2042. //
  2043. // When not running as a service, we can't predict our
  2044. // principle name so simply resolve the binding.
  2045. //
  2046. WStatus = RpcEpResolveBinding(*Handle, frsrpc_ClientIfHandle);
  2047. CLEANUP_WS(4, "++ ERROR: resolving binding;", WStatus, CLEANUP);
  2048. WStatus = RpcMgmtInqServerPrincName(*Handle,
  2049. RPC_C_AUTHN_GSS_NEGOTIATE,
  2050. &InqPrincName);
  2051. CLEANUP_WS(0, "++ ERROR: resolving PrincName;", WStatus, CLEANUP);
  2052. DPRINT1(4, ":S: Inq PrincName is %ws\n", InqPrincName);
  2053. //
  2054. // Put our authentication info into the handle
  2055. //
  2056. if (MutualAuthenticationIsEnabled) {
  2057. WStatus = RpcBindingSetAuthInfoEx(*Handle,
  2058. InqPrincName,
  2059. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2060. RPC_C_AUTHN_GSS_NEGOTIATE,
  2061. NULL,
  2062. RPC_C_AUTHZ_NONE,
  2063. &RpcSecurityQos);
  2064. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  2065. Name->Name, InqPrincName, WStatus);
  2066. } else {
  2067. WStatus = ERROR_NOT_SUPPORTED;
  2068. }
  2069. //
  2070. // Fall back to manual mutual authentication
  2071. //
  2072. if (!WIN_SUCCESS(WStatus)) {
  2073. WStatus = RpcBindingSetAuthInfo(*Handle,
  2074. InqPrincName,
  2075. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2076. RPC_C_AUTHN_GSS_NEGOTIATE,
  2077. NULL,
  2078. RPC_C_AUTHZ_NONE);
  2079. }
  2080. CLEANUP2_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws, %ws);",
  2081. Name->Name, InqPrincName, WStatus, CLEANUP);
  2082. //
  2083. // SUCCESS
  2084. //
  2085. WStatus = ERROR_SUCCESS;
  2086. done:
  2087. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  2088. //
  2089. // Some simple stats for debugging
  2090. //
  2091. DeltaBinds = ++RpcBinds - RpcUnBinds;
  2092. if (DeltaBinds > RpcMaxBinds) {
  2093. RpcMaxBinds = DeltaBinds;
  2094. }
  2095. // Fall through
  2096. CLEANUP:
  2097. if (BindingString) {
  2098. RpcStringFreeW(&BindingString);
  2099. }
  2100. if (InqPrincName) {
  2101. RpcStringFree(&InqPrincName);
  2102. }
  2103. //
  2104. // We are now ready to talk to the server using the frsrpc interfaces
  2105. //
  2106. return WStatus;
  2107. }
  2108. DWORD
  2109. FrsRpcBindToServer(
  2110. IN PGNAME Name,
  2111. IN PWCHAR PrincName,
  2112. IN ULONG AuthLevel,
  2113. OUT handle_t *Handle
  2114. )
  2115. /*++
  2116. Routine Description:
  2117. Set up the bindings to our inbound/outbound partner.
  2118. Arguments:
  2119. Name
  2120. PrincName
  2121. AuthLevel
  2122. Handle
  2123. Return Value:
  2124. Win32 Status
  2125. --*/
  2126. {
  2127. #undef DEBSUB
  2128. #define DEBSUB "FrsRpcBindToServer:"
  2129. DWORD WStatus;
  2130. LONG DeltaBinds;
  2131. PWCHAR BindingString = NULL;
  2132. PWCHAR MachineName;
  2133. FRS_ASSERT(RPC_S_OK == ERROR_SUCCESS);
  2134. //
  2135. // Emulating multiple machines with hardwired config
  2136. // For hardwired -- Eventually DS Free configs.
  2137. //
  2138. if (ServerGuid) {
  2139. return (FrsRpcBindToServerGuid(Name, Handle));
  2140. }
  2141. //
  2142. // Not running as a service; relax binding constraints
  2143. //
  2144. if (!RunningAsAService) {
  2145. return (FrsRpcBindToServerNotService(Name, PrincName, AuthLevel, Handle));
  2146. }
  2147. //
  2148. // Basically, bind to the NtFrs running on Name. Trim leading \\
  2149. //
  2150. MachineName = Name->Name;
  2151. FRS_TRIM_LEADING_2SLASH(MachineName);
  2152. WStatus = RpcStringBindingCompose(NULL, PROTSEQ_TCP_IP, MachineName,
  2153. NULL, NULL, &BindingString);
  2154. CLEANUP1_WS(0, "++ ERROR - Composing for %ws;", Name->Name, WStatus, CLEANUP);
  2155. //
  2156. // Store the binding in the handle
  2157. //
  2158. WStatus = RpcBindingFromStringBinding(BindingString, Handle);
  2159. CLEANUP1_WS(0, "++ ERROR - Storing binding for %ws;", Name->Name, WStatus, CLEANUP);
  2160. //
  2161. // Not authenticating
  2162. //
  2163. if (KerberosIsNotAvailable ||
  2164. AuthLevel == CXTION_AUTH_NONE) {
  2165. goto done;
  2166. }
  2167. //
  2168. // Put our authentication info into the handle
  2169. //
  2170. if (MutualAuthenticationIsEnabled) {
  2171. WStatus = RpcBindingSetAuthInfoEx(*Handle,
  2172. PrincName,
  2173. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2174. RPC_C_AUTHN_GSS_NEGOTIATE,
  2175. NULL,
  2176. RPC_C_AUTHZ_NONE,
  2177. &RpcSecurityQos);
  2178. DPRINT2_WS(1, "++ WARN - RpcBindingSetAuthInfoEx(%ws, %ws);",
  2179. Name->Name, PrincName, WStatus);
  2180. } else {
  2181. WStatus = ERROR_NOT_SUPPORTED;
  2182. }
  2183. //
  2184. // Fall back to manual mutual authentication
  2185. //
  2186. if (!WIN_SUCCESS(WStatus)) {
  2187. WStatus = RpcBindingSetAuthInfo(*Handle,
  2188. PrincName,
  2189. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  2190. RPC_C_AUTHN_GSS_NEGOTIATE,
  2191. NULL,
  2192. RPC_C_AUTHZ_NONE);
  2193. }
  2194. CLEANUP2_WS(0, "++ ERROR - RpcBindingSetAuthInfo(%ws, %ws);",
  2195. Name->Name, PrincName, WStatus, CLEANUP);
  2196. //
  2197. // SUCCESS
  2198. //
  2199. WStatus = ERROR_SUCCESS;
  2200. done:
  2201. DPRINT1(4, ":S: Bound to %ws\n", Name->Name);
  2202. //
  2203. // Some simple stats for debugging
  2204. //
  2205. DeltaBinds = ++RpcBinds - RpcUnBinds;
  2206. if (DeltaBinds > RpcMaxBinds) {
  2207. RpcMaxBinds = DeltaBinds;
  2208. }
  2209. // Fall through
  2210. CLEANUP:
  2211. if (BindingString) {
  2212. RpcStringFreeW(&BindingString);
  2213. }
  2214. //
  2215. // We are now ready to talk to the server using the frsrpc interfaces
  2216. //
  2217. return WStatus;
  2218. }
  2219. VOID
  2220. FrsRpcUnBindFromServer(
  2221. handle_t *Handle
  2222. )
  2223. /*++
  2224. Routine Description:
  2225. Unbind from the server.
  2226. Arguments:
  2227. None.
  2228. Return Value:
  2229. None.
  2230. --*/
  2231. {
  2232. #undef DEBSUB
  2233. #define DEBSUB "FrsRpcUnBindFromServer:"
  2234. DWORD WStatus;
  2235. //
  2236. // Simple stats for debugging
  2237. //
  2238. ++RpcUnBinds;
  2239. try {
  2240. if (Handle) {
  2241. WStatus = RpcBindingFree(Handle);
  2242. DPRINT_WS(0, "++ WARN - RpcBindingFree;", WStatus);
  2243. }
  2244. *Handle = NULL;
  2245. } except (FrsException(GetExceptionInformation())) {
  2246. }
  2247. }
  2248. VOID
  2249. FrsRpcInitializeAccessChecks(
  2250. VOID
  2251. )
  2252. /*++
  2253. Routine Description:
  2254. Create the registry keys that are used to check for access to
  2255. the RPC calls that are exported for applications. The access checks
  2256. have no affect on the RPC calls used for replication.
  2257. The access checks for a given RPC call can be enabled or disabled
  2258. by setting a registry value. If enabled, the RPC call impersonates
  2259. the caller and attempts to open the registry key with the access
  2260. required for that RPC call. The required access is a registry value.
  2261. For example, the following registry hierarchy shows that the
  2262. "Set Ds Polling Interval" has access checks enabled and requires
  2263. write access while "Get Ds Polling Interval" has no access checks.
  2264. NtFrs\Parameters\Access Checks\Set Ds Polling Interval
  2265. Access checks are [enabled | disabled] REG_SZ enabled
  2266. Access checks require [read | write] REG_SZ write
  2267. NtFrs\Parameters\Access Checks\Get Ds Polling Interval
  2268. Access checks are [enabled | disabled] REG_SZ disabled
  2269. The initial set of RPC calls are: (see key context entries in config.c)
  2270. dcpromo - enabled, write
  2271. Set Ds Polling Interval - enabled, write
  2272. Start Ds Polling - enabled, read
  2273. Get Ds Polling Interval - enabled, read
  2274. Get Internal Information - enabled, write
  2275. Get Perfmon Data - enabled, read
  2276. Arguments:
  2277. None.
  2278. Return Value:
  2279. None.
  2280. --*/
  2281. {
  2282. #undef DEBSUB
  2283. #define DEBSUB "FrsRpcInitializeAccessChecks:"
  2284. DWORD WStatus;
  2285. DWORD i;
  2286. PWCHAR AccessChecksAre = NULL;
  2287. PWCHAR AccessChecksRequire = NULL;
  2288. FRS_REG_KEY_CODE FrsRkc;
  2289. PWCHAR ApiName;
  2290. for (i = 0; i < ACX_MAX; ++i) {
  2291. FrsRkc = RpcApiKeys[i].Enable;
  2292. ApiName = RpcApiKeys[i].KeyName;
  2293. //
  2294. // Read the current string Access Check Enable string.
  2295. //
  2296. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksAre);
  2297. if ((AccessChecksAre == NULL) ||
  2298. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_DISABLED)||
  2299. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_ENABLED)) {
  2300. //
  2301. // The key is in the default state so we can clobber it with a
  2302. // new default.
  2303. //
  2304. WStatus = CfgRegWriteString(FrsRkc, NULL, FRS_RKF_FORCE_DEFAULT_VALUE, NULL);
  2305. DPRINT1_WS(0, "++ WARN - Cannot create Enable key for %ws;", ApiName, WStatus);
  2306. AccessChecksAre = FrsFree(AccessChecksAre);
  2307. //
  2308. // Now reread the key for the new default.
  2309. //
  2310. WStatus = CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksAre);
  2311. }
  2312. DPRINT4(4, ":S: AccessChecks: ...\\%ws\\%ws\\%ws = %ws\n",
  2313. ACCESS_CHECKS_KEY, ApiName, ACCESS_CHECKS_ARE, AccessChecksAre);
  2314. if (AccessChecksAre &&
  2315. (WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DEFAULT_DISABLED) ||
  2316. WSTR_EQ(AccessChecksAre, ACCESS_CHECKS_ARE_DISABLED))) {
  2317. //
  2318. // Put a notice in the event log that the access check is disabled.
  2319. //
  2320. EPRINT2(EVENT_FRS_ACCESS_CHECKS_DISABLED, ApiName, ACCESS_CHECKS_ARE);
  2321. }
  2322. AccessChecksAre = FrsFree(AccessChecksAre);
  2323. //
  2324. // Create the Access Rights value. This determines what rights the caller
  2325. // must have in order to use the API. These rights are used when we
  2326. // open the API key after impersonating the RPC caller. If the key
  2327. // open works then the API call can proceed else we return insufficient
  2328. // privilege status (FRS_ERR_INSUFFICENT_PRIV).
  2329. //
  2330. FrsRkc = RpcApiKeys[i].Rights;
  2331. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksRequire);
  2332. if ((AccessChecksRequire == NULL)||
  2333. WSTR_EQ(AccessChecksRequire, ACCESS_CHECKS_REQUIRE_DEFAULT_READ)||
  2334. WSTR_EQ(AccessChecksRequire, ACCESS_CHECKS_REQUIRE_DEFAULT_WRITE)) {
  2335. //
  2336. // The key is in the default state so we can clobber it with a
  2337. // new default.
  2338. //
  2339. WStatus = CfgRegWriteString(FrsRkc, NULL, FRS_RKF_FORCE_DEFAULT_VALUE, NULL);
  2340. DPRINT1_WS(0, "++ WARN - Cannot set access rights key for %ws;", ApiName, WStatus);
  2341. AccessChecksRequire = FrsFree(AccessChecksRequire);
  2342. //
  2343. // Now reread the key for the new default.
  2344. //
  2345. CfgRegReadString(FrsRkc, NULL, 0, &AccessChecksRequire);
  2346. }
  2347. DPRINT4(4, ":S: AccessChecks: ...\\%ws\\%ws\\%ws = %ws\n",
  2348. ACCESS_CHECKS_KEY, ApiName, ACCESS_CHECKS_REQUIRE, AccessChecksRequire);
  2349. AccessChecksRequire = FrsFree(AccessChecksRequire);
  2350. } // end for
  2351. FrsFree(AccessChecksAre);
  2352. FrsFree(AccessChecksRequire);
  2353. }
  2354. VOID
  2355. ShutDownRpc(
  2356. )
  2357. /*++
  2358. Routine Description:
  2359. Shutdown the client and server side of RPC.
  2360. Arguments:
  2361. None.
  2362. Return Value:
  2363. None.
  2364. --*/
  2365. {
  2366. #undef DEBSUB
  2367. #define DEBSUB "ShutDownRpc:"
  2368. RPC_STATUS WStatus;
  2369. RPC_BINDING_VECTOR *BindingVector = NULL;
  2370. //
  2371. // Server side
  2372. //
  2373. // Stop listening for new calls
  2374. //
  2375. try {
  2376. WStatus = RpcMgmtStopServerListening(0) ;
  2377. DPRINT_WS(0, "++ WARN - RpcMgmtStopServerListening;", WStatus);
  2378. } except (FrsException(GetExceptionInformation())) {
  2379. }
  2380. try {
  2381. //
  2382. // Get our registered interfaces
  2383. //
  2384. WStatus = RpcServerInqBindings(&BindingVector);
  2385. DPRINT_WS(0, "++ WARN - RpcServerInqBindings;", WStatus);
  2386. if (RPC_SUCCESS(WStatus)) {
  2387. //
  2388. // And unexport the interfaces together with their dynamic endpoints
  2389. //
  2390. WStatus = RpcEpUnregister(SERVER_frsrpc_ServerIfHandle, BindingVector, 0);
  2391. DPRINT_WS(0, "++ WARN - RpcEpUnregister SERVER_frsrpc_ServerIfHandle;", WStatus);
  2392. WStatus = RpcEpUnregister(NtFrsApi_ServerIfHandle, BindingVector, 0);
  2393. DPRINT_WS(0, "++ WARN - RpcEpUnregister NtFrsApi_ServerIfHandle;", WStatus);
  2394. if (HANDLE_IS_VALID(PerfmonProcessSemaphore)) {
  2395. //
  2396. // PERFMON RPC
  2397. //
  2398. WStatus = RpcEpUnregister(PerfFrs_ServerIfHandle, BindingVector, 0);
  2399. DPRINT_WS(0, "++ WARN - RpcEpUnregister PerfFrs_ServerIfHandle;", WStatus);
  2400. }
  2401. WStatus = RpcBindingVectorFree(&BindingVector);
  2402. DPRINT_WS(0, "++ WARN - RpcBindingVectorFree;", WStatus);
  2403. }
  2404. //
  2405. // Wait for any outstanding RPCs to finish.
  2406. //
  2407. WStatus = RpcMgmtWaitServerListen();
  2408. DPRINT_WS(0, "++ WARN - RpcMgmtWaitServerListen;", WStatus);
  2409. } except (FrsException(GetExceptionInformation())) {
  2410. }
  2411. }
  2412. VOID
  2413. FrsRpcUnInitialize(
  2414. VOID
  2415. )
  2416. /*++
  2417. Routine Description:
  2418. Free up memory once all of the threads in the system have been
  2419. shut down.
  2420. Arguments:
  2421. None.
  2422. Return Value:
  2423. None.
  2424. --*/
  2425. {
  2426. #undef DEBSUB
  2427. #define DEBSUB "FrsRpcUnInitialize:"
  2428. DPRINT(4, ":S: Free sysvol name table.\n");
  2429. DEBUG_FLUSH();
  2430. SysVolsBeingCreated = GTabFreeTable(SysVolsBeingCreated, NULL);
  2431. if (ServerPrincName) {
  2432. if (KerberosIsNotAvailable) {
  2433. DPRINT(4, ":S: Free ServerPrincName (no kerberos).\n");
  2434. DEBUG_FLUSH();
  2435. ServerPrincName = FrsFree(ServerPrincName);
  2436. } else {
  2437. DPRINT(4, ":S: Free ServerPrincName (kerberos).\n");
  2438. DEBUG_FLUSH();
  2439. ServerPrincName = FrsFree(ServerPrincName);
  2440. }
  2441. }
  2442. DPRINT(4, ":S: Done uninitializing RPC.\n");
  2443. DEBUG_FLUSH();
  2444. }
  2445. BOOL
  2446. FrsRpcInitialize(
  2447. VOID
  2448. )
  2449. /*++
  2450. Routine Description:
  2451. Initializting This thread is kicked off by the main thread. This thread sets up
  2452. the server and client side of RPC for the frsrpc interface.
  2453. Arguments:
  2454. Arg - Needed to set status for our parent.
  2455. Return Value:
  2456. TRUE - RPC has started
  2457. FALSE - RPC could not be started
  2458. --*/
  2459. {
  2460. #undef DEBSUB
  2461. #define DEBSUB "FrsRpcInitialize:"
  2462. BOOL StartedOK = FALSE;
  2463. try {
  2464. //
  2465. // Get the maximum number of concurrent RPC calls out of registry.
  2466. //
  2467. CfgRegReadDWord(FKC_MAX_RPC_SERVER_THREADS, NULL, 0, &MaxRpcServerThreads);
  2468. DPRINT1(0,":S: Max RPC threads is %d\n", MaxRpcServerThreads);
  2469. //
  2470. // Register protocol sequences
  2471. //
  2472. RegisterRpcProtseqs();
  2473. DPRINT(0, ":S: FRS RPC protocol sequences registered\n");
  2474. //
  2475. // Register frsrpc interface
  2476. //
  2477. RegisterRpcInterface();
  2478. DPRINT(0, ":S: FRS RPC interface registered\n");
  2479. //
  2480. // Start listening for clients
  2481. //
  2482. StartServerRpc();
  2483. DPRINT(0, ":S: FRS RPC server interface installed\n");
  2484. //
  2485. // Table of sysvols being created
  2486. //
  2487. if (!SysVolsBeingCreated) {
  2488. SysVolsBeingCreated = GTabAllocTable();
  2489. }
  2490. StartedOK = TRUE;
  2491. } except (FrsException(GetExceptionInformation())) {
  2492. DPRINT(0, ":S: Can't start RPC\n");
  2493. }
  2494. //
  2495. // Cleanup
  2496. //
  2497. try {
  2498. if (!StartedOK) {
  2499. ShutDownRpc();
  2500. }
  2501. } except (FrsException(GetExceptionInformation())) {
  2502. DPRINT(0, ":S: Can't shutdown RPC\n");
  2503. }
  2504. //
  2505. // DONE
  2506. //
  2507. //
  2508. // Free up the rpc initialization memory
  2509. //
  2510. SetProcessWorkingSetSize(ProcessHandle, (SIZE_T)-1, (SIZE_T)-1);
  2511. return StartedOK;
  2512. }