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.

1517 lines
33 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. isrpc.cxx
  5. Abstract:
  6. Contains ISRPC class implementation.
  7. Author:
  8. Murali R. Krishnan 11-Dec-1995
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. /************************************************************
  14. * Include Headers
  15. ************************************************************/
  16. #ifndef dllexp
  17. #define dllexp __declspec( dllexport )
  18. #endif
  19. //
  20. // System include files.
  21. //
  22. #ifdef __cplusplus
  23. extern "C" {
  24. #endif
  25. #include <nt.h>
  26. #include <ntrtl.h>
  27. #include <nturtl.h>
  28. #include <windows.h>
  29. #include <winsock2.h>
  30. #include <lm.h>
  31. #include <stdio.h>
  32. #include <stdarg.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <tchar.h>
  36. //#include "dbgutil.h"
  37. //
  38. // Project include files.
  39. //
  40. //#include <inetcom.h>
  41. //#include <inetamsg.h>
  42. //#include <tcpproc.h>
  43. #ifdef __cplusplus
  44. } // extern "C"
  45. #endif // __cplusplus
  46. //#include <svcloc.h>
  47. //#define SECURITY_WIN32
  48. //#include <sspi.h> // Security Support Provider APIs
  49. //#include <schnlsp.h>
  50. //#include <lonsi.hxx>
  51. //#include "globals.hxx"
  52. #include "isrpc.hxx"
  53. /************************************************************
  54. * Functions
  55. ************************************************************/
  56. DWORD
  57. InetinfoStartRpcServerListen(
  58. VOID
  59. )
  60. /*++
  61. Routine Description:
  62. This function starts RpcServerListen for this process. The first
  63. service that is calling this function will actually start the
  64. RpcServerListen, subsequent calls are just noted down in num count.
  65. Arguments:
  66. None.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. RPC_STATUS Status = RPC_S_OK;
  72. Status = RpcServerListen(
  73. 1, // minimum num threads.
  74. RPC_C_LISTEN_MAX_CALLS_DEFAULT, // max concurrent calls.
  75. TRUE ); // don't wait
  76. return( Status );
  77. }
  78. DWORD
  79. InetinfoStopRpcServerListen(
  80. VOID
  81. )
  82. /*++
  83. Routine Description:
  84. Arguments:
  85. None.
  86. Return Value:
  87. None.
  88. --*/
  89. {
  90. RPC_STATUS Status = RPC_S_OK;
  91. Status = RpcMgmtStopServerListening(0);
  92. //
  93. // wait for all RPC threads to go away.
  94. //
  95. if( Status == RPC_S_OK) {
  96. Status = RpcMgmtWaitServerListen();
  97. }
  98. return( Status );
  99. }
  100. ISRPC::ISRPC(IN LPCTSTR pszServiceName)
  101. /*++
  102. This function constructs a new ISRPC object, initializing the
  103. members to proper state.
  104. Always the ISRPC members will use RPC_C_AUTHN_WINNT.
  105. Arguments:
  106. pszServiceName - pointer to string containing the name of the service
  107. dwServiceAuthId - DWORD containing the service Authentication Identifier.
  108. Returns:
  109. A valid initialized ISRPC object on success.
  110. --*/
  111. : m_dwProtocols ( 0),
  112. m_fInterfaceAdded ( FALSE),
  113. m_fEpRegistered ( FALSE),
  114. m_fServerStarted ( FALSE),
  115. m_hRpcInterface ( NULL),
  116. m_pszServiceName ( pszServiceName),
  117. m_pBindingVector ( NULL)
  118. {
  119. //DBG_REQUIRE( SetSecurityDescriptor() == NO_ERROR);
  120. SetSecurityDescriptor();
  121. } // ISRPC::ISRPC()
  122. ISRPC::~ISRPC(VOID)
  123. /*++
  124. This function cleans up the ISRPC object and releases any dynamic memory or
  125. state associated with this object.
  126. --*/
  127. {
  128. CleanupData();
  129. Cleanup();
  130. } // ISRPC::~ISRPC()
  131. DWORD
  132. ISRPC::CleanupData(VOID)
  133. /*++
  134. Routine Description:
  135. This member function cleans up the ISRPC object.
  136. Arguments:
  137. None.
  138. Return Value:
  139. None.
  140. --*/
  141. {
  142. DWORD rpcStatus = RPC_S_OK;
  143. if ( m_fServerStarted) {
  144. rpcStatus = StopServer( );
  145. }
  146. //DBG_ASSERT( rpcStatus == RPC_S_OK);
  147. rpcStatus = UnRegisterInterface();
  148. m_dwProtocols = 0;
  149. m_hRpcInterface = NULL;
  150. return (rpcStatus);
  151. } // ISRPC::CleanupData()
  152. RPC_STATUS RPC_ENTRY NNTPSecurityCallbackFn(
  153. IN RPC_IF_HANDLE InterfaceUuid,
  154. IN void *Context)
  155. {
  156. RPC_CALL_ATTRIBUTES CallAttributes;
  157. RPC_STATUS Status;
  158. CallAttributes.Version = RPC_CALL_ATTRIBUTES_VERSION;
  159. CallAttributes.Flags = 0;
  160. Status = RpcServerInqCallAttributesW(Context, &CallAttributes);
  161. if (Status != RPC_S_OK) return Status;
  162. if ( (CallAttributes.AuthenticationService == RPC_C_AUTHN_NONE)
  163. || (CallAttributes.AuthenticationLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
  164. || (CallAttributes.NullSession) )
  165. {
  166. return RPC_S_ACCESS_DENIED;
  167. }
  168. return RPC_S_OK;
  169. }
  170. DWORD
  171. ISRPC::RegisterInterface( IN RPC_IF_HANDLE hRpcInterface)
  172. /*++
  173. This function registers the RPC inteface in the object.
  174. If there is already a valid instance present in the object,
  175. this function fails and returns error.
  176. If this is the new interface specified, the function registers the
  177. interface both for dynamic and static bindings.
  178. Should be called after calling AddProtocol() and before StartServer()
  179. Arguments:
  180. hRpcInteface - RPC inteface handle.
  181. Returns:
  182. Win32 Error Code - NO_ERROR on success.
  183. --*/
  184. {
  185. DWORD dwError = NO_ERROR;
  186. if ( m_dwProtocols == 0) {
  187. // No protocol added. Return failure.
  188. return ( ERROR_INVALID_PARAMETER);
  189. }
  190. if ( m_hRpcInterface != NULL) {
  191. dwError = ( RPC_S_DUPLICATE_ENDPOINT);
  192. } else {
  193. //
  194. // since there is no duplicate, just set the new value and return.
  195. //
  196. if ( hRpcInterface == NULL) {
  197. dwError = ERROR_INVALID_PARAMETER;
  198. } else {
  199. m_hRpcInterface = hRpcInterface;
  200. }
  201. }
  202. if ( dwError == RPC_S_OK) {
  203. dwError = RpcServerRegisterIfEx(m_hRpcInterface,
  204. 0, // MgrUuid
  205. 0, // MgrEpv (Entry Point Vector)
  206. 0,
  207. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  208. NNTPSecurityCallbackFn
  209. );
  210. if ( dwError == RPC_S_OK ) {
  211. m_fInterfaceAdded = TRUE;
  212. //
  213. // Establish the dynamic bindings if any.
  214. //
  215. if ( (m_dwProtocols & (ISRPC_OVER_TCPIP | ISRPC_OVER_SPX)) != 0) {
  216. dwError = RpcServerInqBindings( &m_pBindingVector);
  217. if ( dwError == RPC_S_OK) {
  218. //DBG_ASSERT( m_pBindingVector != NULL);
  219. dwError = RpcEpRegister(m_hRpcInterface,
  220. m_pBindingVector,
  221. NULL,
  222. (unsigned char *) "" );
  223. if ( dwError == RPC_S_OK) {
  224. m_fEpRegistered = TRUE;
  225. }
  226. } // Ep registering
  227. } // dynamic bindings
  228. } // registration successful
  229. }
  230. return ( dwError);
  231. } // ISRPC::RegisterInterface()
  232. DWORD
  233. ISRPC::UnRegisterInterface( VOID)
  234. /*++
  235. This function unregisters the RPC inteface in the object.
  236. Should be called after after StopServer() and before cleanup.
  237. Arguments:
  238. None
  239. Returns:
  240. Win32 Error Code - NO_ERROR on success.
  241. --*/
  242. {
  243. DWORD rpcStatus = RPC_S_OK;
  244. if ( m_fEpRegistered) {
  245. //DBG_ASSERT( m_hRpcInterface != NULL && m_pBindingVector != NULL);
  246. rpcStatus = RpcEpUnregister(m_hRpcInterface,
  247. m_pBindingVector,
  248. NULL // pUuidVector
  249. );
  250. m_fEpRegistered = FALSE;
  251. }
  252. if ( m_pBindingVector != NULL) {
  253. rpcStatus = RpcBindingVectorFree( &m_pBindingVector);
  254. m_pBindingVector = NULL;
  255. }
  256. if ( m_fInterfaceAdded != NULL) {
  257. #if 1
  258. rpcStatus = RpcServerUnregisterIf(m_hRpcInterface,
  259. NULL, // MgrUuid
  260. TRUE // wait for calls to complete
  261. );
  262. #endif
  263. m_fInterfaceAdded = FALSE;
  264. }
  265. return ( rpcStatus);
  266. } // ISRPC::UnRegisterInterface()
  267. DWORD
  268. ISRPC::AddProtocol( IN DWORD Protocol)
  269. /*++
  270. Routine Description:
  271. This member function adds another protocol to the binding list.
  272. Arguments:
  273. protocol - protocol binding opcode.
  274. fDynamic - Boolean indicating if the call should do dynamic or static
  275. RPC binding for the protocol specified.
  276. Return Value:
  277. RPC error code.
  278. --*/
  279. {
  280. DWORD rpcStatus = RPC_S_OK;
  281. if ( Protocol & ISRPC_OVER_LPC ) {
  282. // Currently we only support static binding
  283. rpcStatus = BindOverLpc( FALSE);
  284. }
  285. #ifndef CHICAGO
  286. //
  287. // Enable all remote bindings
  288. //
  289. if ( rpcStatus == RPC_S_OK ) {
  290. if ( Protocol & ISRPC_OVER_TCPIP ) {
  291. // Currently we only support dynamic binding
  292. rpcStatus = BindOverTcp( TRUE);
  293. }
  294. if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_NP ) {
  295. // Currently we only support static binding
  296. rpcStatus = BindOverNamedPipe( FALSE);
  297. }
  298. if ( rpcStatus == RPC_S_OK && Protocol & ISRPC_OVER_SPX ) {
  299. // Currently we only support dynamic binding
  300. rpcStatus = BindOverSpx( TRUE);
  301. }
  302. }
  303. #else // CHICAGO
  304. rpcStatus = RPC_S_OK;
  305. if ( Protocol & ISRPC_OVER_TCPIP ) {
  306. // Currently we only support dynamic binding
  307. rpcStatus = BindOverTcp( TRUE);
  308. }
  309. if ( Protocol & ISRPC_OVER_NB ) {
  310. // Currently we only support dynamic binding
  311. // Ignore status for NB for now
  312. (VOID)BindOverNetBios(TRUE);
  313. }
  314. #endif // CHICAGO
  315. return( rpcStatus );
  316. } // ISRPC::AddProtocol()
  317. DWORD
  318. ISRPC::RemoveProtocol(IN DWORD Protocol)
  319. /*++
  320. Routine Description:
  321. This member function removes a protocol from the binding list.
  322. Arguments:
  323. protocol - protocol binding opcode.
  324. Return Value:
  325. RPC error code.
  326. Note:
  327. As a side effect, this function removes the dynamic endpoing on
  328. TCPIP when SPX binding is removed and vice-versa.
  329. --*/
  330. {
  331. return ( ERROR_CALL_NOT_IMPLEMENTED);
  332. } // ISRPC::RemoveProtocol()
  333. DWORD
  334. ISRPC::StartServer(
  335. VOID
  336. )
  337. /*++
  338. Routine Description:
  339. This member function start RPC server.
  340. Arguments:
  341. None.
  342. Return Value:
  343. RPC error code.
  344. --*/
  345. {
  346. DWORD rpcStatus;
  347. //
  348. // add the interface.
  349. //
  350. if ( m_hRpcInterface == NULL) {
  351. return (ERROR_INVALID_PARAMETER);
  352. }
  353. //
  354. // start rpc server.
  355. //
  356. #ifndef SERVICE_AS_EXE
  357. rpcStatus = InetinfoStartRpcServerListen();
  358. #else
  359. rpcStatus = RpcServerListen(
  360. 1, // minimum num threads.
  361. 1, // max concurrent calls.
  362. TRUE ); // don't wait
  363. #endif // SERVICE_AS_EXE
  364. if ( rpcStatus == RPC_S_OK ) {
  365. m_fServerStarted = TRUE;
  366. }
  367. return( rpcStatus );
  368. } // ISRPC::StartServer()
  369. DWORD
  370. ISRPC::StopServer(
  371. VOID
  372. )
  373. {
  374. DWORD rpcStatus = RPC_S_OK;
  375. if( m_fServerStarted ) {
  376. #ifndef SERVICE_AS_EXE
  377. rpcStatus = InetinfoStopRpcServerListen();
  378. #else
  379. //
  380. // stop server listen.
  381. //
  382. rpcStatus = RpcMgmtStopServerListening(0);
  383. //
  384. // wait for all RPC threads to go away.
  385. //
  386. if( rpcStatus == RPC_S_OK) {
  387. rpcStatus = RpcMgmtWaitServerListen();
  388. }
  389. #endif // SERVICE_AS_EXE
  390. m_fServerStarted = FALSE;
  391. }
  392. return ( rpcStatus);
  393. } // ISRPC::StopServer()
  394. DWORD
  395. ISRPC::EnumBindingStrings(
  396. IN OUT LPINET_BINDINGS pBindings
  397. )
  398. /*++
  399. Routine Description:
  400. This member function enumurates the binding strings of the protocols
  401. bound to the server.
  402. Arguments:
  403. pBindings : pointer to a binding strings structure. The caller
  404. should call FreeBindingStrings member function to free the string
  405. after use.
  406. Return Value:
  407. Windows Error Code;
  408. --*/
  409. {
  410. DWORD dwError;
  411. RPC_BINDING_VECTOR * pBindingVector = NULL;
  412. LPINET_BIND_INFO pBindingsInfo;
  413. DWORD dwCount = 0;
  414. DWORD i;
  415. //
  416. // query RPC for RPC_BINDING_VECTORS.
  417. //
  418. dwError = RpcServerInqBindings( &pBindingVector );
  419. if( dwError != NO_ERROR ) {
  420. goto Cleanup;
  421. }
  422. //DBG_ASSERT( pBindingVector->Count > 0 );
  423. //
  424. // alloc memory for INET_RPC_BINDING_STRINGS.
  425. //
  426. pBindingsInfo = (LPINET_BIND_INFO)
  427. LocalAlloc( GPTR, sizeof(INET_BIND_INFO) * pBindingVector->Count );
  428. if( pBindingsInfo == NULL ) {
  429. dwError = ERROR_NOT_ENOUGH_MEMORY;
  430. goto Cleanup;
  431. }
  432. //
  433. // convert binding handle to binding vectors.
  434. //
  435. pBindings->NumBindings = 0;
  436. pBindings->BindingsInfo = pBindingsInfo;
  437. for( i = 0; i < pBindingVector->Count; i++ ) {
  438. LPSTR BindingString;
  439. BindingString = NULL;
  440. dwError = RpcBindingToStringBindingA(pBindingVector->BindingH[i],
  441. (LPBYTE *)&BindingString );
  442. if( dwError != NO_ERROR ) {
  443. goto Cleanup;
  444. }
  445. //
  446. // check to we get only our named-pipe endpoint.
  447. //
  448. if( strstr( BindingString, "ncacn_np" ) != NULL ) {
  449. //
  450. // found a named-pipe binding string.
  451. //
  452. if( strstr(BindingString,
  453. m_pszServiceName ) == NULL ) {
  454. //
  455. // found a non service named-pipe entry.
  456. // ignore it.
  457. //
  458. RpcStringFreeA( (LPBYTE *)&BindingString );
  459. } else {
  460. pBindings->BindingsInfo[dwCount].Length =
  461. (strlen(BindingString) + 1) * sizeof(CHAR);
  462. pBindings->BindingsInfo[dwCount].BindData = BindingString;
  463. dwCount++;
  464. }
  465. }
  466. } // for
  467. dwError = NO_ERROR;
  468. pBindings->NumBindings = dwCount;
  469. Cleanup:
  470. if( pBindingVector != NULL ) {
  471. DWORD LocalError;
  472. LocalError = RpcBindingVectorFree( &pBindingVector );
  473. //DBG_ASSERT( LocalError == NO_ERROR );
  474. }
  475. if( dwError != NO_ERROR ) {
  476. FreeBindingStrings( pBindings );
  477. pBindings->NumBindings = 0;
  478. }
  479. return( dwError );
  480. } // ISRPC::EnumBindingStrings()
  481. VOID
  482. ISRPC::FreeBindingStrings(
  483. IN OUT LPINET_BINDINGS pInetBindings
  484. )
  485. /*++
  486. Routine Description:
  487. This member function deletes a binding vector that was returned by the
  488. EnumBindingStrings member function.
  489. Arguments:
  490. pBindings : pointer to a binding vector.
  491. Return Value:
  492. Windows Error Code;
  493. --*/
  494. {
  495. DWORD dwError;
  496. DWORD i;
  497. //
  498. // free binding strings.
  499. //
  500. for( i = 0; i < pInetBindings->NumBindings; i++) {
  501. dwError = RpcStringFreeA( ((LPBYTE *)&pInetBindings
  502. ->BindingsInfo[i].BindData ));
  503. //DBG_ASSERT( dwError == NO_ERROR );
  504. }
  505. pInetBindings->NumBindings = 0;
  506. //
  507. // free bindings info array.
  508. //
  509. if( pInetBindings->BindingsInfo != NULL ) {
  510. LocalFree( (LPWSTR)pInetBindings->BindingsInfo );
  511. pInetBindings->BindingsInfo = NULL;
  512. }
  513. return;
  514. } // ISRPC::FreeBindingStrings()
  515. DWORD
  516. ISRPC::BindOverTcp(IN BOOL fDynamic)
  517. {
  518. DWORD rpcStatus = RPC_S_OK;
  519. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_TCPIP) == 0);
  520. if ( !fDynamic) {
  521. rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
  522. } else {
  523. rpcStatus = ( ISRPC::DynamicBindOverTcp());
  524. }
  525. if ( rpcStatus == RPC_S_OK) {
  526. m_dwProtocols |= ISRPC_OVER_TCPIP;
  527. }
  528. return ( rpcStatus);
  529. } // ISRPC::BindOverTcpIp()
  530. #ifdef CHICAGO
  531. DWORD
  532. ISRPC::BindOverNetBios(IN BOOL fDynamic)
  533. {
  534. DWORD rpcStatus = RPC_S_OK;
  535. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NB) == 0);
  536. if ( !fDynamic) {
  537. return ( ERROR_CALL_NOT_IMPLEMENTED);
  538. }
  539. // We will use Dynamic endpoint for the NetBios binding.
  540. rpcStatus =
  541. RpcServerUseProtseqW(
  542. L"ncacn_nb_ipx", // protocol string.
  543. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  544. &sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
  545. rpcStatus =
  546. RpcServerUseProtseqW(
  547. L"ncacn_nb_tcp", // protocol string.
  548. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  549. &sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
  550. switch (rpcStatus) {
  551. case RPC_S_OK:
  552. //
  553. // set the protocol bit.
  554. //
  555. m_dwProtocols |= ISRPC_OVER_NB;
  556. break;
  557. case RPC_S_DUPLICATE_ENDPOINT:
  558. //DBGPRINTF(( DBG_CONTEXT,
  559. // "(%08x) ncacn_nb is already added for %s\n",
  560. // this,
  561. // m_pszServiceName));
  562. rpcStatus = RPC_S_OK;
  563. break;
  564. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  565. case RPC_S_CANT_CREATE_ENDPOINT:
  566. //DBGPRINTF(( DBG_CONTEXT,
  567. // "(%08x) ncacn_nb is not supported for %s (%ld).\n",
  568. // this, m_pszServiceName, rpcStatus ));
  569. rpcStatus = RPC_S_OK;
  570. break;
  571. default:
  572. break;
  573. } // switch()
  574. //
  575. // if the security support provider is not enabled, do so.
  576. //
  577. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
  578. rpcStatus = AddSecurity();
  579. }
  580. return ( rpcStatus);
  581. } // ISRPC::BindOverNetBios()
  582. #endif // CHICAGO
  583. DWORD
  584. ISRPC::BindOverNamedPipe(IN BOOL fDynamic)
  585. {
  586. DWORD rpcStatus = RPC_S_OK;
  587. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_NP) == 0);
  588. //
  589. // On Named Pipe, we support only static bindings. No dynamic Binding.
  590. //
  591. if ( fDynamic) {
  592. return ( ERROR_CALL_NOT_IMPLEMENTED);
  593. }
  594. if( (m_dwProtocols & ISRPC_OVER_NP) == 0 ) {
  595. WCHAR rgchNp[1024];
  596. wsprintfW( rgchNp,
  597. #ifdef UNICODE
  598. L"%ws%s"
  599. #else
  600. L"%ws%S"
  601. #endif // UNICODE
  602. ,
  603. ISRPC_NAMED_PIPE_PREFIX_W,
  604. m_pszServiceName);
  605. //
  606. // Establish a static Named pipe binding.
  607. //
  608. rpcStatus =
  609. RpcServerUseProtseqEpW(
  610. L"ncacn_np", // protocol string.
  611. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  612. rgchNp, // end point!
  613. &sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
  614. switch (rpcStatus) {
  615. case RPC_S_OK:
  616. //
  617. // set the protocol bit.
  618. //
  619. m_dwProtocols |= ISRPC_OVER_NP;
  620. break;
  621. case RPC_S_DUPLICATE_ENDPOINT:
  622. //
  623. // Ignore the duplicate end point error
  624. //
  625. //DBGPRINTF(( DBG_CONTEXT,
  626. // "(%08x) ncacn_np is already added for %s\n",
  627. // this,
  628. // m_pszServiceName));
  629. m_dwProtocols |= ISRPC_OVER_NP;
  630. rpcStatus = RPC_S_OK;
  631. break;
  632. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  633. case RPC_S_CANT_CREATE_ENDPOINT:
  634. //DBGPRINTF(( DBG_CONTEXT,
  635. // "(%08x) ncacn_np is not supported for %s (%ld).\n",
  636. // this, m_pszServiceName, rpcStatus ));
  637. rpcStatus = RPC_S_OK;
  638. break;
  639. default:
  640. break;
  641. } // switch()
  642. }
  643. return ( rpcStatus);
  644. } // ISRPC::BindOverNamedPipe()
  645. DWORD
  646. ISRPC::BindOverLpc(IN BOOL fDynamic)
  647. {
  648. DWORD rpcStatus = RPC_S_OK;
  649. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_LPC) == 0);
  650. //
  651. // On LPC, we support only static bindings. No dynamic Binding.
  652. //
  653. if ( fDynamic) {
  654. return ( ERROR_CALL_NOT_IMPLEMENTED);
  655. }
  656. if( (m_dwProtocols & ISRPC_OVER_LPC) == 0 ) {
  657. WCHAR rgchLpc[1024];
  658. // LPC Endpoint string is: <InterfaceName>_LPC
  659. wsprintfW( rgchLpc,
  660. #ifdef UNICODE
  661. L"%s_%ws"
  662. #else
  663. L"%S_%ws"
  664. #endif // UNICODE
  665. ,
  666. m_pszServiceName,
  667. ISRPC_LPC_NAME_SUFFIX_W);
  668. //
  669. // Establish a static Lpc binding.
  670. //
  671. rpcStatus =
  672. RpcServerUseProtseqEpW(
  673. L"ncalrpc", // protocol string.
  674. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  675. rgchLpc, // end point!
  676. &sm_sid[ACL_INDEX_ALLOW_ALL] ); // security
  677. switch (rpcStatus) {
  678. case RPC_S_OK:
  679. //
  680. // set the protocol bit.
  681. //
  682. m_dwProtocols |= ISRPC_OVER_LPC;
  683. break;
  684. case RPC_S_DUPLICATE_ENDPOINT:
  685. //
  686. // Ignore the duplicate end point error
  687. //
  688. //DBGPRINTF(( DBG_CONTEXT,
  689. // "(%08x) ncalrpc is already added for %s\n",
  690. // this,
  691. // m_pszServiceName));
  692. m_dwProtocols |= ISRPC_OVER_LPC;
  693. rpcStatus = RPC_S_OK;
  694. break;
  695. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  696. case RPC_S_CANT_CREATE_ENDPOINT:
  697. //DBGPRINTF(( DBG_CONTEXT,
  698. // "(%08x) ncalrpc is not supported for %s (%ld).\n",
  699. // this, m_pszServiceName, rpcStatus ));
  700. rpcStatus = RPC_S_OK;
  701. break;
  702. default:
  703. break;
  704. } // switch()
  705. }
  706. return ( rpcStatus);
  707. } // ISRPC::BindOverLpc()
  708. DWORD
  709. ISRPC::BindOverSpx(IN BOOL fDynamic)
  710. {
  711. DWORD rpcStatus = RPC_S_OK;
  712. //DBG_ASSERT( (m_dwProtocols & ISRPC_OVER_SPX) == 0);
  713. if ( !fDynamic) {
  714. rpcStatus = ( ERROR_CALL_NOT_IMPLEMENTED);
  715. } else {
  716. rpcStatus = ISRPC::DynamicBindOverSpx();
  717. }
  718. if ( rpcStatus == RPC_S_OK) {
  719. m_dwProtocols |= ISRPC_OVER_SPX;
  720. }
  721. return ( rpcStatus);
  722. } // ISRPC::BindOverSpx()
  723. # if DBG
  724. VOID
  725. ISRPC::Print(VOID) const
  726. {
  727. } // ISRPC::Print()
  728. # endif // DBG
  729. /******************************
  730. * STATIC Member Definitions
  731. ******************************/
  732. DWORD ISRPC::sm_dwProtocols = 0;
  733. SECURITY_DESCRIPTOR ISRPC::sm_sid[2];
  734. PACL ISRPC::sm_pACL[2];
  735. BOOL ISRPC::sm_fSecurityEnabled = FALSE;
  736. DWORD
  737. ISRPC::Initialize(VOID)
  738. {
  739. sm_dwProtocols = 0;
  740. return SetSecurityDescriptor();
  741. } // ISRPC::Initialize()
  742. DWORD
  743. ISRPC::Cleanup(VOID)
  744. {
  745. //
  746. // Free up the memory holding the ACL for the security descriptor
  747. //
  748. delete [] ((BYTE *) sm_pACL[0]);
  749. sm_pACL[0] = NULL;
  750. delete [] ((BYTE *) sm_pACL[1]);
  751. sm_pACL[1] = NULL;
  752. //
  753. // Free up the security descriptor
  754. //
  755. ZeroMemory( (PVOID) &sm_sid, sizeof(sm_sid));
  756. //
  757. // For now nothing to do. Just a place holder.
  758. //
  759. return ( NO_ERROR);
  760. } // ISRPC::Cleanup()
  761. DWORD
  762. ISRPC::DynamicBindOverTcp(VOID)
  763. /*++
  764. This static function (ISRPC member) establishes a dynamic endpoing
  765. RPC binding over TCP/IP, using a run-time library call to RPC.
  766. RPC run-time library allows one to create as many dynamic end points
  767. as one wishes. So we maintain external state and control the number
  768. of end points created to 1.
  769. Arguments:
  770. None
  771. Returns:
  772. RPC status - RPC_S_OK for success.
  773. --*/
  774. {
  775. DWORD rpcStatus = RPC_S_OK;
  776. if( (sm_dwProtocols & ISRPC_OVER_TCPIP) == 0 ) {
  777. //
  778. // Not already present. Add dynamic endpoint over TCP/IP
  779. //
  780. rpcStatus =
  781. RpcServerUseProtseqW(
  782. L"ncacn_ip_tcp", // protocol string.
  783. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  784. &sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
  785. switch (rpcStatus) {
  786. case RPC_S_OK:
  787. //
  788. // set the protocol bit.
  789. //
  790. sm_dwProtocols |= ISRPC_OVER_TCPIP;
  791. break;
  792. case RPC_S_DUPLICATE_ENDPOINT:
  793. //DBGPRINTF(( DBG_CONTEXT,
  794. // "ncacn_ip_tcp is already added.\n"));
  795. sm_dwProtocols |= ISRPC_OVER_TCPIP;
  796. rpcStatus = RPC_S_OK;
  797. break;
  798. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  799. case RPC_S_CANT_CREATE_ENDPOINT:
  800. //DBGPRINTF(( DBG_CONTEXT,
  801. // "ncacn_ip_tcp is not supported. Error = %ld\n",
  802. // rpcStatus));
  803. break;
  804. default:
  805. break;
  806. } // switch()
  807. //
  808. // if the security support provider is not enabled, do so.
  809. //
  810. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled() ) {
  811. rpcStatus = AddSecurity();
  812. }
  813. }
  814. return ( rpcStatus);
  815. } // ISRPC::DynamicBindOverTcp()
  816. DWORD
  817. ISRPC::DynamicBindOverSpx(VOID)
  818. /*++
  819. This static function (ISRPC member) establishes a dynamic endpoing
  820. RPC binding over SPX, using a run-time library call to RPC.
  821. RPC run-time library allows one to create as many dynamic end points
  822. as one wishes. So we maintain external state and control the number
  823. of end points created to 1.
  824. Arguments:
  825. None
  826. Returns:
  827. RPC status - RPC_S_OK for success.
  828. --*/
  829. {
  830. DWORD rpcStatus = RPC_S_OK;
  831. if( (sm_dwProtocols & ISRPC_OVER_SPX) == 0 ) {
  832. // Use dynamic end point for the server.
  833. rpcStatus =
  834. RpcServerUseProtseqW(
  835. L"ncacn_spx", // protocol string.
  836. ISRPC_PROTSEQ_MAX_REQS, //max concurrent calls
  837. &sm_sid[ACL_INDEX_ALLOW_ADMIN] ); // security
  838. switch (rpcStatus) {
  839. case RPC_S_OK:
  840. //
  841. // set the protocol bit.
  842. //
  843. sm_dwProtocols |= ISRPC_OVER_SPX;
  844. break;
  845. case RPC_S_DUPLICATE_ENDPOINT:
  846. //DBGPRINTF(( DBG_CONTEXT,
  847. // "ncacn_spx is already added.\n"
  848. // ));
  849. sm_dwProtocols |= ISRPC_OVER_SPX;
  850. rpcStatus = RPC_S_OK;
  851. break;
  852. case RPC_S_PROTSEQ_NOT_SUPPORTED:
  853. case RPC_S_CANT_CREATE_ENDPOINT:
  854. //DBGPRINTF(( DBG_CONTEXT,
  855. // "ncacn_spx is not supported. Error (%ld).\n",
  856. // rpcStatus ));
  857. break;
  858. default:
  859. break;
  860. } // switch()
  861. //
  862. // if the security support provider is not enabled, do so.
  863. //
  864. if( rpcStatus == RPC_S_OK && !IsSecurityEnabled()) {
  865. rpcStatus = AddSecurity();
  866. }
  867. }
  868. return ( rpcStatus);
  869. } // ISRPC::DynamicBindOverSpx()
  870. DWORD
  871. ISRPC::SetSecurityDescriptor( VOID)
  872. /*++
  873. Routine Description:
  874. This member function builds the security descriptor used by RPC module.
  875. The security descriptor denies everybody the ability to change/see anything
  876. connected to the DACL and allows everybody to read from/write to the pipe.
  877. Arguments:
  878. None.
  879. Return Value:
  880. Windows error code.
  881. --*/
  882. {
  883. DWORD dwError = NO_ERROR;
  884. BOOL fSuccess = FALSE;
  885. SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
  886. SID_IDENTIFIER_AUTHORITY siaNt = SECURITY_NT_AUTHORITY;
  887. PSID psidWorld = NULL;
  888. PSID psidAdmins = NULL;
  889. int sdCount;
  890. sm_pACL[0] = NULL;
  891. sm_pACL[1] = NULL;
  892. //
  893. // Create the "WORLD" sid
  894. //
  895. if ( !AllocateAndInitializeSid( &siaWorld,
  896. 1,
  897. SECURITY_WORLD_RID,
  898. 0,0,0,0,0,0,0,
  899. &psidWorld )
  900. || !AllocateAndInitializeSid( &siaNt,
  901. 2,
  902. SECURITY_BUILTIN_DOMAIN_RID,
  903. DOMAIN_ALIAS_RID_ADMINS,
  904. 0,0,0,0,0,0,
  905. &psidAdmins ) )
  906. {
  907. goto cleanup;
  908. }
  909. for (sdCount=0; sdCount<2; sdCount++)
  910. {
  911. BYTE *pbBuffer = NULL;
  912. DWORD cbAcl = 0;
  913. PSID pSid2Allow = (ACL_INDEX_ALLOW_ALL == sdCount)? psidWorld: psidAdmins;
  914. InitializeSecurityDescriptor(&sm_sid[sdCount],
  915. SECURITY_DESCRIPTOR_REVISION );
  916. //
  917. // Calculate the size of the ACL that will hold the the ACESS_DENIED and ACCESS_ALLOW ace
  918. // [ripped off from MSDN docs]
  919. //
  920. cbAcl = sizeof(ACL) +
  921. sizeof( ACCESS_ALLOWED_ACE ) +
  922. sizeof( ACCESS_DENIED_ACE ) +
  923. GetLengthSid(psidWorld) +
  924. GetLengthSid(pSid2Allow) -
  925. 2*sizeof(DWORD) ;
  926. if ( ! ( pbBuffer = new BYTE[cbAcl] ) )
  927. {
  928. goto cleanup;
  929. }
  930. sm_pACL[sdCount] = (PACL) pbBuffer;
  931. //
  932. // Initialize the ACL
  933. //
  934. if ( !InitializeAcl( sm_pACL[sdCount],
  935. cbAcl,
  936. ACL_REVISION ) )
  937. {
  938. goto cleanup;
  939. }
  940. //
  941. // Add the Access Denied ACE; this has to be first in the list to make sure
  942. // that any attempt to muck with the DACL will be disallowed
  943. //
  944. if ( !AddAccessDeniedAce( sm_pACL[sdCount],
  945. ACL_REVISION,
  946. WRITE_DAC | DELETE | WRITE_OWNER,
  947. psidWorld ) )
  948. {
  949. goto cleanup;
  950. }
  951. //
  952. // Add the Access Allowed ACE
  953. //
  954. if ( !AddAccessAllowedAce( sm_pACL[sdCount],
  955. ACL_REVISION,
  956. FILE_ALL_ACCESS,
  957. pSid2Allow ) )
  958. {
  959. goto cleanup;
  960. }
  961. //
  962. // Set (no) group & owner for the security descriptor
  963. //
  964. if ( !SetSecurityDescriptorOwner( &sm_sid[sdCount],
  965. NULL,
  966. FALSE ) )
  967. {
  968. goto cleanup;
  969. }
  970. if ( !SetSecurityDescriptorGroup( &sm_sid[sdCount],
  971. NULL,
  972. FALSE ) )
  973. {
  974. goto cleanup;
  975. }
  976. if ( !( fSuccess = SetSecurityDescriptorDacl ( &sm_sid[sdCount],
  977. TRUE, // Dacl present
  978. sm_pACL[sdCount],
  979. FALSE ) ) ) // Not defaulted
  980. {
  981. goto cleanup;
  982. }
  983. }
  984. cleanup:
  985. if ( psidWorld )
  986. {
  987. FreeSid( psidWorld );
  988. }
  989. if ( psidAdmins )
  990. {
  991. FreeSid( psidAdmins );
  992. }
  993. if (!fSuccess)
  994. {
  995. dwError = GetLastError();
  996. if ( sm_pACL[0] )
  997. {
  998. delete (BYTE*) sm_pACL[0];
  999. sm_pACL[0] = NULL;
  1000. }
  1001. if ( sm_pACL[1] )
  1002. {
  1003. delete (BYTE*) sm_pACL[1];
  1004. sm_pACL[1] = NULL;
  1005. }
  1006. //
  1007. // free up security discriptor memory and set it to NULL.
  1008. //
  1009. memset( (PVOID ) &sm_sid, 0, sizeof(sm_sid));
  1010. }
  1011. return( dwError );
  1012. } // ISRPC::SetSecurityDescriptor()
  1013. DWORD
  1014. ISRPC::AddSecurity(
  1015. VOID
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This member function adds security support provider over RPC.
  1020. Arguments:
  1021. None.
  1022. Return Value:
  1023. Windows error code.
  1024. --*/
  1025. {
  1026. DWORD rpcStatus;
  1027. //
  1028. // Register for authentication using WinNT.
  1029. //
  1030. rpcStatus = RpcServerRegisterAuthInfo(
  1031. (unsigned char * ) NULL, // app name to security provider
  1032. RPC_C_AUTHN_WINNT, // Auth package ID.
  1033. NULL, // RPC_C_AUTHN_WINNT ==> NULL
  1034. NULL // args ptr for authn function.
  1035. );
  1036. if ( rpcStatus == RPC_S_OK) {
  1037. sm_fSecurityEnabled = TRUE;
  1038. }
  1039. return (rpcStatus);
  1040. } // ISRPC::AddSecurity()