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.

1311 lines
29 KiB

  1. /*++
  2. Copyright (c) 2001-2001 Microsoft Corporation
  3. Module Name:
  4. rpc.c
  5. Abstract:
  6. DNS Resolver Service
  7. RPC intialization, shutdown and utility routines.
  8. Author:
  9. Jim Gilroy (jamesg) April 19, 2001
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include <rpc.h>
  14. #include "rpcdce.h"
  15. #include "secobj.h"
  16. #undef UNICODE
  17. //
  18. // RPC globals
  19. //
  20. BOOL g_fRpcInitialized = FALSE;
  21. DWORD g_RpcProtocol = RESOLVER_RPC_USE_LPC;
  22. PSECURITY_DESCRIPTOR g_pRpcSecurityDescriptor;
  23. #define AUTO_BIND
  24. //
  25. // Resolver access control
  26. //
  27. PSECURITY_DESCRIPTOR g_pAccessSecurityDescriptor = NULL;
  28. PACL g_pAccessAcl = NULL;
  29. PSID g_pAccessOwnerSid = NULL;
  30. GENERIC_MAPPING g_AccessGenericMapping =
  31. {
  32. RESOLVER_GENERIC_READ,
  33. RESOLVER_GENERIC_WRITE,
  34. RESOLVER_GENERIC_EXECUTE,
  35. RESOLVER_GENERIC_ALL
  36. };
  37. #define SECURITY_LOCK() EnterCriticalSection( &CacheCS )
  38. #define SECURITY_UNLOCK() LeaveCriticalSection( &CacheCS )
  39. //
  40. // Privileges
  41. //
  42. #if 0
  43. #define RESOLVER_PRIV_READ 1
  44. #define RESOLVER_PRIV_ENUM 2
  45. #define RESOLVER_PRIV_FLUSH 3
  46. #define RESOLVER_PRIV_REGISTER 4
  47. #endif
  48. DNS_STATUS
  49. Rpc_InitAccessChecking(
  50. VOID
  51. );
  52. VOID
  53. Rpc_CleanupAccessChecking(
  54. VOID
  55. );
  56. BOOL
  57. Rpc_IsProtoLpcA(
  58. IN PVOID pContext
  59. )
  60. /*++
  61. Routine Description:
  62. Check if access if over LPC
  63. Arguments:
  64. pContext -- client RPC context
  65. Return Value:
  66. TRUE if protocol is LPC
  67. FALSE otherwise
  68. --*/
  69. {
  70. DNS_STATUS status;
  71. BOOL fisLpc = FALSE;
  72. PSTR pbinding = NULL;
  73. PSTR pprotoString = NULL;
  74. DNSDBG( RPC, (
  75. "Rpc_IsAccessOverLpc( context=%p )\n",
  76. pContext ));
  77. //
  78. // get string binding
  79. //
  80. status = RpcBindingToStringBindingA(
  81. pContext,
  82. & pbinding );
  83. if ( status != NO_ERROR )
  84. {
  85. goto Cleanup;
  86. }
  87. //
  88. // get protocol as string
  89. //
  90. status = RpcStringBindingParseA(
  91. pbinding,
  92. NULL,
  93. & pprotoString,
  94. NULL,
  95. NULL,
  96. NULL );
  97. if ( status != NO_ERROR )
  98. {
  99. goto Cleanup;
  100. }
  101. //
  102. // check for LPC
  103. //
  104. fisLpc = ( _stricmp( pprotoString, "ncalrpc" ) == 0 );
  105. RpcStringFreeA( &pprotoString );
  106. Cleanup:
  107. if ( pbinding )
  108. {
  109. RpcStringFreeA( &pbinding );
  110. }
  111. return( fisLpc );
  112. }
  113. BOOL
  114. Rpc_IsProtoLpc(
  115. IN PVOID pContext
  116. )
  117. /*++
  118. Routine Description:
  119. Check if access if over LPC
  120. Arguments:
  121. pContext -- client RPC context
  122. Return Value:
  123. TRUE if protocol is LPC
  124. FALSE otherwise
  125. --*/
  126. {
  127. DNS_STATUS status;
  128. BOOL fisLpc = FALSE;
  129. PWSTR pbinding = NULL;
  130. PWSTR pprotoString = NULL;
  131. DNSDBG( RPC, (
  132. "Rpc_IsAccessOverLpc( context=%p )\n",
  133. pContext ));
  134. //
  135. // get string binding
  136. //
  137. status = RpcBindingToStringBinding(
  138. pContext,
  139. & pbinding );
  140. if ( status != NO_ERROR )
  141. {
  142. goto Cleanup;
  143. }
  144. //
  145. // get protocol as string
  146. //
  147. status = RpcStringBindingParse(
  148. pbinding,
  149. NULL,
  150. & pprotoString,
  151. NULL,
  152. NULL,
  153. NULL );
  154. if ( status != NO_ERROR )
  155. {
  156. goto Cleanup;
  157. }
  158. //
  159. // check for LPC
  160. //
  161. fisLpc = ( _wcsicmp( pprotoString, L"ncalrpc" ) == 0 );
  162. RpcStringFree( &pprotoString );
  163. Cleanup:
  164. if ( pbinding )
  165. {
  166. RpcStringFree( &pbinding );
  167. }
  168. return( fisLpc );
  169. }
  170. RPC_STATUS
  171. RPC_ENTRY
  172. Rpc_SecurityCallback(
  173. IN RPC_IF_HANDLE IfHandle,
  174. IN PVOID pContext
  175. )
  176. /*++
  177. Routine Description:
  178. RPC callback security check.
  179. Arguments:
  180. IfHandle -- interface handle
  181. pContext -- client RPC context
  182. Return Value:
  183. NO_ERROR if security check allows access.
  184. ErrorCode on security failure.
  185. --*/
  186. {
  187. DNSDBG( RPC, (
  188. "Rpc_SecurityCallback( context=%p )\n",
  189. pContext ));
  190. //
  191. // check if connection over LPC
  192. //
  193. if ( !Rpc_IsProtoLpc(pContext) )
  194. {
  195. return ERROR_ACCESS_DENIED;
  196. }
  197. return NO_ERROR;
  198. }
  199. DNS_STATUS
  200. Rpc_Initialize(
  201. VOID
  202. )
  203. /*++
  204. Routine Description:
  205. Initialize server side RPC.
  206. Arguments:
  207. None.
  208. Return Value:
  209. ERROR_SUCCESS if successful.
  210. Error status on failure.
  211. --*/
  212. {
  213. RPC_STATUS status;
  214. BOOL fusingTcpip = FALSE;
  215. DNSDBG( RPC, (
  216. "Rpc_Initialize()\n"
  217. "\tIF handle = %p\n"
  218. "\tprotocol = %d\n",
  219. DnsResolver_ServerIfHandle,
  220. g_RpcProtocol
  221. ));
  222. //
  223. // RPC disabled?
  224. //
  225. if ( ! g_RpcProtocol )
  226. {
  227. g_RpcProtocol = RESOLVER_RPC_USE_LPC;
  228. }
  229. #if 0
  230. //
  231. // Create security for RPC API
  232. //
  233. status = NetpCreateWellKnownSids( NULL );
  234. if ( status != ERROR_SUCCESS )
  235. {
  236. DNS_PRINT(( "ERROR: Creating well known SIDs.\n" ));
  237. return( status );
  238. }
  239. status = RpcUtil_CreateSecurityObjects();
  240. if ( status != ERROR_SUCCESS )
  241. {
  242. DNS_PRINT(( "ERROR: Creating DNS security object.\n" ));
  243. return( status );
  244. }
  245. #endif
  246. //
  247. // build security descriptor
  248. //
  249. // NULL security descriptor gives some sort of default security
  250. // on the interface
  251. // - owner is this service (currently "Network Service")
  252. // - read access for everyone
  253. //
  254. // note: if roll your own, remember to avoid NULL DACL, this
  255. // puts NO security on interface including the right to
  256. // change security, so any app can hijack the ACL and
  257. // deny access to folks; the default SD==NULL security
  258. // doesn't give everyone WRITE_DACL
  259. //
  260. g_pRpcSecurityDescriptor = NULL;
  261. //
  262. // RPC over LPC
  263. //
  264. if( g_RpcProtocol & RESOLVER_RPC_USE_LPC )
  265. {
  266. status = RpcServerUseProtseqEpW(
  267. L"ncalrpc", // protocol string.
  268. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // maximum concurrent calls
  269. RESOLVER_RPC_LPC_ENDPOINT_W, // endpoint
  270. g_pRpcSecurityDescriptor // security
  271. );
  272. // duplicate endpoint is ok
  273. if ( status == RPC_S_DUPLICATE_ENDPOINT )
  274. {
  275. status = RPC_S_OK;
  276. }
  277. if ( status != RPC_S_OK )
  278. {
  279. DNSDBG( INIT, (
  280. "ERROR: RpcServerUseProtseqEp() for LPC failed.]n"
  281. "\tstatus = %d 0x%08lx.\n",
  282. status, status ));
  283. return( status );
  284. }
  285. }
  286. #if 0 // use use LPC interface
  287. //
  288. // RCP over TCP/IP
  289. //
  290. if( g_RpcProtocol & RESOLVER_RPC_USE_TCPIP )
  291. {
  292. #ifdef AUTO_BIND
  293. RPC_BINDING_VECTOR * bindingVector;
  294. status = RpcServerUseProtseqW(
  295. L"ncacn_ip_tcp", // protocol string.
  296. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // max concurrent calls
  297. g_pRpcSecurityDescriptor
  298. );
  299. if ( status != RPC_S_OK )
  300. {
  301. DNSDBG( INIT, (
  302. "ERROR: RpcServerUseProtseq() for TCP/IP failed.]n"
  303. "\tstatus = %d 0x%08lx.\n",
  304. status, status ));
  305. return( status );
  306. }
  307. status = RpcServerInqBindings( &bindingVector );
  308. if ( status != RPC_S_OK )
  309. {
  310. DNSDBG( INIT, (
  311. "ERROR: RpcServerInqBindings failed.\n"
  312. "\tstatus = %d 0x%08lx.\n",
  313. status, status ));
  314. return( status );
  315. }
  316. //
  317. // register interface(s)
  318. // since only one DNS server on a host can use
  319. // RpcEpRegister() rather than RpcEpRegisterNoReplace()
  320. //
  321. status = RpcEpRegisterW(
  322. DnsResolver_ServerIfHandle,
  323. bindingVector,
  324. NULL,
  325. L"" );
  326. if ( status != RPC_S_OK )
  327. {
  328. DNSDBG( ANY, (
  329. "ERROR: RpcEpRegisterNoReplace() failed.\n"
  330. "\tstatus = %d %p.\n",
  331. status, status ));
  332. return( status );
  333. }
  334. //
  335. // free binding vector
  336. //
  337. status = RpcBindingVectorFree( &bindingVector );
  338. ASSERT( status == RPC_S_OK );
  339. status = RPC_S_OK;
  340. #else // not AUTO_BIND
  341. status = RpcServerUseProtseqEpW(
  342. L"ncacn_ip_tcp", // protocol string.
  343. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // maximum concurrent calls
  344. RESOLVER_RPC_SERVER_PORT_W, // endpoint
  345. g_pRpcSecurityDescriptor // security
  346. );
  347. if ( status != RPC_S_OK )
  348. {
  349. DNSDBG( ANY, (
  350. "ERROR: RpcServerUseProtseqEp() for TCP/IP failed.]n"
  351. "\tstatus = %d 0x%08lx.\n",
  352. status, status ));
  353. return( status );
  354. }
  355. #endif // AUTO_BIND
  356. fusingTcpip = TRUE;
  357. }
  358. //
  359. // RPC over named pipes
  360. //
  361. if ( g_RpcProtocol & RESOLVER_RPC_USE_NAMED_PIPE )
  362. {
  363. status = RpcServerUseProtseqEpW(
  364. L"ncacn_np", // protocol string.
  365. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // maximum concurrent calls
  366. RESOLVER_RPC_PIPE_NAME_W, // endpoint
  367. g_pRpcSecurityDescriptor
  368. );
  369. // duplicate endpoint is ok
  370. if ( status == RPC_S_DUPLICATE_ENDPOINT )
  371. {
  372. status = RPC_S_OK;
  373. }
  374. if ( status != RPC_S_OK )
  375. {
  376. DNSDBG( INIT, (
  377. "ERROR: RpcServerUseProtseqEp() for named pipe failed.]n"
  378. "\tstatus = %d 0x%08lx.\n",
  379. status,
  380. status ));
  381. return( status );
  382. }
  383. }
  384. #endif // only LPC interface
  385. //
  386. // register DNS RPC interface(s)
  387. //
  388. status = RpcServerRegisterIfEx(
  389. DnsResolver_ServerIfHandle,
  390. NULL,
  391. NULL,
  392. 0,
  393. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  394. Rpc_SecurityCallback
  395. );
  396. if ( status != RPC_S_OK )
  397. {
  398. DNSDBG( INIT, (
  399. "ERROR: RpcServerRegisterIfEx() failed.]n"
  400. "\tstatus = %d 0x%08lx.\n",
  401. status, status ));
  402. return(status);
  403. }
  404. #if 0
  405. //
  406. // for TCP/IP setup authentication
  407. //
  408. if ( fuseTcpip )
  409. {
  410. status = RpcServerRegisterAuthInfoW(
  411. RESOLVER_RPC_SECURITY_W, // app name to security provider.
  412. RESOLVER_RPC_SECURITY_AUTH_ID, // Auth package ID.
  413. NULL, // Encryption function handle.
  414. NULL ); // argment pointer to Encrypt function.
  415. if ( status != RPC_S_OK )
  416. {
  417. DNSDBG( INIT, (
  418. "ERROR: RpcServerRegisterAuthInfo() failed.]n"
  419. "\tstatus = %d 0x%08lx.\n",
  420. status, status ));
  421. return( status );
  422. }
  423. }
  424. #endif
  425. //
  426. // Listen on RPC
  427. //
  428. status = RpcServerListen(
  429. 1, // min threads
  430. RPC_C_PROTSEQ_MAX_REQS_DEFAULT, // max concurrent calls
  431. TRUE ); // return on completion
  432. if ( status != RPC_S_OK )
  433. {
  434. if ( status != RPC_S_ALREADY_LISTENING )
  435. {
  436. DNS_PRINT((
  437. "ERROR: RpcServerListen() failed\n"
  438. "\tstatus = %d 0x%p\n",
  439. status, status ));
  440. return( status );
  441. }
  442. status = NO_ERROR;
  443. }
  444. g_fRpcInitialized = TRUE;
  445. return( status );
  446. } // Rpc_Initialize
  447. VOID
  448. Rpc_Shutdown(
  449. VOID
  450. )
  451. /*++
  452. Routine Description:
  453. Shutdown RPC on the server.
  454. Arguments:
  455. None.
  456. Return Value:
  457. None.
  458. --*/
  459. {
  460. DWORD status;
  461. RPC_BINDING_VECTOR * bindingVector = NULL;
  462. DNSDBG( RPC, ( "Rpc_Shutdown().\n" ));
  463. if( ! g_fRpcInitialized )
  464. {
  465. DNSDBG( RPC, (
  466. "RPC not active, no shutdown necessary.\n" ));
  467. return;
  468. }
  469. #if 0
  470. // can not stop server as another service may share this process
  471. //
  472. // stop server listen
  473. // then wait for all RPC threads to go away
  474. //
  475. status = RpcMgmtStopServerListening(
  476. NULL // this app
  477. );
  478. if ( status == RPC_S_OK )
  479. {
  480. status = RpcMgmtWaitServerListen();
  481. }
  482. #endif
  483. //
  484. // unbind / unregister endpoints
  485. //
  486. status = RpcServerInqBindings( &bindingVector );
  487. ASSERT( status == RPC_S_OK );
  488. if ( status == RPC_S_OK )
  489. {
  490. status = RpcEpUnregister(
  491. DnsResolver_ServerIfHandle,
  492. bindingVector,
  493. NULL ); // Uuid vector.
  494. if ( status != RPC_S_OK )
  495. {
  496. DNSDBG( ANY, (
  497. "ERROR: RpcEpUnregister, status = %d.\n", status ));
  498. }
  499. }
  500. //
  501. // free binding vector
  502. //
  503. if ( bindingVector )
  504. {
  505. status = RpcBindingVectorFree( &bindingVector );
  506. ASSERT( status == RPC_S_OK );
  507. }
  508. //
  509. // wait for all calls to complete
  510. //
  511. status = RpcServerUnregisterIf(
  512. DnsResolver_ServerIfHandle,
  513. 0,
  514. TRUE );
  515. ASSERT( status == ERROR_SUCCESS );
  516. g_fRpcInitialized = FALSE;
  517. //
  518. // dump resolver access checking security structs
  519. //
  520. Rpc_CleanupAccessChecking();
  521. DNSDBG( RPC, (
  522. "RPC shutdown completed.\n" ));
  523. }
  524. //
  525. // RPC access control
  526. //
  527. // The RPC interface, by design, must be open to basically every
  528. // process for query. So the RPC interface itself uses just
  529. // default security (above).
  530. //
  531. // To get more detailed call-by-call access checking for special
  532. // operations -- enum, flush, cluster registrations -- we need
  533. // separate access checking.
  534. //
  535. DNS_STATUS
  536. Rpc_InitAccessChecking(
  537. VOID
  538. )
  539. /*++
  540. Routine Description:
  541. Initialize resolver security.
  542. Arguments:
  543. None
  544. Return Value:
  545. NO_ERROR if successful.
  546. ErrorCode on failure.
  547. --*/
  548. {
  549. PSECURITY_DESCRIPTOR psd = NULL;
  550. SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
  551. PACL pacl = NULL;
  552. PSID psidAdmin = NULL;
  553. PSID psidPowerUser = NULL;
  554. PSID psidLocalService = NULL;
  555. PSID psidNetworkService = NULL;
  556. PSID psidNetworkConfigOps = NULL;
  557. DWORD lengthAcl;
  558. DNS_STATUS status = NO_ERROR;
  559. BOOL bresult;
  560. DNSDBG( INIT, ( "Rpc_InitAccessChecking()\n" ));
  561. //
  562. // check if already have SD
  563. //
  564. // explicitly "create once" semantics; once
  565. // created SD is read-only and not destroyed until
  566. // shutdown
  567. //
  568. if ( g_pAccessSecurityDescriptor )
  569. {
  570. return NO_ERROR;
  571. }
  572. // lock and retest
  573. SECURITY_LOCK();
  574. if ( g_pAccessSecurityDescriptor )
  575. {
  576. status = NO_ERROR;
  577. goto Unlock;
  578. }
  579. //
  580. // build SIDs that will be allowed access
  581. //
  582. bresult = AllocateAndInitializeSid(
  583. &authority,
  584. 2,
  585. SECURITY_BUILTIN_DOMAIN_RID,
  586. DOMAIN_ALIAS_RID_ADMINS,
  587. 0, 0, 0, 0, 0, 0,
  588. & psidAdmin
  589. );
  590. bresult = bresult &&
  591. AllocateAndInitializeSid(
  592. &authority,
  593. 2,
  594. SECURITY_BUILTIN_DOMAIN_RID,
  595. DOMAIN_ALIAS_RID_POWER_USERS,
  596. 0, 0, 0, 0, 0, 0,
  597. & psidPowerUser
  598. );
  599. bresult = bresult &&
  600. AllocateAndInitializeSid(
  601. &authority,
  602. 1,
  603. SECURITY_LOCAL_SERVICE_RID,
  604. 0,
  605. 0, 0, 0, 0, 0, 0,
  606. &psidLocalService
  607. );
  608. bresult = bresult &&
  609. AllocateAndInitializeSid(
  610. &authority,
  611. 1,
  612. SECURITY_NETWORK_SERVICE_RID,
  613. 0,
  614. 0, 0, 0, 0, 0, 0,
  615. &psidNetworkService
  616. );
  617. bresult = bresult &&
  618. AllocateAndInitializeSid(
  619. &authority,
  620. 2,
  621. SECURITY_BUILTIN_DOMAIN_RID,
  622. DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS,
  623. 0, 0, 0, 0, 0, 0,
  624. &psidNetworkConfigOps
  625. );
  626. if ( !bresult )
  627. {
  628. status = GetLastError();
  629. if ( status == NO_ERROR )
  630. {
  631. status = DNS_ERROR_NO_MEMORY;
  632. }
  633. DNSDBG( ANY, (
  634. "Failed building resolver ACEs!\n" ));
  635. goto Cleanup;
  636. }
  637. //
  638. // allocate ACL
  639. //
  640. lengthAcl = ( (ULONG)sizeof(ACL)
  641. + 5*((ULONG)sizeof(ACCESS_ALLOWED_ACE) - (ULONG)sizeof(ULONG)) +
  642. + GetLengthSid( psidAdmin )
  643. + GetLengthSid( psidPowerUser )
  644. + GetLengthSid( psidLocalService )
  645. + GetLengthSid( psidNetworkService )
  646. + GetLengthSid( psidNetworkConfigOps ) );
  647. pacl = GENERAL_HEAP_ALLOC( lengthAcl );
  648. if ( !pacl )
  649. {
  650. status = GetLastError();
  651. goto Cleanup;
  652. }
  653. bresult = InitializeAcl( pacl, lengthAcl, ACL_REVISION2 );
  654. //
  655. // init ACLs
  656. //
  657. // - default to generic READ\WRITE
  658. // - local service GENERIC_ALL to include registration
  659. // - admin gets GENERIC_ALL on debug to test registration
  660. //
  661. // DCR: GENERIC_ALL on admin subject to test flag
  662. //
  663. // note: the masks for the individual SIDs need not be
  664. // GENERIC bits, they can be made completely with
  665. // with individual bits or mixed\matched with GENERIC
  666. // bits as desired
  667. //
  668. bresult = bresult &&
  669. AddAccessAllowedAce(
  670. pacl,
  671. ACL_REVISION2,
  672. GENERIC_ALL,
  673. psidLocalService );
  674. bresult = bresult &&
  675. AddAccessAllowedAce(
  676. pacl,
  677. ACL_REVISION2,
  678. #ifdef DBG
  679. GENERIC_ALL,
  680. #else
  681. GENERIC_READ | GENERIC_WRITE,
  682. #endif
  683. psidAdmin );
  684. bresult = bresult &&
  685. AddAccessAllowedAce(
  686. pacl,
  687. ACL_REVISION2,
  688. GENERIC_READ | GENERIC_WRITE,
  689. psidPowerUser );
  690. bresult = bresult &&
  691. AddAccessAllowedAce(
  692. pacl,
  693. ACL_REVISION2,
  694. GENERIC_READ | GENERIC_WRITE,
  695. psidNetworkService );
  696. bresult = bresult &&
  697. AddAccessAllowedAce(
  698. pacl,
  699. ACL_REVISION2,
  700. GENERIC_READ | GENERIC_WRITE,
  701. psidNetworkConfigOps );
  702. if ( !bresult )
  703. {
  704. status = GetLastError();
  705. DNSDBG( ANY, (
  706. "Failed building resolver ACEs!\n" ));
  707. goto Cleanup;
  708. }
  709. //
  710. // allocate security descriptor
  711. // then init with ACL
  712. //
  713. psd = GENERAL_HEAP_ALLOC( SECURITY_DESCRIPTOR_MIN_LENGTH );
  714. if ( !psd )
  715. {
  716. status = DNS_ERROR_NO_MEMORY;
  717. goto Cleanup;
  718. }
  719. bresult = InitializeSecurityDescriptor(
  720. psd,
  721. SECURITY_DESCRIPTOR_REVISION );
  722. bresult = bresult &&
  723. SetSecurityDescriptorDacl(
  724. psd,
  725. TRUE, // have DACL
  726. pacl, // DACL
  727. FALSE // DACL not defaulted, explicit
  728. );
  729. // security folks indicate need owner to do AccessCheck
  730. bresult = bresult &&
  731. SetSecurityDescriptorOwner(
  732. psd,
  733. psidNetworkService,
  734. FALSE // owner not defaulted, explicit
  735. );
  736. #if 0
  737. // adding group seemed to make it worse
  738. bresult = bresult &&
  739. SetSecurityDescriptorGroup(
  740. psd,
  741. psidNetworkService,
  742. FALSE // group not defaulted, explicit
  743. );
  744. #endif
  745. if ( !bresult )
  746. {
  747. status = GetLastError();
  748. DNSDBG( ANY, (
  749. "Failed setting security descriptor!\n" ));
  750. goto Cleanup;
  751. }
  752. Cleanup:
  753. if ( psidAdmin )
  754. {
  755. FreeSid( psidAdmin );
  756. }
  757. if ( psidPowerUser )
  758. {
  759. FreeSid( psidPowerUser );
  760. }
  761. if ( psidLocalService )
  762. {
  763. FreeSid( psidLocalService );
  764. }
  765. if ( psidNetworkConfigOps )
  766. {
  767. FreeSid( psidNetworkConfigOps );
  768. }
  769. // validate SD
  770. if ( status == NO_ERROR )
  771. {
  772. if ( psd &&
  773. IsValidSecurityDescriptor(psd) )
  774. {
  775. g_pAccessSecurityDescriptor = psd;
  776. g_pAccessAcl = pacl;
  777. g_pAccessOwnerSid = psidNetworkService;
  778. goto Unlock;
  779. }
  780. status = GetLastError();
  781. DNSDBG( RPC, (
  782. "Invalid security descriptor\n",
  783. status ));
  784. ASSERT( FALSE );
  785. }
  786. // failed
  787. if ( status == NO_ERROR )
  788. {
  789. status = DNS_ERROR_NO_MEMORY;
  790. }
  791. GENERAL_HEAP_FREE( psd );
  792. GENERAL_HEAP_FREE( pacl );
  793. if ( psidNetworkService )
  794. {
  795. FreeSid( psidNetworkService );
  796. }
  797. Unlock:
  798. SECURITY_UNLOCK();
  799. DNSDBG( INIT, (
  800. "Leave Rpc_InitAccessChecking() = %d\n",
  801. status ));
  802. return( status );
  803. }
  804. VOID
  805. Rpc_CleanupAccessChecking(
  806. VOID
  807. )
  808. /*++
  809. Routine Description:
  810. Cleanup resolver security allocations for shutdown.
  811. Arguments:
  812. None
  813. Return Value:
  814. None
  815. --*/
  816. {
  817. GENERAL_HEAP_FREE( g_pAccessSecurityDescriptor );
  818. GENERAL_HEAP_FREE( g_pAccessAcl );
  819. if ( g_pAccessOwnerSid )
  820. {
  821. FreeSid( g_pAccessOwnerSid );
  822. g_pAccessOwnerSid = NULL;
  823. }
  824. g_pAccessSecurityDescriptor = NULL;
  825. g_pAccessAcl = NULL;
  826. }
  827. BOOL
  828. Rpc_AccessCheck(
  829. IN DWORD DesiredAccess
  830. )
  831. /*++
  832. Routine Description:
  833. Access check on resolver operations.
  834. Note, we do NOT do this on common operations -- query.
  835. This is pointless and way too expensive. We only protect
  836. Arguments:
  837. DesiredAccess -- access desired
  838. Return Value:
  839. None
  840. --*/
  841. {
  842. DNS_STATUS status;
  843. BOOL bstatus;
  844. HANDLE hthread = NULL;
  845. HANDLE htoken = NULL;
  846. BOOL fimpersonating = FALSE;
  847. DWORD desiredAccess = DesiredAccess;
  848. PRIVILEGE_SET privilegeSet;
  849. DWORD grantedAccess;
  850. DWORD privilegeSetLength;
  851. DNSDBG( RPC, (
  852. "Rpc_AccessCheck( priv=%08x )\n",
  853. DesiredAccess ));
  854. //
  855. // create security descriptor if not created yet
  856. //
  857. if ( !g_pAccessSecurityDescriptor )
  858. {
  859. status = Rpc_InitAccessChecking();
  860. if ( status != NO_ERROR )
  861. {
  862. goto Failed;
  863. }
  864. DNS_ASSERT( g_pAccessSecurityDescriptor );
  865. }
  866. if ( !IsValidSecurityDescriptor( g_pAccessSecurityDescriptor ) )
  867. {
  868. status = GetLastError();
  869. DNSDBG( RPC, (
  870. "ERROR Invalid access check SD %p => %u\n",
  871. g_pAccessSecurityDescriptor,
  872. status ));
  873. goto Failed;
  874. }
  875. //
  876. // impersonate and test access against mapping
  877. //
  878. status = RpcImpersonateClient( 0 );
  879. if ( status != NO_ERROR )
  880. {
  881. DNSDBG( RPC, (
  882. "ERROR <%u>: failed RpcImpersonateClient()\n",
  883. status ));
  884. DNS_ASSERT( FALSE );
  885. goto Failed;
  886. }
  887. fimpersonating = TRUE;
  888. //
  889. // get thread token
  890. //
  891. hthread = GetCurrentThread();
  892. if ( !hthread )
  893. {
  894. goto Failed;
  895. }
  896. bstatus = OpenThreadToken(
  897. hthread,
  898. TOKEN_QUERY,
  899. TRUE,
  900. &htoken );
  901. if ( !bstatus )
  902. {
  903. status = GetLastError();
  904. DNSDBG( RPC, (
  905. "\nERROR <%lu>: failed to open thread token!\n",
  906. status ));
  907. ASSERT( FALSE );
  908. goto Failed;
  909. }
  910. //
  911. // map generic bits
  912. // - we should NOT be called with generic bits
  913. // only bits for specific resolver operations
  914. //
  915. if ( (desiredAccess & SPECIFIC_RIGHTS_ALL) != desiredAccess )
  916. {
  917. DNS_ASSERT( FALSE );
  918. DNSDBG( RPC, (
  919. "desiredAccess before MapGenericMask() = %p\n",
  920. desiredAccess ));
  921. MapGenericMask(
  922. & desiredAccess,
  923. & g_AccessGenericMapping );
  924. DNSDBG( RPC, (
  925. "desiredAccess after MapGenericMask() = %p\n",
  926. desiredAccess ));
  927. }
  928. //
  929. // do access check
  930. //
  931. privilegeSetLength = sizeof(privilegeSet);
  932. if ( ! AccessCheck(
  933. g_pAccessSecurityDescriptor,
  934. htoken,
  935. desiredAccess,
  936. & g_AccessGenericMapping,
  937. & privilegeSet,
  938. & privilegeSetLength,
  939. & grantedAccess,
  940. & bstatus ) )
  941. {
  942. status = GetLastError();
  943. DNSDBG( RPC, (
  944. "AccessCheck() Failed => %u\n"
  945. "\tsec descp = %p\n"
  946. "\thtoken = %p\n"
  947. "\tdesired access = %08x\n"
  948. "\tgeneric mapping = %p\n"
  949. "\tpriv set ptr = %p\n"
  950. "\tpriv set length = %p\n"
  951. "\tgranted ptr = %p\n"
  952. "\tbstatus ptr = %p\n",
  953. status,
  954. g_pAccessSecurityDescriptor,
  955. htoken,
  956. desiredAccess,
  957. & g_AccessGenericMapping,
  958. & privilegeSet,
  959. & privilegeSetLength,
  960. & grantedAccess,
  961. & bstatus ));
  962. goto Failed;
  963. }
  964. //
  965. // access check successful
  966. // - access is either granted or denied
  967. if ( bstatus )
  968. {
  969. DNSDBG( RPC, (
  970. "RPC Client GRANTED access (%08x) by AccessCheck\n",
  971. DesiredAccess ));
  972. goto Cleanup;
  973. }
  974. else
  975. {
  976. DNSDBG( RPC, (
  977. "Warning: Client DENIED by AccessCheck\n"
  978. "\trequested access = %08x\n",
  979. desiredAccess ));
  980. goto Cleanup;
  981. }
  982. Failed:
  983. //
  984. // failure to do access check
  985. //
  986. // note again: NOT ACCESS_DENIED, but failure to be able to complete
  987. // the test
  988. //
  989. // note: since we aren't in general protecting anything interesting,
  990. // the we grant most access on failure --as admins may want the info
  991. // for diagnostic purposes, the current lone exception is cluster
  992. // registrations
  993. //
  994. // privilege:
  995. // - enum => allow access
  996. // - flush => allow access
  997. // - cluster registration => deny access
  998. //
  999. DNSDBG( ANY, (
  1000. "ERROR: Failed to execute RPC access check status = %d\n",
  1001. status ));
  1002. #if 0
  1003. // DCR: FIX: can't screen REGISTER until AccessCheck() works
  1004. bstatus = !( desiredAccess & RESOLVER_ACCESS_REGISTER );
  1005. #else
  1006. bstatus = TRUE;
  1007. #endif
  1008. Cleanup:
  1009. if ( htoken )
  1010. {
  1011. CloseHandle( htoken );
  1012. }
  1013. if ( hthread )
  1014. {
  1015. CloseHandle( hthread );
  1016. }
  1017. if ( fimpersonating )
  1018. {
  1019. RpcRevertToSelf();
  1020. }
  1021. return( bstatus );
  1022. }
  1023. //
  1024. // End rpc.c
  1025. //