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.

6326 lines
157 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1992 - 1999
  3. Module Name:
  4. dgsvr.cxx
  5. Abstract:
  6. This is the server protocol code for datagram rpc.
  7. Author:
  8. Dave Steckler (davidst) 15-Dec-1992
  9. Revision History:
  10. Jeff Roberts (jroberts) 11-22-1994
  11. Rewrote it.
  12. Jeff Roberts (jroberts) 9-30-1996
  13. Began asynchronous call support.
  14. Edward Reus (edwardr) 7-09-1997
  15. Support for large packets (Falcon).
  16. --*/
  17. #include <precomp.hxx>
  18. //
  19. // Remember that any #defines must go AFTER the precompiled header in order
  20. // to be noticed by the compiler.
  21. //
  22. // uncomment this to have the server try the msconv interface, used by NT5 beta 1.
  23. //
  24. // #define TRY_MSCONV_INTERFACE
  25. #include "sdict2.hxx"
  26. #include "secsvr.hxx"
  27. #include "hndlsvr.hxx"
  28. #include "dgpkt.hxx"
  29. #include "delaytab.hxx"
  30. #include "hashtabl.hxx"
  31. #include "locks.hxx"
  32. #include "dgclnt.hxx"
  33. #include "dgsvr.hxx"
  34. #include <conv.h>
  35. #include <convc.h>
  36. #ifdef TRY_MSCONV_INTERFACE
  37. #include <msconv.h>
  38. #endif
  39. #define IDLE_SCONNECTION_LIFETIME (3 * 60 * 1000)
  40. #define IDLE_SCONNECTION_SWEEP_INTERVAL (30 * 1000)
  41. #define IDLE_SCALL_LIFETIME (15 * 1000)
  42. struct REMOTE_ADDRESS_INFO
  43. {
  44. #pragma warning(disable:4200)
  45. unsigned RemoteInfoLength;
  46. unsigned SecurityInfoPadLength;
  47. byte Address[];
  48. #pragma warning(default:4200)
  49. };
  50. //------------------------------------------------------------------------
  51. LONG fPruning = FALSE;
  52. SERVER_ACTIVITY_TABLE * ServerConnections;
  53. ASSOC_GROUP_TABLE * AssociationGroups;
  54. LONG ServerConnectionCount = 0;
  55. LONG ServerCallCount = 0;
  56. #ifdef INTRODUCE_ERRORS
  57. extern long ServerDelayTime;
  58. extern long ServerDelayRate;
  59. extern long ServerDropRate;
  60. #endif
  61. //--------------------------------------------------------------------
  62. extern int
  63. StringLengthWithEscape (
  64. IN RPC_CHAR * String
  65. );
  66. extern RPC_CHAR *
  67. StringCopyEscapeCharacters (
  68. OUT RPC_CHAR * Destination,
  69. IN RPC_CHAR * Source
  70. );
  71. void
  72. ServerCallScavengerProc(
  73. void * Parms
  74. );
  75. RPC_STATUS
  76. InitializeServerGlobals(
  77. );
  78. void
  79. InterpretFailureOptions(
  80. );
  81. //--------------------------------------------------------------------
  82. #if !defined(WIN96)
  83. char __pure_virtual_called()
  84. {
  85. ASSERT(0 && "rpc: pure virtual fn called in dg");
  86. return 0;
  87. }
  88. #endif
  89. boolean ServerGlobalsInitialized = FALSE;
  90. RPC_STATUS
  91. InitializeServerGlobals(
  92. )
  93. /*++
  94. Routine Description:
  95. This fn initializes all the global variables used by the datagram
  96. server. If anything fails, all the objects are destroyed.
  97. Arguments:
  98. none
  99. Return Value:
  100. RPC_S_OK if ok
  101. RPC_S_OUT_OF_MEMORY if an object could not be created
  102. --*/
  103. {
  104. RPC_STATUS Status = RPC_S_OK;
  105. //
  106. // Don't take the global mutex if we can help it.
  107. //
  108. if (ServerGlobalsInitialized)
  109. {
  110. return 0;
  111. }
  112. RequestGlobalMutex();
  113. if (0 != InitializeRpcProtocolDgClient())
  114. {
  115. ClearGlobalMutex();
  116. return RPC_S_OUT_OF_MEMORY;
  117. }
  118. if (!ServerGlobalsInitialized)
  119. {
  120. ServerConnections = new SERVER_ACTIVITY_TABLE(&Status);
  121. if (!ServerConnections)
  122. {
  123. Status = RPC_S_OUT_OF_MEMORY;
  124. }
  125. if (Status != RPC_S_OK)
  126. {
  127. goto abend;
  128. }
  129. AssociationGroups = new ASSOC_GROUP_TABLE(&Status);
  130. if (!AssociationGroups)
  131. {
  132. Status = RPC_S_OUT_OF_MEMORY;
  133. }
  134. if (Status != RPC_S_OK)
  135. {
  136. goto abend;
  137. }
  138. ServerGlobalsInitialized = TRUE;
  139. }
  140. ClearGlobalMutex();
  141. return Status;
  142. //--------------------------------------------------------------------
  143. abend:
  144. delete AssociationGroups;
  145. AssociationGroups = 0;
  146. delete ServerConnections;
  147. ServerConnections = 0;
  148. ClearGlobalMutex();
  149. return Status;
  150. }
  151. RPC_ADDRESS *
  152. DgCreateRpcAddress (
  153. IN TRANS_INFO * TransportInfo
  154. )
  155. /*++
  156. Routine Description:
  157. This is a psuedo-constructor for the DG_ADDRESS class. This is done this
  158. way so that the calling routine doesn't have to have any protocol-specific
  159. knowledge.
  160. Arguments:
  161. TransportInterface - Pointer to a PDG_RPC_SERVER_TRANSPORT_INFO.
  162. pStatus - Pointer to where to put the return value
  163. Return Value:
  164. pointer to new DG_ADDRESS.
  165. --*/
  166. {
  167. //
  168. // If the global active call table hasn't been initialized, then do
  169. // so now.
  170. //
  171. if (0 != InitializeServerGlobals())
  172. {
  173. return 0;
  174. }
  175. RPC_STATUS Status = RPC_S_OK;
  176. PDG_ADDRESS Address;
  177. Address = new (TransportInfo) DG_ADDRESS(
  178. TransportInfo,
  179. &Status
  180. );
  181. if (!Address)
  182. {
  183. return 0;
  184. }
  185. if (Status != RPC_S_OK)
  186. {
  187. delete Address;
  188. return 0;
  189. }
  190. return Address;
  191. }
  192. DG_ADDRESS::DG_ADDRESS(
  193. TRANS_INFO * a_LoadableTransport,
  194. RPC_STATUS * pStatus
  195. )
  196. : RPC_ADDRESS(pStatus),
  197. TotalThreadsThisEndpoint (0),
  198. ThreadsReceivingThisEndpoint(0),
  199. MinimumCallThreads (0),
  200. MaximumConcurrentCalls (0),
  201. CachedConnections (0),
  202. ActiveCallCount (0),
  203. AutoListenCallCount (0)
  204. /*++
  205. Routine Description:
  206. This is the constructor for a DG_ADDRESS.
  207. Arguments:
  208. TransportInterface - Pointer to a PDG_RPC_SERVER_TRANSPORT_INFO
  209. pStatus - Pointer to where to put the return value
  210. Return Value:
  211. None (this is a constructor)
  212. Revision History:
  213. --*/
  214. {
  215. TransInfo = a_LoadableTransport;
  216. ObjectType = DG_ADDRESS_TYPE;
  217. //
  218. // Make sure the RPC_ADDRESS (et. al.) initialized correctly.
  219. //
  220. if (*pStatus != RPC_S_OK)
  221. {
  222. return;
  223. }
  224. Endpoint.TransportInterface = (RPC_DATAGRAM_TRANSPORT *)
  225. TransInfo->InqTransInfo();
  226. }
  227. DG_ADDRESS::~DG_ADDRESS()
  228. /*++
  229. Routine Description:
  230. This is the destructor for a DG_ADDRESS.
  231. It is called only if the endpoint failed!
  232. Arguments:
  233. <None>
  234. Return Value:
  235. <None>
  236. --*/
  237. {
  238. }
  239. inline void
  240. DG_ADDRESS::BeginAutoListenCall (
  241. )
  242. {
  243. AutoListenCallCount.Increment() ;
  244. }
  245. inline void
  246. DG_ADDRESS::EndAutoListenCall (
  247. )
  248. {
  249. ASSERT(AutoListenCallCount.GetInteger() >= 1);
  250. AutoListenCallCount.Decrement() ;
  251. }
  252. void
  253. DG_ADDRESS::WaitForCalls(
  254. )
  255. {
  256. while (InqNumberOfActiveCalls() > AutoListenCallCount.GetInteger())
  257. {
  258. ServerConnections->PruneEntireTable(0);
  259. PauseExecution(500);
  260. }
  261. }
  262. void
  263. DG_ADDRESS::EncourageCallCleanup(
  264. RPC_INTERFACE * Interface
  265. )
  266. {
  267. if (ServerGlobalsInitialized && AutoListenCallCount.GetInteger() > 0)
  268. {
  269. ServerConnections->PruneEntireTable(Interface);
  270. }
  271. }
  272. RPC_STATUS
  273. DG_ADDRESS::ServerSetupAddress (
  274. IN RPC_CHAR * NetworkAddress,
  275. IN RPC_CHAR * * pEndpointString,
  276. IN unsigned int PendingQueueSize,
  277. IN void * SecurityDescriptor,
  278. IN unsigned long EndpointFlags,
  279. IN unsigned long NICFlags,
  280. OUT NETWORK_ADDRESS_VECTOR * * ppNetworkAddressVector
  281. )
  282. {
  283. RPC_STATUS Status;
  284. Status = Endpoint.TransportInterface->Listen(
  285. Endpoint.TransportEndpoint,
  286. NetworkAddress,
  287. pEndpointString,
  288. SecurityDescriptor,
  289. EndpointFlags,
  290. NICFlags,
  291. ppNetworkAddressVector
  292. );
  293. if (!Status)
  294. {
  295. Status = Endpoint.TransportInterface->QueryEndpointStats(
  296. &Endpoint.TransportEndpoint,
  297. &Endpoint.Stats
  298. );
  299. }
  300. Endpoint.Flags = EndpointFlags;
  301. return Status;
  302. }
  303. #ifndef NO_PLUG_AND_PLAY
  304. void
  305. DG_ADDRESS::PnpNotify (
  306. )
  307. {
  308. Endpoint.TransportInterface->PnpNotify();
  309. }
  310. #endif
  311. RPC_STATUS
  312. DG_ADDRESS::ServerStartingToListen (
  313. IN unsigned int MinThreads,
  314. IN unsigned int MaxCalls
  315. )
  316. /*++
  317. Routine Description:
  318. The runtime calls this fn to ensure a thread is listening on the address's
  319. endpoint. Currently, it may be called from RpcServerUse*Protseq*() or
  320. from RpcServerRegisterIfEx().
  321. Arguments:
  322. MinimumCallThreads - Supplies a number indicating the minimum number
  323. of call threads that should be created for this address. This is
  324. a hint, and datagram ignores it.
  325. MaximumConcurrentCalls - Supplies the maximum number of concurrent
  326. calls that this server will support. RPC_INTERFACE::DispatchToStub
  327. limits the number of threads dispatched to a stub; the argument
  328. here is just a hint for the transport.
  329. Return Value:
  330. RPC_S_OK if everything went ok.
  331. RPC_S_OUT_OF_THREADS if we needed another thread and couldn't create one
  332. --*/
  333. {
  334. MaximumConcurrentCalls = MaxCalls;
  335. return CheckThreadPool();
  336. }
  337. RPC_STATUS
  338. DG_ADDRESS::CompleteListen(
  339. )
  340. {
  341. Endpoint.TransportInterface->CompleteListen(Endpoint.TransportEndpoint);
  342. return 0;
  343. }
  344. RPC_STATUS
  345. DG_ADDRESS::CheckThreadPool(
  346. )
  347. {
  348. return TransInfo->CreateThread();
  349. }
  350. RPC_STATUS RPC_ENTRY
  351. I_RpcLaunchDatagramReceiveThread(
  352. void * pVoid
  353. )
  354. {
  355. /*++
  356. Routine Description:
  357. If all of the following are true:
  358. - the transport is part of our thread-sharing scheme
  359. - this address's endpoint is being monitored by the shared thread
  360. (hence no RPC thread is receiving on the endpoint)
  361. - the shared thread detects data on this address's endpoint
  362. then the shared thread will call this (exported) function to create
  363. a thread to handle the incoming packet.
  364. Arguments:
  365. pVoid - the DG_ADDRESS of the endpoint with data
  366. Return Value:
  367. result from CreateThread()
  368. --*/
  369. PDG_ADDRESS pAddress = (PDG_ADDRESS) pVoid;
  370. return pAddress->CheckThreadPool();
  371. }
  372. void
  373. DG_ADDRESS::ServerStoppedListening (
  374. )
  375. /*++
  376. Routine Description:
  377. The runtime calls this fn to inform the address that the server is not
  378. listening any more. Since auto-listen interfaces may still be present,
  379. this doesn't mean much anymore.
  380. Arguments:
  381. <None>
  382. Return Value:
  383. <None>
  384. --*/
  385. {
  386. }
  387. long
  388. DG_ADDRESS::InqNumberOfActiveCalls (
  389. )
  390. {
  391. return ActiveCallCount;
  392. }
  393. BOOL
  394. DG_ADDRESS::ForwardPacketIfNecessary(
  395. IN PDG_PACKET Packet,
  396. IN DG_TRANSPORT_ADDRESS RemoteAddress
  397. )
  398. /*++
  399. Routine Description:
  400. (courtesy of Connie)
  401. The runtime has determined that it is dedicated to the
  402. Epmapper and that pkts may arrive that are really
  403. destined for an endpoint other than that of the epmapper
  404. (ie: this is the beginning of dynamic endpoint resolution
  405. by the forwarding mechanism).
  406. The runtime has just received a packet and has called
  407. this routine to determine if (a) the packet is destined
  408. for the epmapper (in which case it returns indicating that
  409. the packet should be processed as is) OR
  410. (b) the packet is destined for another local server (in
  411. which case it forwarded to its intented destination) OR
  412. (c) is in error (in which case returns indicating an error).
  413. It searches for the i/f. If not found it calls the
  414. epmapper get forward function to determine the real destination
  415. endpoint for this i/f. If the epmapper recognizes the i/f,
  416. it calls ForwardPacket to forward the packet.
  417. Return Value:
  418. TRUE if the packet needed to be forwarded
  419. FALSE if it should be handled locally
  420. --*/
  421. {
  422. RPC_STATUS Status;
  423. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  424. RPC_INTERFACE * pRpcInterface;
  425. RPC_SYNTAX_IDENTIFIER RpcIfSyntaxIdentifier;
  426. char * EndpointString = 0;
  427. //
  428. // Build an interface syntax identifier from the packet.
  429. //
  430. RpcpMemoryCopy(
  431. &RpcIfSyntaxIdentifier.SyntaxGUID,
  432. &pHeader->InterfaceId,
  433. sizeof(RPC_UUID)
  434. );
  435. RpcIfSyntaxIdentifier.SyntaxVersion.MajorVersion =
  436. pHeader->InterfaceVersion.MajorVersion;
  437. RpcIfSyntaxIdentifier.SyntaxVersion.MinorVersion =
  438. pHeader->InterfaceVersion.MinorVersion;
  439. //
  440. // Try to find the appropriate interface to dispatch to.
  441. //
  442. pRpcInterface = Server->FindInterface(&RpcIfSyntaxIdentifier);
  443. //
  444. // If the Interface is Mgmt If .. EpMapper has registered it and will be found
  445. // The criteria then is .. If Packet has a Non NULL Obj Id forward .. else process
  446. //
  447. if (pRpcInterface &&
  448. 0 == RpcpMemoryCompare(&pHeader->ObjectId, &NullUuid, sizeof(UUID)) )
  449. {
  450. //Interface found, just process as normal
  451. return FALSE;
  452. }
  453. else
  454. {
  455. //Interface wasn't found. Let's ask endpoint mapper to resolve it
  456. //for us.
  457. unsigned char * AnsiProtseq;
  458. // Must convert the protocol sequence into an ansi string.
  459. unsigned Length = 1 + RpcpStringLength(InqRpcProtocolSequence());
  460. AnsiProtseq = (unsigned char *) _alloca(Length);
  461. if (!AnsiProtseq)
  462. {
  463. return TRUE;
  464. }
  465. NTSTATUS NtStatus;
  466. NtStatus = RtlUnicodeToMultiByteN((char *) AnsiProtseq,
  467. Length,
  468. NULL,
  469. InqRpcProtocolSequence(),
  470. Length * sizeof(RPC_CHAR)
  471. );
  472. ASSERT(NT_SUCCESS(NtStatus));
  473. RpcTryExcept
  474. {
  475. // Call the epmapper get forward function. It returns the
  476. // endpoint of the server this packet is really destined for.
  477. Status = (*Server->pRpcForwardFunction)(
  478. (UUID *) &pHeader->InterfaceId,
  479. (RPC_VERSION *) &pHeader->InterfaceVersion,
  480. (UUID *) &pHeader->ObjectId,
  481. AnsiProtseq,
  482. (void * *) &EndpointString
  483. );
  484. }
  485. RpcExcept( I_RpcExceptionFilter(RpcExceptionCode()) )
  486. {
  487. Status = RpcExceptionCode();
  488. }
  489. RpcEndExcept
  490. if (Status != RPC_S_OK)
  491. {
  492. if (!(pHeader->PacketFlags & DG_PF_BROADCAST) &&
  493. !(pHeader->PacketFlags & DG_PF_MAYBE))
  494. {
  495. // couldn't find the interface, or some other error occurred.
  496. // The X/Open version of the AES, available in 1997, says we should
  497. // set the boot time to zero in this situation.
  498. //
  499. InitErrorPacket(Packet, DG_REJECT, RPC_S_UNKNOWN_IF );
  500. Packet->Header.ServerBootTime = 0;
  501. SendPacketBack (&Packet->Header, Packet->GetPacketBodyLen(), RemoteAddress);
  502. }
  503. return TRUE;
  504. }
  505. if (EndpointString)
  506. {
  507. ForwardPacket(Packet, RemoteAddress, EndpointString);
  508. I_RpcFree(EndpointString);
  509. }
  510. }
  511. return TRUE;
  512. }
  513. RPC_STATUS
  514. DG_ADDRESS::ForwardPacket(
  515. IN PDG_PACKET Packet,
  516. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  517. IN char * ServerEndpointString
  518. )
  519. /*++
  520. Routine Description:
  521. This method will be called to forward a packet that was just
  522. received to the intended destination endpoint.
  523. The runtime has received a packet for an unknkown i/f.
  524. It has passed this packet to the epmapper who has found the
  525. correct destination enpoint in its table and has instructed the
  526. runtime to forward the packet to this Endpoint. This procedure
  527. will do just that.
  528. --*/
  529. {
  530. //
  531. // Avoid a loop if the server gets confused.
  532. //
  533. if (Packet->Header.PacketType != DG_REQUEST &&
  534. Packet->Header.PacketType != DG_PING &&
  535. Packet->Header.PacketType != DG_QUIT)
  536. {
  537. #ifdef DEBUGRPC
  538. DbgPrint("DG RPC: not forwarding packet of type %u\n", Packet->Header.PacketType);
  539. #endif
  540. return RPC_S_OK;
  541. }
  542. //
  543. // Use the same value for 32 and 64 bit.
  544. //
  545. #define REMOTE_ADDRESS_PAD 8
  546. unsigned Length;
  547. REMOTE_ADDRESS_INFO *pRemoteAddressInfo;
  548. unsigned EndpointInfoStart = Align( Packet->DataLength, REMOTE_ADDRESS_PAD );
  549. unsigned EndpointInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  550. + Endpoint.TransportInterface->AddressSize;
  551. //
  552. // We have not yet subtracted the header from the packet's DataLength.
  553. //
  554. Length = EndpointInfoStart + EndpointInfoLength;
  555. //
  556. // If the packet header was byte-swapped, restore it to its original format.
  557. //
  558. ByteSwapPacketHeaderIfNecessary(Packet);
  559. // BE CAREFUL READING OR WRITING THE PACKET HEADER AFTER IT IS BYTE-SWAPPED.
  560. //
  561. // If the original packet is short enough, we can append out data
  562. // to the end; otherwise, we need to send one packet with the original
  563. // data and another with the client address info.
  564. //
  565. if (Length <= Endpoint.Stats.PreferredPduSize)
  566. {
  567. //
  568. // Mark it "forwarded with appended endpoint info"
  569. //
  570. Packet->Header.PacketFlags |= DG_PF_FORWARDED;
  571. Packet->Header.PacketFlags2 &= ~DG_PF2_FORWARDED_2;
  572. pRemoteAddressInfo = (REMOTE_ADDRESS_INFO *) ( Packet->Header.Data
  573. + EndpointInfoStart
  574. - sizeof(NCA_PACKET_HEADER) );
  575. pRemoteAddressInfo->SecurityInfoPadLength = EndpointInfoStart - Packet->DataLength;
  576. }
  577. else
  578. {
  579. Length = EndpointInfoLength + sizeof(NCA_PACKET_HEADER);
  580. //
  581. // Mark it "forwarded without appended endpoint info"
  582. //
  583. Packet->Header.PacketFlags &= ~DG_PF_FORWARDED;
  584. Packet->Header.PacketFlags2 |= DG_PF2_FORWARDED_2;
  585. Endpoint.TransportInterface->ForwardPacket( Endpoint.TransportEndpoint,
  586. 0,
  587. 0,
  588. &Packet->Header,
  589. Packet->DataLength,
  590. 0,
  591. 0,
  592. ServerEndpointString
  593. );
  594. //
  595. // Mark it "endpoint info only".
  596. //
  597. Packet->Header.PacketFlags |= DG_PF_FORWARDED;
  598. Packet->Header.PacketFlags2 |= DG_PF2_FORWARDED_2;
  599. Packet->SetPacketBodyLen(EndpointInfoLength);
  600. Packet->Header.AuthProto = 0;
  601. pRemoteAddressInfo = (REMOTE_ADDRESS_INFO *) Packet->Header.Data;
  602. pRemoteAddressInfo->SecurityInfoPadLength = 0;
  603. }
  604. //
  605. // Add endpoint info and send it.
  606. //
  607. pRemoteAddressInfo->RemoteInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  608. + Endpoint.TransportInterface->AddressSize;
  609. RpcpMemoryCopy(
  610. pRemoteAddressInfo->Address,
  611. RemoteAddress,
  612. Endpoint.TransportInterface->AddressSize
  613. );
  614. Endpoint.TransportInterface->ForwardPacket( Endpoint.TransportEndpoint,
  615. 0,
  616. 0,
  617. &Packet->Header,
  618. Length,
  619. 0,
  620. 0,
  621. ServerEndpointString
  622. );
  623. return RPC_S_OK;
  624. }
  625. BOOL
  626. DG_ADDRESS::CaptureClientAddress(
  627. IN PDG_PACKET Packet,
  628. OUT DG_TRANSPORT_ADDRESS RemoteAddress
  629. )
  630. /*++
  631. Routine Description:
  632. This method is called when a packet with DG_PF_FORWARDED arrives.
  633. This means the endpoint mapper sent it and it includes a
  634. REMOTE_ADDRESS_INFO structure. The fn will remove it and store the
  635. client's remote address in RemoteAddress.
  636. If the packet was forwarded and not fragmented, we restore it to its
  637. original state and zap the DG_PF_FORWARDED bit.
  638. Return Value:
  639. TRUE if the packet was valid
  640. FALSE if it appeared malformed
  641. --*/
  642. {
  643. ASSERT( Packet->DataLength >= Packet->GetPacketBodyLen() );
  644. //
  645. // Watch for packets that might crash us.
  646. //
  647. unsigned AddressInfoLength = sizeof(REMOTE_ADDRESS_INFO)
  648. + Endpoint.TransportInterface->AddressSize;
  649. if (Packet->DataLength < Packet->GetPacketBodyLen() ||
  650. Packet->DataLength - Packet->GetPacketBodyLen() < AddressInfoLength)
  651. {
  652. #ifdef DEBUGRPC
  653. DbgPrint("RPC DG: forwarded packet data is impossibly short\n");
  654. #endif
  655. return FALSE;
  656. }
  657. Packet->DataLength -= AddressInfoLength;
  658. //
  659. // If this is a nonfragmented packet, the endpoint info is beyond
  660. // the stub data and security trailer.
  661. //
  662. REMOTE_ADDRESS_INFO * pAddressInfo;
  663. if (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2)
  664. {
  665. pAddressInfo = (REMOTE_ADDRESS_INFO *) Packet->Header.Data;
  666. }
  667. else
  668. {
  669. // After fixing up the length, we can treat this like a packet
  670. // sent directly from the client.
  671. //
  672. Packet->Header.PacketFlags &= ~DG_PF_FORWARDED;
  673. pAddressInfo = (REMOTE_ADDRESS_INFO *) ( Packet->Header.Data
  674. + Packet->DataLength );
  675. if (pAddressInfo->RemoteInfoLength != AddressInfoLength)
  676. {
  677. #ifdef DEBUGRPC
  678. DbgPrint("RPC DG: forwarded packet contains wrong address structure length\n");
  679. #endif
  680. return FALSE;
  681. }
  682. if (pAddressInfo != AlignPtr( pAddressInfo, REMOTE_ADDRESS_PAD ))
  683. {
  684. #ifdef DEBUGRPC
  685. DbgPrint("RPC DG: forwarded packet contains a misaligned address structure\n");
  686. #endif
  687. return FALSE;
  688. }
  689. }
  690. if (pAddressInfo->SecurityInfoPadLength > REMOTE_ADDRESS_PAD ||
  691. Packet->DataLength < pAddressInfo->SecurityInfoPadLength)
  692. {
  693. #ifdef DEBUGRPC
  694. DbgPrint("RPC DG: forwarded packet's address struct has invalid pad length\n");
  695. #endif
  696. return FALSE;
  697. }
  698. Packet->DataLength -= pAddressInfo->SecurityInfoPadLength;
  699. //
  700. // Record the client's true endpoint.
  701. //
  702. RpcpMemoryCopy(
  703. RemoteAddress,
  704. pAddressInfo->Address,
  705. Endpoint.TransportInterface->AddressSize
  706. );
  707. return TRUE;
  708. }
  709. #pragma optimize("t", on)
  710. void
  711. ProcessDgServerPacket(
  712. IN DWORD Status,
  713. IN DG_TRANSPORT_ENDPOINT LocalEndpoint,
  714. IN void * PacketHeader,
  715. IN unsigned long PacketLength,
  716. IN DatagramTransportPair *AddressPair
  717. )
  718. {
  719. PDG_PACKET Packet = DG_PACKET::FromPacketHeader(PacketHeader);
  720. Packet->DataLength = PacketLength;
  721. #ifdef INTRODUCE_ERRORS
  722. if (::ServerDropRate)
  723. {
  724. if ((GetRandomCounter() % 100) < ::ServerDropRate)
  725. {
  726. unsigned Frag = (Packet->Header.PacketType << 16) | Packet->Header.GetFragmentNumber();
  727. unsigned Uuid = *(unsigned *) &Packet->Header.ActivityId;
  728. unsigned Type = Packet->Header.PacketType;
  729. LogError(SU_PACKET, EV_DROP, (void *) Uuid, (void *) Type, Frag);
  730. Packet->Free();
  731. return;
  732. }
  733. }
  734. if (::ServerDelayRate)
  735. {
  736. if ((GetRandomCounter() % 100) < ::ServerDelayRate)
  737. {
  738. unsigned Frag = (Packet->Header.PacketType << 16) | Packet->Header.GetFragmentNumber();
  739. unsigned Uuid = *(unsigned *) &Packet->Header.ActivityId;
  740. unsigned Type = Packet->Header.PacketType;
  741. LogError(SU_PACKET, EV_DELAY, (void *) Uuid, (void *) Type, Frag);
  742. Sleep(::ServerDelayTime);
  743. }
  744. }
  745. #endif
  746. if (Status == RPC_P_OVERSIZE_PACKET)
  747. {
  748. #ifdef DEBUGRPC
  749. PrintToDebugger("RPC DG: async packet is too large\n");
  750. #endif
  751. Packet->Flags |= DG_PF_PARTIAL;
  752. Status = RPC_S_OK;
  753. }
  754. if (Status != RPC_S_OK)
  755. {
  756. LogError(SU_PACKET, EV_STATUS, Packet, 0, Status);
  757. #ifdef DEBUGRPC
  758. PrintToDebugger("RPC DG: async receive completed with status 0x%lx\n", Status);
  759. #endif
  760. Packet->Free();
  761. return;
  762. }
  763. DG_ADDRESS * Address = DG_ADDRESS::FromEndpoint(LocalEndpoint);
  764. Address->DispatchPacket(Packet, AddressPair);
  765. }
  766. void
  767. DG_ADDRESS::DispatchPacket(
  768. DG_PACKET * Packet,
  769. IN DatagramTransportPair *AddressPair
  770. )
  771. {
  772. RPC_INTERFACE * pRpcInterface;
  773. RPC_SYNTAX_IDENTIFIER RpcIfSyntaxIdentifier;
  774. //
  775. // Mask off bits not used by X/Open or by us.
  776. // Notice that the current arrangement strips the extra bits before
  777. // forwarding, so if these bits become important the code will have to
  778. // be rearranged.
  779. //
  780. Packet->Header.RpcVersion &= 0x0F;
  781. Packet->Header.PacketType &= 0x1F;
  782. Packet->Header.PacketFlags &= 0x7f;
  783. Packet->Header.PacketFlags2 &= 0x87;
  784. //
  785. // Filter out packets that clients shouldn't send.
  786. //
  787. switch (Packet->Header.PacketType)
  788. {
  789. case DG_REQUEST:
  790. case DG_PING:
  791. case DG_FACK:
  792. case DG_QUIT:
  793. case DG_ACK:
  794. {
  795. break;
  796. }
  797. default:
  798. {
  799. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  800. FreePacket(Packet);
  801. return;
  802. }
  803. } // switch (PacketType)
  804. if (Packet->Header.RpcVersion != DG_RPC_PROTOCOL_VERSION)
  805. {
  806. #ifdef DEBUGRPC
  807. DbgPrint("dg rpc: packet %x has version %u\n", Packet, Packet->Header.RpcVersion);
  808. DbgPrint(" length %u\n", Packet->DataLength);
  809. if (Packet->DataLength > 80)
  810. {
  811. Packet->DataLength = 80;
  812. }
  813. DumpBuffer(&Packet->Header, Packet->DataLength);
  814. #endif
  815. SendRejectPacket(Packet, NCA_STATUS_VERSION_MISMATCH, AddressPair->RemoteAddress);
  816. FreePacket(Packet);
  817. return;
  818. }
  819. ByteSwapPacketHeaderIfNecessary(Packet);
  820. //
  821. // Make sure the header is intact.
  822. // Allow a packet with truncated stub data to pass; the SCALL
  823. // will send a FACK-with-body to tell the client our max packet size.
  824. //
  825. if (Packet->DataLength < sizeof(NCA_PACKET_HEADER))
  826. {
  827. #ifdef DEBUGRPC
  828. DbgPrint("dg rpc: packet %x has invalid length\n", Packet);
  829. DbgPrint(" length %u\n", Packet->DataLength);
  830. if (Packet->DataLength > 80)
  831. {
  832. Packet->DataLength = 80;
  833. }
  834. DumpBuffer(&Packet->Header, Packet->DataLength);
  835. RpcpBreakPoint();
  836. #endif
  837. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  838. FreePacket(Packet);
  839. return;
  840. }
  841. //
  842. // If we are the endpoint mapper, forward packet if necessary.
  843. //
  844. if (GlobalRpcServer->pRpcForwardFunction)
  845. {
  846. if (TRUE == ForwardPacketIfNecessary(Packet, AddressPair->RemoteAddress))
  847. {
  848. LogEvent(SU_ADDRESS, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  849. FreePacket(Packet);
  850. return;
  851. }
  852. }
  853. //
  854. // Exclude RPC header from DataLength.
  855. //
  856. Packet->DataLength -= sizeof(NCA_PACKET_HEADER);
  857. //
  858. // If the packet includes a client address trailer from the endpoint mapper,
  859. // remove it and stick the client address in <RemoteAddres>.
  860. //
  861. if (Packet->Header.PacketFlags & DG_PF_FORWARDED)
  862. {
  863. if (FALSE == CaptureClientAddress(Packet, AddressPair->RemoteAddress))
  864. {
  865. LogEvent(SU_ADDRESS, EV_PKT_IN, this, (void *) 4, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  866. FreePacket(Packet);
  867. return;
  868. }
  869. }
  870. // Reject pkt if boot time in pkt does not match
  871. // the server's boot time.
  872. //
  873. if (Packet->Header.ServerBootTime != ProcessStartTime &&
  874. Packet->Header.ServerBootTime != 0)
  875. {
  876. if (!(Packet->Header.PacketFlags & DG_PF_MAYBE))
  877. {
  878. SendRejectPacket(Packet, NCA_STATUS_WRONG_BOOT_TIME, AddressPair->RemoteAddress);
  879. }
  880. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 5, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  881. FreePacket(Packet);
  882. return;
  883. }
  884. //
  885. // sometimes OSF packets say they include security info
  886. // when they don't.
  887. //
  888. DeleteSpuriousAuthProto(Packet);
  889. //
  890. // Find or create a connection and then give it the packet.
  891. //
  892. DG_SCONNECTION * Connection = ServerConnections->FindOrCreate(this, Packet);
  893. if (!Connection)
  894. {
  895. if (Packet->Header.PacketFlags & (DG_PF_BROADCAST | DG_PF_MAYBE))
  896. {
  897. //
  898. // not much point sending an error packet in this case
  899. //
  900. }
  901. else
  902. {
  903. if (Packet->Header.PacketType == DG_REQUEST)
  904. {
  905. SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  906. }
  907. else
  908. {
  909. CleanupPacket(&Packet->Header);
  910. Packet->Header.PacketType = DG_NOCALL;
  911. Packet->SetPacketBodyLen(0);
  912. Packet->SetFragmentNumber(0xffff);
  913. SetSerialNumber( &Packet->Header, 0);
  914. SendPacketBack( &Packet->Header, 0, AddressPair->RemoteAddress);
  915. }
  916. }
  917. LogError(SU_ADDRESS, EV_PKT_IN, this, (void *) 6, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  918. FreePacket(Packet);
  919. return;
  920. }
  921. Connection->DispatchPacket(Packet, AddressPair);
  922. ServerConnections->Prune();
  923. }
  924. #pragma optimize("", on)
  925. PDG_SCONNECTION
  926. DG_ADDRESS::AllocateConnection(
  927. )
  928. /*++
  929. Routine Description:
  930. Allocates a new DG_SCONNECTION from the cache or from the heap.
  931. Arguments:
  932. none
  933. Return Value:
  934. the call
  935. --*/
  936. {
  937. PDG_SCONNECTION Connection;
  938. AddressMutex.Request();
  939. UUID_HASH_TABLE_NODE * Node = CachedConnections;
  940. if (Node)
  941. {
  942. CachedConnections = Node->pNext;
  943. AddressMutex.Clear();
  944. Connection = DG_SCONNECTION::FromHashNode(Node);
  945. }
  946. else
  947. {
  948. AddressMutex.Clear();
  949. RPC_STATUS Status = RPC_S_OK;
  950. Connection = new DG_SCONNECTION(this, &Status);
  951. if (!Connection)
  952. {
  953. return 0;
  954. }
  955. if (Status != RPC_S_OK)
  956. {
  957. delete Connection;
  958. return 0;
  959. }
  960. }
  961. LogEvent(SU_SCONN, EV_START, Connection, this);
  962. return Connection;
  963. }
  964. void
  965. DG_ADDRESS::FreeConnection(
  966. PDG_SCONNECTION Connection
  967. )
  968. /*++
  969. Routine Description:
  970. Returns an unused DG_SCONNECTION to the cache or the heap.
  971. Arguments:
  972. the connection
  973. Return Value:
  974. none
  975. --*/
  976. {
  977. AddressMutex.Request();
  978. if (CachedConnections)
  979. {
  980. AddressMutex.Clear();
  981. delete Connection;
  982. return;
  983. }
  984. else
  985. {
  986. CachedConnections = &Connection->ActivityNode;
  987. Connection->ActivityNode.pNext = 0;
  988. AddressMutex.Clear();
  989. return;
  990. }
  991. AddressMutex.Request();
  992. Connection->ActivityNode.pNext = CachedConnections;
  993. CachedConnections = &Connection->ActivityNode;
  994. AddressMutex.Clear();
  995. }
  996. DG_SCALL::DG_SCALL(
  997. DG_ADDRESS * Address,
  998. RPC_STATUS * pStatus
  999. ) :
  1000. DG_PACKET_ENGINE(DG_RESPONSE, Address->AllocatePacket(), pStatus),
  1001. Connection (0),
  1002. PipeWaitEvent (0),
  1003. PipeWaitType (PWT_NONE),
  1004. PipeThreadId (0),
  1005. State (CallInit),
  1006. pCachedSid (0),
  1007. pwsCachedUserName(0),
  1008. dwCachedUserNameSize(0)
  1009. /*++
  1010. Routine Description:
  1011. This is the constructor for the DG_SCALL class. This class represents a
  1012. call in progress on a server.
  1013. Arguments:
  1014. pAddress - The address this call is taking place on.
  1015. pStatus - Where to put a construction error code.
  1016. --*/
  1017. {
  1018. #ifdef MONITOR_SERVER_PACKET_COUNT
  1019. OutstandingPacketCount = 0;
  1020. #endif
  1021. DispatchBuffer = 0;
  1022. LogEvent(SU_SCALL, EV_CREATE, this, Address);
  1023. ObjectType = DG_SCALL_TYPE;
  1024. InterlockedIncrement(&ServerCallCount);
  1025. if (*pStatus)
  1026. {
  1027. return;
  1028. }
  1029. SourceEndpoint = &Address->Endpoint;
  1030. }
  1031. BOOL
  1032. DG_SCALL::Cleanup()
  1033. {
  1034. if (ReferenceCount)
  1035. {
  1036. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, ReferenceCount);
  1037. ASSERT( State != CallComplete && State != CallInit );
  1038. return FALSE;
  1039. }
  1040. if (pAsync)
  1041. {
  1042. DoPostDispatchProcessing();
  1043. }
  1044. switch (State)
  1045. {
  1046. case CallBeforeDispatch:
  1047. case CallDispatched:
  1048. CleanupReceiveWindow();
  1049. case CallSendingResponse:
  1050. RPC_MESSAGE Message;
  1051. CleanupSendWindow();
  1052. Message.Buffer = DispatchBuffer;
  1053. Message.ReservedForRuntime = 0;
  1054. FreeBuffer(&Message);
  1055. ASSERT( !DispatchBuffer );
  1056. if (Privileges)
  1057. {
  1058. ASSERT( Connection->ActiveSecurityContext );
  1059. Connection->ActiveSecurityContext->DeletePac( Privileges );
  1060. Privileges = 0;
  1061. }
  1062. if (Interface->IsAutoListenInterface())
  1063. {
  1064. Connection->pAddress->EndAutoListenCall();
  1065. Interface->EndAutoListenCall();
  1066. }
  1067. Connection->pAddress->DecrementActiveCallCount();
  1068. if (pAsync)
  1069. {
  1070. Interface->EndCall( FALSE, TRUE );
  1071. }
  1072. Cancelled = FALSE;
  1073. ASSERT( PipeWaitType == PWT_NONE );
  1074. PipeThreadId = 0;
  1075. case CallInit:
  1076. if ( LastReceiveBuffer )
  1077. {
  1078. RPC_MESSAGE Message;
  1079. Message.Buffer = LastReceiveBuffer;
  1080. Message.ReservedForRuntime = 0;
  1081. FreeBuffer(&Message);
  1082. }
  1083. #ifdef MONITOR_SERVER_PACKET_COUNT
  1084. ASSERT( OutstandingPacketCount == 0 );
  1085. #endif
  1086. Connection->FreeCall(this);
  1087. SetState(CallComplete);
  1088. break;
  1089. case CallComplete:
  1090. {
  1091. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, CallComplete);
  1092. break;
  1093. }
  1094. default:
  1095. {
  1096. LogEvent(SU_SCALL, EV_CLEANUP, this, 0, State);
  1097. #ifdef DEBUGRPC
  1098. DbgPrint("RPC: process %x bad call state %x in DG_SCALL::Cleanup\n",
  1099. GetCurrentProcessId(), State);
  1100. #endif
  1101. }
  1102. }
  1103. return TRUE;
  1104. }
  1105. inline BOOL
  1106. DG_SCALL_TABLE::Add(
  1107. PDG_SCALL Call,
  1108. unsigned long Sequence
  1109. )
  1110. {
  1111. //
  1112. // Add the call to the end of the active call list.
  1113. //
  1114. Call->Next = 0;
  1115. Call->Previous = ActiveCallTail;
  1116. if (ActiveCallHead)
  1117. {
  1118. ASSERT( Call->GetSequenceNumber() > ActiveCallTail->GetSequenceNumber() );
  1119. ActiveCallTail->Next = Call;
  1120. }
  1121. else
  1122. {
  1123. ActiveCallHead = Call;
  1124. }
  1125. ActiveCallTail = Call;
  1126. return TRUE;
  1127. }
  1128. inline void
  1129. DG_SCALL_TABLE::Remove(
  1130. PDG_SCALL Call
  1131. )
  1132. {
  1133. LogEvent(SU_SCALL, EV_REMOVED, Call, this);
  1134. if (Call->Previous)
  1135. {
  1136. ASSERT( ActiveCallHead != Call );
  1137. Call->Previous->Next = Call->Next;
  1138. }
  1139. else
  1140. {
  1141. ASSERT( ActiveCallHead == Call );
  1142. ActiveCallHead = Call->Next;
  1143. }
  1144. if (Call->Next)
  1145. {
  1146. ASSERT( ActiveCallTail != Call );
  1147. Call->Next->Previous = Call->Previous;
  1148. }
  1149. else
  1150. {
  1151. ASSERT( ActiveCallTail == Call );
  1152. ActiveCallTail = Call->Previous;
  1153. }
  1154. Call->Next = 0;
  1155. Call->Previous = 0;
  1156. }
  1157. inline PDG_SCALL
  1158. DG_SCALL_TABLE::Successor(
  1159. PDG_SCALL Call
  1160. )
  1161. {
  1162. // ASSERT( Call == Find(Call->SequenceNumber) );
  1163. return Call->Next;
  1164. }
  1165. inline PDG_SCALL
  1166. DG_SCALL_TABLE::Find(
  1167. unsigned long Sequence
  1168. )
  1169. {
  1170. PDG_SCALL Call;
  1171. for (Call = ActiveCallHead; Call; Call = Call->Next)
  1172. {
  1173. if (Call->GetSequenceNumber() == Sequence)
  1174. {
  1175. return Call;
  1176. }
  1177. if (Call->GetSequenceNumber() > Sequence)
  1178. {
  1179. return NULL;
  1180. }
  1181. }
  1182. return NULL;
  1183. }
  1184. inline PDG_SCALL
  1185. DG_SCALL_TABLE::Predecessor(
  1186. unsigned long Sequence
  1187. )
  1188. {
  1189. PDG_SCALL Call, Previous = 0;
  1190. for (Call = ActiveCallHead; Call; Call = Call->Next)
  1191. {
  1192. if (Call->GetSequenceNumber() >= Sequence)
  1193. {
  1194. break;
  1195. }
  1196. Previous = Call;
  1197. }
  1198. return Previous;
  1199. }
  1200. inline void
  1201. DG_SCALL_TABLE::RemoveIdleCalls(
  1202. BOOL Aggressive,
  1203. RPC_INTERFACE * Interface
  1204. )
  1205. {
  1206. PDG_SCALL Call;
  1207. for (Call = ActiveCallHead; Call; )
  1208. {
  1209. ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) );
  1210. PDG_SCALL Next = Call->Next;
  1211. // If the call has in fact expired, it will be removed from this list
  1212. // and added to the connection's cached call list.
  1213. //
  1214. Call->HasExpired( Aggressive, Interface );
  1215. Call = Next;
  1216. }
  1217. }
  1218. DG_SCONNECTION::DG_SCONNECTION(
  1219. DG_ADDRESS * a_Address,
  1220. RPC_STATUS * pStatus
  1221. ) :
  1222. DG_COMMON_CONNECTION(a_Address->Endpoint.TransportInterface, pStatus),
  1223. pAddress (a_Address),
  1224. pAssocGroup (0),
  1225. CachedCalls (0),
  1226. LastInterface (0),
  1227. CurrentCall (0),
  1228. MaxKeySeq (0),
  1229. fFirstCall (0),
  1230. BlockIdleCallRemoval(0),
  1231. pMessageMutex (0)
  1232. {
  1233. LogEvent(SU_SCONN, EV_CREATE, this, a_Address);
  1234. ObjectType = DG_SCONNECTION_TYPE;
  1235. fFirstCall = 0;
  1236. InterlockedIncrement(&ServerConnectionCount);
  1237. }
  1238. DG_SCONNECTION::~DG_SCONNECTION()
  1239. {
  1240. InterlockedDecrement(&ServerConnectionCount);
  1241. delete CachedCalls;
  1242. if (pMessageMutex)
  1243. {
  1244. delete pMessageMutex;
  1245. }
  1246. }
  1247. void
  1248. DG_SCONNECTION::Activate(
  1249. PNCA_PACKET_HEADER pHeader,
  1250. unsigned short NewHash
  1251. )
  1252. {
  1253. AuthInfo.AuthenticationService = pHeader->AuthProto;
  1254. if (AuthInfo.AuthenticationService)
  1255. {
  1256. DG_SECURITY_TRAILER * pVerifier = (DG_SECURITY_TRAILER *)
  1257. (pHeader->Data + pHeader->GetPacketBodyLen());
  1258. AuthInfo.AuthenticationLevel = pVerifier->protection_level;
  1259. AuthInfo.AuthorizationService = 0;
  1260. AuthInfo.ServerPrincipalName = 0;
  1261. AuthInfo.PacHandle = 0;
  1262. }
  1263. else
  1264. {
  1265. AuthInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
  1266. AuthInfo.AuthorizationService = RPC_C_AUTHZ_NONE;
  1267. AuthInfo.ServerPrincipalName = 0;
  1268. AuthInfo.PacHandle = 0;
  1269. }
  1270. ActivityNode.Initialize(&pHeader->ActivityId);
  1271. ActivityHint = NewHash;
  1272. LogEvent( SU_SCONN, EV_START, this, IntToPtr(pHeader->ActivityId.Data1), ActivityHint );
  1273. PDG_SCALL Call;
  1274. for (Call = CachedCalls; Call; Call = Call->Next)
  1275. {
  1276. Call->BindToConnection(this);
  1277. }
  1278. Callback.State = NoCallbackAttempted;
  1279. MaxKeySeq = 0;
  1280. LowestActiveSequence = 0;
  1281. LowestUnusedSequence = 0;
  1282. TimeStamp = GetTickCount();
  1283. }
  1284. void
  1285. DG_SCONNECTION::Deactivate(
  1286. )
  1287. {
  1288. LogEvent(SU_SCONN, EV_STOP, this, pAddress);
  1289. ASSERT( !CurrentCall );
  1290. while (CachedCalls && CachedCalls->Next)
  1291. {
  1292. PDG_SCALL Call = CachedCalls;
  1293. CachedCalls = Call->Next;
  1294. delete Call;
  1295. }
  1296. for (unsigned u = 0; u <= MaxKeySeq; ++u)
  1297. {
  1298. delete SecurityContextDict.Delete(u);
  1299. }
  1300. //
  1301. // Delete all previous interface callback results.
  1302. //
  1303. int cursor;
  1304. InterfaceCallbackResults.Reset(cursor);
  1305. while (InterfaceCallbackResults.Next(cursor, TRUE))
  1306. ;
  1307. ActiveSecurityContext = 0;
  1308. if (pAssocGroup)
  1309. {
  1310. AssociationGroups->DecrementRefCount(pAssocGroup);
  1311. pAssocGroup = 0;
  1312. }
  1313. pAddress->FreeConnection(this);
  1314. }
  1315. PDG_SCALL
  1316. DG_SCONNECTION::AllocateCall()
  1317. {
  1318. PDG_SCALL Call = 0;
  1319. if (CachedCalls)
  1320. {
  1321. Call = CachedCalls;
  1322. CachedCalls = CachedCalls->Next;
  1323. ASSERT( !Call->InvalidHandle(DG_SCALL_TYPE) );
  1324. ASSERT( !CachedCalls || !CachedCalls->InvalidHandle(DG_SCALL_TYPE) );
  1325. }
  1326. else
  1327. {
  1328. RPC_STATUS Status = RPC_S_OK;
  1329. Call = new (pAddress->Endpoint.TransportInterface) DG_SCALL(pAddress, &Status);
  1330. if (!Call)
  1331. {
  1332. return 0;
  1333. }
  1334. if (Status)
  1335. {
  1336. delete Call;
  1337. return 0;
  1338. }
  1339. Call->BindToConnection(this);
  1340. }
  1341. //
  1342. // Allow ACTIVE_CALL_TABLE::Remove to succeed even if the call is not in the table.
  1343. //
  1344. Call->Next = Call;
  1345. Call->Previous = Call;
  1346. IncrementRefCount();
  1347. return Call;
  1348. }
  1349. void
  1350. DG_SCONNECTION::FreeCall(
  1351. PDG_SCALL Call
  1352. )
  1353. {
  1354. DecrementRefCount();
  1355. if (CurrentCall == Call)
  1356. {
  1357. CurrentCall = ActiveCalls.Successor(Call);
  1358. }
  1359. if (Call->GetSequenceNumber() == LowestActiveSequence)
  1360. {
  1361. PDG_SCALL Successor = ActiveCalls.Successor(Call);
  1362. if (Successor)
  1363. {
  1364. LowestActiveSequence = Successor->GetSequenceNumber();
  1365. }
  1366. else
  1367. {
  1368. LowestActiveSequence = LowestUnusedSequence;
  1369. }
  1370. }
  1371. ActiveCalls.Remove(Call);
  1372. AddCallToCache(Call);
  1373. }
  1374. void
  1375. DG_SCALL::NewCall(
  1376. PDG_PACKET a_Packet,
  1377. DatagramTransportPair *AddressPair
  1378. )
  1379. {
  1380. ASSERT( State == CallInit || State == CallComplete );
  1381. ASSERT( DispatchBuffer == 0 );
  1382. SetState(CallInit);
  1383. SequenceNumber = a_Packet->Header.SequenceNumber;
  1384. pSavedPacket->Header.ObjectId = a_Packet->Header.ObjectId;
  1385. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  1386. pSavedPacket->Header.PacketFlags = 0;
  1387. BasePacketFlags = 0;
  1388. DG_PACKET_ENGINE::NewCall();
  1389. RpcpMemoryCopy(RemoteAddress, AddressPair->RemoteAddress, Connection->TransportInterface->AddressSize);
  1390. LocalAddress = *(DWORD *)AddressPair->LocalAddress;
  1391. if ((a_Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) &&
  1392. (a_Packet->Header.PacketFlags & DG_PF_FORWARDED) == 0)
  1393. {
  1394. KnowClientAddress = FALSE;
  1395. }
  1396. else
  1397. {
  1398. KnowClientAddress = TRUE;
  1399. }
  1400. CallWasForwarded = FALSE;
  1401. CallInProgress = FALSE;
  1402. Privileges = 0;
  1403. CancelEventId = 0;
  1404. pAsync = 0;
  1405. FinalSendBufferPresent = FALSE;
  1406. }
  1407. DG_SCALL::~DG_SCALL()
  1408. /*++
  1409. Routine Description:
  1410. Destructor for the DG_SCALL object.
  1411. Arguments:
  1412. <None>
  1413. Return Value:
  1414. <None>
  1415. --*/
  1416. {
  1417. #ifdef MONITOR_SERVER_PACKET_COUNT
  1418. ASSERT( OutstandingPacketCount == 0 );
  1419. #endif
  1420. InterlockedDecrement(&ServerCallCount);
  1421. delete PipeWaitEvent;
  1422. PipeWaitEvent = 0;
  1423. if (pCachedSid)
  1424. {
  1425. I_RpcFree(pCachedSid);
  1426. }
  1427. if (pwsCachedUserName)
  1428. {
  1429. I_RpcFree(pwsCachedUserName);
  1430. }
  1431. }
  1432. RPC_STATUS
  1433. DG_SCALL::NegotiateTransferSyntax (
  1434. IN OUT PRPC_MESSAGE Message
  1435. )
  1436. {
  1437. // this can happen in the callback case only.
  1438. // Datagrams don't really support multiple transfer
  1439. // syntaxes. Return whatever the stub wants, which is
  1440. // already recorded in the transfer syntax field
  1441. return RPC_S_OK;
  1442. }
  1443. RPC_STATUS
  1444. DG_SCALL::GetBuffer (
  1445. IN OUT PRPC_MESSAGE Message,
  1446. IN UUID *ObjectUuid
  1447. )
  1448. /*++
  1449. Routine Description:
  1450. This routine is called by the stub to allocate space. This space is to
  1451. be used for output arguments.
  1452. If these args fit into a single packet, then use the first packet
  1453. on the to-be-deleted list.
  1454. Arguments:
  1455. Message - The RPC_MESSAGE structure associated with this call.
  1456. Return Value:
  1457. RPC_S_OK
  1458. RPC_S_OUT_OF_MEMORY
  1459. --*/
  1460. {
  1461. LogEvent(SU_SCALL, EV_PROC, this, IntToPtr(Message->BufferLength), 'G' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  1462. RPC_STATUS Status = CommonGetBuffer(Message);
  1463. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  1464. if (Status)
  1465. {
  1466. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  1467. }
  1468. #ifdef MONITOR_SERVER_PACKET_COUNT
  1469. DG_PACKET::FromStubData(Message->Buffer)->pCount = &OutstandingPacketCount;
  1470. InterlockedIncrement( &OutstandingPacketCount );
  1471. LogEvent( SU_SCALL, '(', this, DG_PACKET::FromStubData(Message->Buffer), OutstandingPacketCount );
  1472. #endif
  1473. return Status;
  1474. }
  1475. void
  1476. DG_SCALL::FreeBuffer (
  1477. IN PRPC_MESSAGE Message
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. This routine is called to free up the marshalled data after the stub
  1482. is through with it.
  1483. Arguments:
  1484. Message - The RPC_MESSAGE structure associated with this call
  1485. Return Value:
  1486. <none>
  1487. --*/
  1488. {
  1489. LogEvent(SU_SCALL, EV_PROC, this, Message, 'F' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  1490. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, 0);
  1491. if (Message->Buffer)
  1492. {
  1493. if (Message->Buffer == DispatchBuffer)
  1494. {
  1495. DispatchBuffer = 0;
  1496. }
  1497. // The ReservedForRuntime field is a local variable of ProcessRpcCall,
  1498. // so it is valid only during dispatch.
  1499. //
  1500. if (State == CallDispatched && Message->ReservedForRuntime)
  1501. {
  1502. PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
  1503. if (Message->Buffer == Info->OldBuffer)
  1504. {
  1505. Info->OldBuffer = 0;
  1506. }
  1507. }
  1508. CommonFreeBuffer(Message);
  1509. }
  1510. }
  1511. RPC_STATUS
  1512. DG_SCALL::SendReceive (
  1513. IN OUT PRPC_MESSAGE Message
  1514. )
  1515. /*++
  1516. Routine Description:
  1517. This routine is called for a user-level callback.
  1518. Arguments:
  1519. Message - The RPC_MESSAGE structure associated with this call
  1520. Return Value:
  1521. RPC_S_OK
  1522. RPC_S_OUT_OF_MEMORY
  1523. Revision History:
  1524. --*/
  1525. {
  1526. Message->ReservedForRuntime = 0;
  1527. FreeBuffer(Message);
  1528. return RPC_S_CALL_FAILED;
  1529. }
  1530. #pragma optimize("t", on)
  1531. void
  1532. DG_SCONNECTION::DispatchPacket(
  1533. IN DG_PACKET * Packet,
  1534. IN DatagramTransportPair *AddressPair
  1535. )
  1536. /*++
  1537. Routine Description:
  1538. Once a packet's activity UUID is known, this fn dispatches the packet
  1539. to the appropriate DG_SCALL, creating one if necessary.
  1540. Arguments:
  1541. Packet - the packet to dispatch
  1542. AddressPair - the remote/local address that sent/received the packet
  1543. --*/
  1544. {
  1545. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1546. #ifdef DEBUGRPC
  1547. RPC_UUID * pInActivityUuid = &pHeader->ActivityId;
  1548. ASSERT(0 == ActivityNode.CompareUuid(pInActivityUuid));
  1549. #endif
  1550. TimeStamp = GetTickCount();
  1551. //
  1552. // Make sure the security info is consistent.
  1553. //
  1554. if (AuthInfo.AuthenticationService != pHeader->AuthProto)
  1555. {
  1556. if (pHeader->PacketType != DG_PING &&
  1557. (0 == (pHeader->PacketFlags & DG_PF_MAYBE) || pHeader->AuthProto))
  1558. {
  1559. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 10, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1560. #ifdef DEBUGRPC
  1561. DbgPrint("dg rpc: %lx dropping %u whose auth service %u is inconsistent w/the activity %u\n",
  1562. GetCurrentProcessId(), pHeader->PacketType, pHeader->AuthProto, AuthInfo.AuthenticationService);
  1563. #endif
  1564. Mutex.Clear();
  1565. Packet->Free();
  1566. return;
  1567. }
  1568. }
  1569. else if (pHeader->AuthProto)
  1570. {
  1571. DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *)
  1572. (Packet->Header.Data + Packet->GetPacketBodyLen());
  1573. if (Verifier->protection_level != AuthInfo.AuthenticationLevel)
  1574. {
  1575. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 11, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1576. #ifdef DEBUGRPC
  1577. DbgPrint("dg rpc: %lx dropping pkt whose auth level is inconsistent with the activity\n", GetCurrentProcessId());
  1578. #endif
  1579. Mutex.Clear();
  1580. Packet->Free();
  1581. return;
  1582. }
  1583. }
  1584. //
  1585. // Sanity-check the packet length.
  1586. //
  1587. if (0 == (Packet->Flags & DG_PF_PARTIAL))
  1588. {
  1589. if (pHeader->AuthProto)
  1590. {
  1591. if (Packet->DataLength < Packet->GetPacketBodyLen() + sizeof(DG_SECURITY_TRAILER))
  1592. {
  1593. #ifdef DEBUGRPC
  1594. DbgPrint("dg rpc: secure packet truncated from at least %lu to %lu\n",
  1595. Packet->GetPacketBodyLen() + sizeof(DG_SECURITY_TRAILER), Packet->DataLength);
  1596. #endif
  1597. Mutex.Clear();
  1598. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 8, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1599. Packet->Free();
  1600. return;
  1601. }
  1602. }
  1603. else
  1604. {
  1605. if (Packet->DataLength < Packet->GetPacketBodyLen())
  1606. {
  1607. #ifdef DEBUGRPC
  1608. DbgPrint("dg rpc: packet truncated from %lu to %lu\n", Packet->GetPacketBodyLen(), Packet->DataLength);
  1609. #endif
  1610. Mutex.Clear();
  1611. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 9, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1612. Packet->Free();
  1613. return;
  1614. }
  1615. }
  1616. }
  1617. //
  1618. // [maybe] calls require little of our advanced technology.
  1619. //
  1620. if (pHeader->PacketFlags & DG_PF_MAYBE)
  1621. {
  1622. if (HandleMaybeCall(Packet, AddressPair))
  1623. {
  1624. // mutex released in HandleMaybeCall.
  1625. return;
  1626. }
  1627. }
  1628. //
  1629. // Calls below LowestActiveSequence are dead.
  1630. //
  1631. if (pHeader->SequenceNumber < LowestActiveSequence)
  1632. {
  1633. Mutex.Clear();
  1634. LogEvent(SU_SCONN, EV_PKT_IN, this, (void *) 0, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1635. Packet->Free();
  1636. return;
  1637. }
  1638. //
  1639. // Find or allocate the DG_SCALL for this packet.
  1640. //
  1641. PDG_SCALL Call = 0;
  1642. if (pHeader->SequenceNumber < LowestUnusedSequence)
  1643. {
  1644. Call = ActiveCalls.Find(pHeader->SequenceNumber);
  1645. if (!Call)
  1646. {
  1647. Mutex.Clear();
  1648. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1649. Packet->Free();
  1650. return;
  1651. }
  1652. }
  1653. else
  1654. {
  1655. Call = HandleNewCall(Packet, AddressPair);
  1656. if (!Call)
  1657. {
  1658. Mutex.Clear();
  1659. Packet->Free();
  1660. return;
  1661. }
  1662. }
  1663. Mutex.VerifyOwned();
  1664. Call->DispatchPacket(Packet, AddressPair->RemoteAddress);
  1665. CallDispatchLoop();
  1666. Mutex.Clear();
  1667. Mutex.VerifyNotOwned();
  1668. }
  1669. void
  1670. DG_SCONNECTION::CallDispatchLoop()
  1671. {
  1672. Mutex.VerifyOwned();
  1673. //
  1674. // The loop below is to handle the case where a bunch of async calls arrive
  1675. // more or less simultaneously. When stub #1 has finished, we should
  1676. // dispatch stub #2 immediately instead of waiting for the client to ping.
  1677. //
  1678. while (CurrentCall && CurrentCall->ReadyToDispatch() &&
  1679. (Callback.State == CallbackSucceeded ||
  1680. Callback.State == NoCallbackAttempted ))
  1681. {
  1682. PDG_SCALL Call = CurrentCall;
  1683. Call->ProcessRpcCall();
  1684. if (CurrentCall == Call)
  1685. {
  1686. CurrentCall = ActiveCalls.Successor(Call);
  1687. }
  1688. }
  1689. Mutex.VerifyOwned();
  1690. }
  1691. PDG_SCALL
  1692. DG_SCONNECTION::HandleNewCall(
  1693. IN DG_PACKET * Packet,
  1694. IN DatagramTransportPair *AddressPair
  1695. )
  1696. {
  1697. PDG_SCALL Call = 0;
  1698. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1699. //
  1700. // Only a REQUEST can instantiate a new call.
  1701. //
  1702. if (pHeader->PacketType != DG_REQUEST)
  1703. {
  1704. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1705. CleanupPacket(&Packet->Header);
  1706. Packet->Header.PacketType = DG_NOCALL;
  1707. Packet->SetPacketBodyLen(0);
  1708. Packet->SetFragmentNumber(0xffff);
  1709. SealAndSendPacket( &pAddress->Endpoint,
  1710. AddressPair->RemoteAddress,
  1711. &Packet->Header,
  1712. 0
  1713. );
  1714. return 0;
  1715. }
  1716. if ((Packet->Header.PacketFlags & DG_PF_FORWARDED) &&
  1717. (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) == 0)
  1718. {
  1719. //
  1720. // This packet is not a true request.
  1721. //
  1722. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1723. return 0;
  1724. }
  1725. //
  1726. // See if the call closes a previous call.
  1727. //
  1728. if (0 == (pHeader->PacketFlags2 & DG_PF2_UNRELATED))
  1729. {
  1730. PDG_SCALL PreviousCall = ActiveCalls.Predecessor(pHeader->SequenceNumber);
  1731. if (PreviousCall)
  1732. {
  1733. PreviousCall->FinishSendOrReceive(TRUE);
  1734. PreviousCall->Cleanup();
  1735. }
  1736. }
  1737. LowestUnusedSequence = pHeader->SequenceNumber + 1;
  1738. //
  1739. // Prepare a DG_SCALL to handle the packet.
  1740. //
  1741. Call = AllocateCall();
  1742. LogEvent(SU_SCALL, EV_START, Call, this, pHeader->SequenceNumber);
  1743. if (!Call)
  1744. {
  1745. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 4, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1746. pAddress->SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  1747. return 0;
  1748. }
  1749. Call->NewCall(Packet, AddressPair);
  1750. if (FALSE == ActiveCalls.Add(Call, pHeader->SequenceNumber))
  1751. {
  1752. AddCallToCache(Call);
  1753. LogError(SU_SCONN, EV_PKT_IN, this, (void *) 5, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1754. pAddress->SendRejectPacket(Packet, RPC_S_OUT_OF_MEMORY, AddressPair->RemoteAddress);
  1755. return 0;
  1756. }
  1757. if (!CurrentCall)
  1758. {
  1759. CurrentCall = Call;
  1760. }
  1761. return Call;
  1762. }
  1763. #pragma optimize("", on)
  1764. BOOL
  1765. DG_SCONNECTION::HandleMaybeCall(
  1766. IN DG_PACKET * Packet,
  1767. IN DatagramTransportPair *AddressPair
  1768. )
  1769. {
  1770. PNCA_PACKET_HEADER pHeader = &Packet->Header;
  1771. if (pHeader->PacketType != DG_REQUEST)
  1772. {
  1773. Mutex.Clear();
  1774. Packet->Free();
  1775. return TRUE;
  1776. }
  1777. if (!(pHeader->PacketFlags & DG_PF_FORWARDED) &&
  1778. !(pHeader->PacketFlags2 & DG_PF2_FORWARDED_2) )
  1779. {
  1780. DG_SCALL * Call = AllocateCall();
  1781. LogEvent(SU_SCALL, EV_START, Call, this, pHeader->SequenceNumber);
  1782. if (!Call)
  1783. {
  1784. Mutex.Clear();
  1785. Packet->Free();
  1786. return TRUE;
  1787. }
  1788. Call->NewCall(Packet, AddressPair);
  1789. Call->DealWithRequest( Packet );
  1790. if (Call->ReadyToDispatch())
  1791. {
  1792. Call->ProcessRpcCall();
  1793. }
  1794. BOOL Result = Call->Cleanup();
  1795. ASSERT( Result );
  1796. Mutex.Clear();
  1797. return TRUE;
  1798. }
  1799. //
  1800. // [maybe] calls fragmented by the ep mapper go through the normal route
  1801. //
  1802. return FALSE;
  1803. }
  1804. BOOL
  1805. DG_SCALL::ReadyToDispatch(
  1806. )
  1807. {
  1808. BOOL fReadyToDispatch = FALSE;
  1809. //
  1810. // Before we can execute the call, we need the client's true endpoint,
  1811. // for a forwarded call. For a non-idempotent call we also need a
  1812. // successful callback.
  1813. //
  1814. // For a stub in a pipes interface, we need only fragment zero;
  1815. // for ordinary interfaces we need all the fragments.
  1816. //
  1817. if (KnowClientAddress && State == CallBeforeDispatch)
  1818. {
  1819. //
  1820. // See if we are ready to dispatch to the stub.
  1821. //
  1822. if (Interface->IsPipeInterface())
  1823. {
  1824. if (pReceivedPackets && 0 == pReceivedPackets->GetFragmentNumber())
  1825. {
  1826. fReadyToDispatch = TRUE;
  1827. }
  1828. }
  1829. else
  1830. {
  1831. if (fReceivedAllFragments)
  1832. {
  1833. fReadyToDispatch = TRUE;
  1834. }
  1835. }
  1836. }
  1837. //
  1838. // Make sure the callback succeeded.
  1839. //
  1840. if (fReadyToDispatch)
  1841. {
  1842. if (0 == (pReceivedPackets->Header.PacketFlags & DG_PF_IDEMPOTENT) &&
  1843. !Connection->pAssocGroup)
  1844. {
  1845. fReadyToDispatch = FALSE;
  1846. }
  1847. }
  1848. return fReadyToDispatch;
  1849. }
  1850. #pragma optimize("t", on)
  1851. void
  1852. DG_SCALL::DispatchPacket(
  1853. IN PDG_PACKET Packet,
  1854. IN DG_TRANSPORT_ADDRESS a_RemoteAddress
  1855. )
  1856. {
  1857. #ifdef MONITOR_SERVER_PACKET_COUNT
  1858. if (Packet->Header.PacketType == DG_REQUEST)
  1859. {
  1860. InterlockedIncrement( &OutstandingPacketCount );
  1861. Packet->pCount = &OutstandingPacketCount;
  1862. LogEvent( SU_SCALL, '(', this, Packet, OutstandingPacketCount );
  1863. }
  1864. #endif
  1865. TimeStamp = GetTickCount();
  1866. if (State == CallInit &&
  1867. Packet->Header.PacketType != DG_REQUEST)
  1868. {
  1869. LogError(SU_SCALL, EV_PKT_IN, this, (void *) 1, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1870. if (KnowClientAddress)
  1871. {
  1872. SendFackOrNocall(Packet, DG_NOCALL);
  1873. }
  1874. FreePacket(Packet);
  1875. return;
  1876. }
  1877. if (State == CallComplete)
  1878. {
  1879. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) 2, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1880. FreePacket(Packet);
  1881. return;
  1882. }
  1883. //
  1884. // FORWARDED FORWARDED_2 Meaning
  1885. // --------- ----------- -------
  1886. // no no packet sent directly from client
  1887. // yes no packet forwarded by ep mapper (with DREP/ep trailer)
  1888. // no yes packet data forwarded by ep mapper (no trailer)
  1889. // yes yes sent from ep mapper; contains only the DREP/ep trailer
  1890. //
  1891. if (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2)
  1892. {
  1893. CallWasForwarded = TRUE;
  1894. if (Packet->Header.PacketFlags & DG_PF_FORWARDED)
  1895. {
  1896. if (!KnowClientAddress)
  1897. {
  1898. //
  1899. // Record the client's true endpoint.
  1900. //
  1901. RpcpMemoryCopy(
  1902. RemoteAddress,
  1903. a_RemoteAddress,
  1904. Connection->pAddress->Endpoint.TransportInterface->AddressSize
  1905. );
  1906. KnowClientAddress = TRUE;
  1907. }
  1908. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) 3, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1909. FreePacket(Packet);
  1910. return;
  1911. }
  1912. }
  1913. else
  1914. {
  1915. ASSERT( (Packet->Header.PacketFlags & DG_PF_FORWARDED) == 0 );
  1916. }
  1917. LogEvent(SU_SCALL, EV_PKT_IN, this, 0, (Packet->Header.PacketType << 16) | Packet->GetFragmentNumber());
  1918. switch (Packet->Header.PacketType)
  1919. {
  1920. case DG_REQUEST: DealWithRequest (Packet); break;
  1921. case DG_PING: DealWithPing (Packet); break;
  1922. case DG_FACK: DealWithFack (Packet); break;
  1923. case DG_QUIT: DealWithQuit (Packet); break;
  1924. case DG_ACK: DealWithAck (Packet); break;
  1925. default:
  1926. {
  1927. FreePacket(Packet);
  1928. FinishSendOrReceive(TRUE);
  1929. Cleanup();
  1930. }
  1931. }
  1932. }
  1933. #pragma optimize("", on)
  1934. void
  1935. DG_SCALL::DealWithPing(
  1936. PDG_PACKET pPacket
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. Figures out what to do with a PING packet. It may send a WORKING
  1941. or NOCALL packet, or retransmit response fragments.
  1942. Arguments:
  1943. pPacket - the PING packet
  1944. Return Value:
  1945. none
  1946. --*/
  1947. {
  1948. //
  1949. // Ignore security trailer. The only way extra PINGs can hose me is by
  1950. // chewing up CPU, and authenticating would only make it worse.
  1951. //
  1952. NCA_PACKET_HEADER * pHeader = &pPacket->Header;
  1953. unsigned PacketSeq = pHeader->SequenceNumber;
  1954. unsigned short Serial = ReadSerialNumber(&pPacket->Header);
  1955. if (Serial < ReceiveSerialNumber)
  1956. {
  1957. FreePacket(pPacket);
  1958. return;
  1959. }
  1960. ReceiveSerialNumber = Serial;
  1961. switch (State)
  1962. {
  1963. case CallInit:
  1964. {
  1965. SendFackOrNocall(pPacket, DG_NOCALL);
  1966. break;
  1967. }
  1968. case CallBeforeDispatch:
  1969. case CallDispatched:
  1970. case CallAfterDispatch:
  1971. {
  1972. if (fReceivedAllFragments)
  1973. {
  1974. pHeader->PacketType = DG_WORKING;
  1975. pHeader->SetPacketBodyLen(0);
  1976. SealAndSendPacket(pHeader);
  1977. }
  1978. else
  1979. {
  1980. SendFackOrNocall(pPacket, DG_FACK);
  1981. }
  1982. break;
  1983. }
  1984. case CallSendingResponse:
  1985. {
  1986. SendSomeFragments();
  1987. break;
  1988. }
  1989. case CallComplete:
  1990. {
  1991. break;
  1992. }
  1993. default:
  1994. {
  1995. ASSERT(0 && "invalid call state");
  1996. }
  1997. }
  1998. FreePacket(pPacket);
  1999. }
  2000. RPC_STATUS
  2001. DG_SCONNECTION::VerifyNonRequestPacket(
  2002. DG_PACKET * Packet
  2003. )
  2004. {
  2005. if (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  2006. {
  2007. if (AuthInfo.AuthenticationService != RPC_C_AUTHN_DCE_PRIVATE )
  2008. {
  2009. SECURITY_CONTEXT * Context = FindMatchingSecurityContext(Packet);
  2010. if (!Context)
  2011. {
  2012. LogError(SU_SCONN, EV_STATUS, this, (void *) 110, RPC_S_ACCESS_DENIED );
  2013. return RPC_S_ACCESS_DENIED;
  2014. }
  2015. return VerifySecurePacket(Packet, Context);
  2016. }
  2017. }
  2018. return RPC_S_OK;
  2019. }
  2020. RPC_STATUS
  2021. DG_SCONNECTION::VerifyRequestPacket(
  2022. DG_PACKET * Packet
  2023. )
  2024. {
  2025. if (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  2026. {
  2027. SECURITY_CONTEXT * Context = FindMatchingSecurityContext(Packet);
  2028. if (!Context)
  2029. {
  2030. LogError(SU_SCONN, EV_STATUS, this, (void *) 111, RPC_S_ACCESS_DENIED );
  2031. return RPC_S_ACCESS_DENIED;
  2032. }
  2033. return VerifySecurePacket(Packet, Context);
  2034. }
  2035. return RPC_S_OK;
  2036. }
  2037. void
  2038. DG_SCALL::DealWithQuit(
  2039. PDG_PACKET pPacket
  2040. )
  2041. /*++
  2042. Routine Description:
  2043. Handles a QUIT packet:
  2044. - If the cancel event ID is new, we cancel the current call and send a QUACK.
  2045. - If the event ID is the current one, we retransmit the QUACK.
  2046. - If the event ID is older than the current one, we ignore the packet.
  2047. Arguments:
  2048. the packet
  2049. Return Value:
  2050. none
  2051. --*/
  2052. {
  2053. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2054. {
  2055. FreePacket(pPacket);
  2056. return;
  2057. }
  2058. QUIT_BODY_0 * pBody = (QUIT_BODY_0 *) pPacket->Header.Data;
  2059. if (pPacket->GetPacketBodyLen() < sizeof(QUIT_BODY_0) ||
  2060. pBody->Version != 0)
  2061. {
  2062. #ifdef DEBUGRPC
  2063. DbgPrint("RPC DG: unknown quit format: version 0x%lx, length 0x%hx\n",
  2064. pBody->Version, pPacket->GetPacketBodyLen()
  2065. );
  2066. #endif
  2067. FreePacket(pPacket);
  2068. return;
  2069. }
  2070. if (pBody->EventId > CancelEventId)
  2071. {
  2072. CancelEventId = pBody->EventId;
  2073. Cancel(0);
  2074. }
  2075. if (pBody->EventId == CancelEventId)
  2076. {
  2077. pSavedPacket->Header.PacketType = DG_QUACK;
  2078. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  2079. pSavedPacket->SetPacketBodyLen(sizeof(QUACK_BODY_0));
  2080. QUACK_BODY_0 * pAckBody = (QUACK_BODY_0 *) pSavedPacket->Header.Data;
  2081. pAckBody->Version = 0;
  2082. pAckBody->EventId = CancelEventId;
  2083. //
  2084. // If the app has picked up the cancel notification, set Accepted == TRUE.
  2085. // This is likely only if the QUIT was retransmitted.
  2086. //
  2087. if (Cancelled)
  2088. {
  2089. pAckBody->Accepted = FALSE;
  2090. }
  2091. else
  2092. {
  2093. pAckBody->Accepted = TRUE;
  2094. }
  2095. SealAndSendPacket(&pSavedPacket->Header);
  2096. }
  2097. else
  2098. {
  2099. #ifdef DEBUGRPC
  2100. DbgPrint("RPC DG: stale cancel event id %lu\n", pBody->EventId);
  2101. #endif
  2102. }
  2103. FreePacket(pPacket);
  2104. }
  2105. void
  2106. DG_SCALL::DealWithAck(
  2107. PDG_PACKET pPacket
  2108. )
  2109. /*++
  2110. Routine Description:
  2111. Figures out what to do with an ACK packet.
  2112. It turns off the fragment-retransmission timer.
  2113. Arguments:
  2114. pPacket - the ACK packet
  2115. Return Value:
  2116. none
  2117. --*/
  2118. {
  2119. if (State == CallSendingResponse)
  2120. {
  2121. //
  2122. // Accept only an authenticated ACK if the call is secure.
  2123. //
  2124. // Sometimes OSF clients will omit the sec trailer from the ACK.
  2125. //
  2126. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2127. {
  2128. FreePacket(pPacket);
  2129. return;
  2130. }
  2131. FinishSendOrReceive(FALSE);
  2132. Cleanup();
  2133. }
  2134. FreePacket(pPacket);
  2135. }
  2136. void
  2137. DG_SCALL::DealWithFack(
  2138. PDG_PACKET pPacket
  2139. )
  2140. /*++
  2141. Routine Description:
  2142. Figures out what to do with a FACK packet.
  2143. If there is more data to send, it sends the next fragment
  2144. and restarts the fragment-retransmission timer.
  2145. Arguments:
  2146. pPacket - the packet
  2147. Return Value:
  2148. none
  2149. --*/
  2150. {
  2151. BOOL Ignore;
  2152. // is call finished?
  2153. if (State != CallSendingResponse)
  2154. {
  2155. FreePacket(pPacket);
  2156. return;
  2157. }
  2158. if (RPC_S_OK != Connection->VerifyNonRequestPacket(pPacket))
  2159. {
  2160. FreePacket(pPacket);
  2161. return;
  2162. }
  2163. //
  2164. // Note fack arrival, and send more packets if necessary.
  2165. //
  2166. TimeoutCount = 0;
  2167. SendBurstLength += 1;
  2168. UpdateSendWindow(pPacket, &Ignore);
  2169. //
  2170. // See whether we need to wake up a call to I_RpcSend, or generate an APC.
  2171. //
  2172. if (IsBufferAcknowledged())
  2173. {
  2174. FinishSendOrReceive(FALSE);
  2175. }
  2176. FreePacket(pPacket);
  2177. }
  2178. #pragma optimize("t", on)
  2179. void
  2180. DG_SCALL::DealWithRequest(
  2181. PDG_PACKET pPacket
  2182. )
  2183. {
  2184. RPC_STATUS Status = RPC_S_OK;
  2185. PNCA_PACKET_HEADER pHeader = &pPacket->Header;
  2186. ASSERT(pHeader->SequenceNumber == SequenceNumber);
  2187. switch (State)
  2188. {
  2189. case CallInit:
  2190. {
  2191. //
  2192. // Be sure the server is listening and the interface is supported.
  2193. //
  2194. RPC_SYNTAX_IDENTIFIER InterfaceInfo;
  2195. InterfaceInfo.SyntaxVersion = pHeader->InterfaceVersion;
  2196. RpcpMemoryCopy(
  2197. &(InterfaceInfo.SyntaxGUID),
  2198. &(pHeader->InterfaceId),
  2199. sizeof(RPC_UUID)
  2200. );
  2201. if (Connection->LastInterface &&
  2202. 0 == Connection->LastInterface->MatchInterfaceIdentifier(&InterfaceInfo))
  2203. {
  2204. Interface = Connection->LastInterface;
  2205. }
  2206. else
  2207. {
  2208. Interface = GlobalRpcServer->FindInterface(&InterfaceInfo);
  2209. Connection->LastInterface = Interface;
  2210. }
  2211. if (!Interface)
  2212. {
  2213. Status = RPC_S_UNKNOWN_IF;
  2214. }
  2215. else if (!GlobalRpcServer->IsServerListening() &&
  2216. !Interface->IsAutoListenInterface())
  2217. {
  2218. Status = RPC_S_SERVER_TOO_BUSY;
  2219. // If this is a message transport (i.e. Falcon) then
  2220. // wait around for a while before giving up. The user
  2221. // may not have called RpcServerListen() yet...
  2222. if (Connection->TransportInterface->IsMessageTransport)
  2223. {
  2224. for (int i=0; i<100; i++)
  2225. {
  2226. if (GlobalRpcServer->IsServerListening())
  2227. {
  2228. Status = RPC_S_OK;
  2229. break;
  2230. }
  2231. else
  2232. {
  2233. Sleep(100); // Loop 100 * Sleep 100 = 10 seconds.
  2234. }
  2235. }
  2236. }
  2237. }
  2238. if (Status == RPC_S_OK)
  2239. {
  2240. Status = Interface->IsObjectSupported(&pHeader->ObjectId);
  2241. }
  2242. if (Status == RPC_S_OK &&
  2243. Connection->DidCallbackFail())
  2244. {
  2245. Status = RPC_S_CALL_FAILED_DNE;
  2246. }
  2247. if (Status != RPC_S_OK)
  2248. {
  2249. BOOL fSendReject = !(pHeader->PacketFlags & DG_PF_MAYBE);
  2250. FreePacket(pPacket);
  2251. if (fSendReject)
  2252. {
  2253. pSavedPacket->Header.SequenceNumber = SequenceNumber;
  2254. Connection->pAddress->SendRejectPacket(pSavedPacket, Status, RemoteAddress);
  2255. }
  2256. Cleanup();
  2257. break;
  2258. }
  2259. //
  2260. // The server is listening and the interface is present.
  2261. // We will increment these counters to declare that a call
  2262. // is in progress.
  2263. //
  2264. CallInProgress = TRUE;
  2265. Connection->pAddress->IncrementActiveCallCount();
  2266. if (Interface->IsAutoListenInterface())
  2267. {
  2268. Interface->BeginAutoListenCall() ;
  2269. Connection->pAddress->BeginAutoListenCall() ;
  2270. }
  2271. SetState(CallBeforeDispatch);
  2272. //
  2273. // No "break" here.
  2274. //
  2275. }
  2276. case CallBeforeDispatch:
  2277. case CallDispatched:
  2278. case CallAfterDispatch:
  2279. {
  2280. if (fReceivedAllFragments)
  2281. {
  2282. pHeader->PacketType = DG_WORKING;
  2283. pHeader->SetPacketBodyLen(0);
  2284. SealAndSendPacket(pHeader);
  2285. FreePacket(pPacket);
  2286. break;
  2287. }
  2288. //
  2289. // If the client sent an oversize fragment, send a FACK-with-body
  2290. // telling him our limit.
  2291. //
  2292. if (pPacket->Flags & DG_PF_PARTIAL)
  2293. {
  2294. SendFackOrNocall(pPacket, DG_FACK);
  2295. FreePacket(pPacket);
  2296. break;
  2297. }
  2298. //
  2299. // Add the fragment to the call's packet list.
  2300. //
  2301. BOOL Added = UpdateReceiveWindow(pPacket);
  2302. if (!Added)
  2303. {
  2304. unsigned Frag = (pPacket->Header.PacketType << 16) | pPacket->GetFragmentNumber();
  2305. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) '!', Frag);
  2306. }
  2307. //
  2308. // See whether we need to wake up a call to I_RpcReceive.
  2309. //
  2310. if (PipeWaitType == PWT_RECEIVE &&
  2311. (fReceivedAllFragments ||
  2312. (PipeWaitLength && ConsecutiveDataBytes >= PipeWaitLength)))
  2313. {
  2314. FinishSendOrReceive(FALSE);
  2315. }
  2316. if (KnowClientAddress)
  2317. {
  2318. Connection->SubmitCallbackIfNecessary(this, pPacket, RemoteAddress);
  2319. }
  2320. if (!Added)
  2321. {
  2322. FreePacket(pPacket);
  2323. }
  2324. break;
  2325. }
  2326. case CallSendingResponse:
  2327. {
  2328. SendSomeFragments();
  2329. FreePacket(pPacket);
  2330. break;
  2331. }
  2332. default:
  2333. {
  2334. ASSERT(0 && "invalid call state");
  2335. break;
  2336. }
  2337. }
  2338. }
  2339. void
  2340. DG_SCALL::ProcessRpcCall()
  2341. /*++
  2342. Routine Description:
  2343. This routine is called when we determine that all the packets for a
  2344. given call have been received.
  2345. --*/
  2346. {
  2347. BOOL ObjectUuidSpecified;
  2348. PNCA_PACKET_HEADER pHeader = &pReceivedPackets->Header;
  2349. PRPC_DISPATCH_TABLE DispatchTableToUse;
  2350. ASSERT(State == CallBeforeDispatch);
  2351. SetState(CallDispatched);
  2352. //
  2353. // Save the object uuid if necessary.
  2354. //
  2355. if (pHeader->ObjectId.IsNullUuid())
  2356. {
  2357. ObjectUuidSpecified = FALSE;
  2358. }
  2359. else
  2360. {
  2361. ObjectUuidSpecified = TRUE;
  2362. pSavedPacket->Header.ObjectId.CopyUuid(&pHeader->ObjectId);
  2363. }
  2364. RpcRuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  2365. RpcMessage.ReservedForRuntime = &RpcRuntimeInfo ;
  2366. RpcMessage.Handle = (RPC_BINDING_HANDLE) this;
  2367. RpcMessage.ProcNum = pHeader->OperationNumber;
  2368. RpcMessage.TransferSyntax = 0;
  2369. RpcMessage.ImportContext = 0;
  2370. RpcMessage.RpcFlags = PacketToRpcFlags(pHeader->PacketFlags);
  2371. unsigned OriginalSequenceNumber = SequenceNumber;
  2372. unsigned long SavedAwayRpcFlags = RpcMessage.RpcFlags;
  2373. RPC_STATUS Status = RPC_S_OK;
  2374. //
  2375. // For secure RPC, verify packet integrity.
  2376. //
  2377. if (pHeader->AuthProto)
  2378. {
  2379. PDG_PACKET pScan = pReceivedPackets;
  2380. do
  2381. {
  2382. Status = Connection->VerifyRequestPacket(pScan);
  2383. if (Status)
  2384. {
  2385. LogError( SU_SCALL, EV_STATUS, this, UlongToPtr(0x200), Status );
  2386. }
  2387. pScan = pScan->pNext;
  2388. }
  2389. while (pScan && Status == RPC_S_OK);
  2390. }
  2391. //
  2392. // Coalesce packet data.
  2393. //
  2394. if (RPC_S_OK == Status)
  2395. {
  2396. RpcMessage.Buffer = 0;
  2397. RpcMessage.BufferLength = 0;
  2398. Status = AssembleBufferFromPackets(&RpcMessage);
  2399. }
  2400. if (Status != RPC_S_OK)
  2401. {
  2402. InitErrorPacket(pSavedPacket, DG_REJECT, Status);
  2403. SealAndSendPacket(&pSavedPacket->Header);
  2404. Cleanup();
  2405. return;
  2406. }
  2407. DispatchBuffer = RpcMessage.Buffer;
  2408. //
  2409. // The thread context is used by routines like RpcBindingInqAuthClient
  2410. // when the user specifies hBinding == 0.
  2411. //
  2412. RpcpSetThreadContext(this);
  2413. //
  2414. // Make sure the thread is not impersonating.
  2415. //
  2416. ASSERT(0 == QueryThreadSecurityContext());
  2417. TerminateWhenConvenient = FALSE;
  2418. AsyncStatus = RPC_S_OK;
  2419. //
  2420. // Time to deal with the interface security callback. If it is required,
  2421. // the call must be secure. If we have already made a callback using
  2422. // the current auth context, we can use the cached results; otherwise,
  2423. // we should call back.
  2424. //
  2425. if (Interface->IsSecurityCallbackReqd())
  2426. {
  2427. Status = Connection->MakeApplicationSecurityCallback(Interface, this);
  2428. if (Status)
  2429. {
  2430. LogError( SU_SCALL, EV_STATUS, this, UlongToPtr(0x201), Status );
  2431. }
  2432. }
  2433. if (TerminateWhenConvenient)
  2434. {
  2435. RpcpSetThreadContext(0);
  2436. Cleanup();
  2437. return;
  2438. }
  2439. //
  2440. // If this is a message based transport then we will need the
  2441. // message mutex for call serialization:
  2442. //
  2443. if (Connection->TransportInterface->IsMessageTransport)
  2444. {
  2445. if (!Connection->pMessageMutex)
  2446. {
  2447. Connection->MessageMutexInitialize(&Status);
  2448. }
  2449. }
  2450. //
  2451. // If no errors have occurred, we are ready to dispatch. Release
  2452. // the call mutex, call the server stub, and grab the mutex again.
  2453. //
  2454. BOOL StubWasCalled = FALSE;
  2455. if (RPC_S_OK == Status)
  2456. {
  2457. ASSERT(Interface);
  2458. //
  2459. // doc:appref
  2460. //
  2461. // SetAsyncHandle adds a reference to the call on behalf of the app,
  2462. // so that the call cannot be deleted even though the manager routine
  2463. // has completed and no Send or Receive calls are pending.
  2464. // That reference should be removed when one of the following occurs:
  2465. //
  2466. // a) (obsolete)
  2467. // b) the app sends the last buffer (RPC_BUFFER_PARTIAL not set)
  2468. // c) a Send() returns something other than OK or SEND_INCOMPLETE
  2469. // d) the app calls AbortAsyncCall
  2470. //
  2471. IncrementRefCount();
  2472. Connection->Mutex.Clear();
  2473. //
  2474. // If this is a message based call (MQ) then take a mutex for
  2475. // serialization:
  2476. //
  2477. if (Connection->TransportInterface->IsMessageTransport)
  2478. {
  2479. ASSERT(Connection->pMessageMutex);
  2480. Connection->pMessageMutex->Request();
  2481. Connection->TransportInterface->AllowReceives(
  2482. SourceEndpoint->TransportEndpoint,
  2483. FALSE,
  2484. FALSE );
  2485. }
  2486. else
  2487. {
  2488. //
  2489. // Normal, non-message based calls:
  2490. //
  2491. Connection->pAddress->CheckThreadPool();
  2492. }
  2493. StubWasCalled = TRUE;
  2494. RPC_STATUS ExceptionCode = 0;
  2495. DispatchTableToUse = Interface->GetDefaultDispatchTable();
  2496. if ( !ObjectUuidSpecified )
  2497. {
  2498. Status = Interface->DispatchToStub(
  2499. &RpcMessage, // msg
  2500. 0, // callback flag
  2501. DispatchTableToUse, // dispatch table to use for
  2502. // this interface
  2503. &ExceptionCode // exception code
  2504. );
  2505. }
  2506. else
  2507. {
  2508. Status = Interface->DispatchToStubWithObject(
  2509. &RpcMessage, // msg
  2510. &pSavedPacket->Header.ObjectId, // object uuid
  2511. 0, // callback flag
  2512. DispatchTableToUse, // dispatch table to use for
  2513. // this interface
  2514. &ExceptionCode // exception code
  2515. );
  2516. }
  2517. //
  2518. // If this is a message based call (MQ) then clear the mutex:
  2519. //
  2520. if (Connection->TransportInterface->IsMessageTransport)
  2521. {
  2522. Connection->pMessageMutex->Clear();
  2523. Connection->TransportInterface->AllowReceives(
  2524. SourceEndpoint->TransportEndpoint,
  2525. TRUE,
  2526. FALSE );
  2527. Connection->pAddress->CheckThreadPool();
  2528. }
  2529. RpcMessage.RpcFlags = SavedAwayRpcFlags;
  2530. if (Status == RPC_S_PROCNUM_OUT_OF_RANGE ||
  2531. Status == RPC_S_UNSUPPORTED_TYPE ||
  2532. Status == RPC_S_SERVER_TOO_BUSY ||
  2533. Status == RPC_S_NOT_LISTENING ||
  2534. Status == RPC_S_UNKNOWN_IF)
  2535. {
  2536. StubWasCalled = FALSE;
  2537. }
  2538. Connection->Mutex.Request();
  2539. DecrementRefCount();
  2540. if (Status == RPC_P_EXCEPTION_OCCURED)
  2541. {
  2542. if (pAsync)
  2543. {
  2544. //
  2545. // Abort any lingering receive.
  2546. //
  2547. FinishSendOrReceive(TRUE);
  2548. DecrementRefCount();
  2549. //
  2550. // Later code will see TerminateWhenConvenient and will not send a fault packet.
  2551. //
  2552. InitErrorPacket(pSavedPacket, DG_FAULT, ExceptionCode);
  2553. SealAndSendPacket(&pSavedPacket->Header);
  2554. }
  2555. Status = ExceptionCode;
  2556. }
  2557. //
  2558. // If the manager routine impersonated the client,
  2559. // restore the thread to its native security context.
  2560. //
  2561. RevertToSelf();
  2562. }
  2563. RpcpSetThreadContext(0);
  2564. //
  2565. // Remember that a sync stub may have called the completion routine,
  2566. // or sent some [out] pipe data.
  2567. //
  2568. //
  2569. // Don't send a response of any sort for a [maybe] call.
  2570. //
  2571. if (RpcMessage.RpcFlags & RPC_NCA_FLAGS_MAYBE)
  2572. {
  2573. if (!Status)
  2574. {
  2575. FreeBuffer(&RpcMessage);
  2576. }
  2577. return;
  2578. }
  2579. //
  2580. // Has the client cancelled the call or another server thread aborted it?
  2581. //
  2582. if (TerminateWhenConvenient)
  2583. {
  2584. // if (!Status)
  2585. // {
  2586. // FreeBuffer(&Message);
  2587. // }
  2588. Cleanup();
  2589. return;
  2590. }
  2591. ASSERT( State == CallDispatched ||
  2592. State == CallSendingResponse );
  2593. //
  2594. // Ordinary error?
  2595. //
  2596. if (Status != RPC_S_OK)
  2597. {
  2598. if (StubWasCalled)
  2599. {
  2600. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  2601. }
  2602. else
  2603. {
  2604. InitErrorPacket(pSavedPacket, DG_REJECT, Status);
  2605. }
  2606. SealAndSendPacket(&pSavedPacket->Header);
  2607. Cleanup();
  2608. return;
  2609. }
  2610. //
  2611. // No error; the call is still in progress.
  2612. //
  2613. if (pAsync)
  2614. {
  2615. if (State == CallDispatched)
  2616. {
  2617. ASSERT( fReceivedAllFragments || Interface->IsPipeInterface() );
  2618. SetState(CallAfterDispatch);
  2619. }
  2620. }
  2621. else
  2622. {
  2623. ASSERT( fReceivedAllFragments );
  2624. if (State == CallSendingResponse)
  2625. {
  2626. ASSERT( Interface->IsPipeInterface() );
  2627. }
  2628. SetState(CallSendingResponse);
  2629. //
  2630. // Send the static [out] call parameters; [out] pipes were sent by the stub.
  2631. //
  2632. SetFragmentLengths();
  2633. PushBuffer(&RpcMessage);
  2634. CleanupReceiveWindow();
  2635. }
  2636. }
  2637. #pragma optimize("", on)
  2638. void
  2639. DG_SCALL::AddPacketToReceiveList(
  2640. PDG_PACKET pPacket
  2641. )
  2642. /*++
  2643. Routine Description:
  2644. Adds a packet to the receive list and lets the caller know whether this
  2645. call is ready to be processed.
  2646. Arguments:
  2647. pPacket - the packet to add to the list.
  2648. Return Value:
  2649. Revision History:
  2650. --*/
  2651. {
  2652. PNCA_PACKET_HEADER pHeader = &pPacket->Header;
  2653. unsigned Frag = (pPacket->Header.PacketType << 16) | pPacket->GetFragmentNumber();
  2654. BOOL Added = UpdateReceiveWindow(pPacket);
  2655. if (!Added)
  2656. {
  2657. LogEvent(SU_SCALL, EV_PKT_IN, this, (void *) '!', Frag);
  2658. }
  2659. //
  2660. // See whether we need to wake up a call to I_RpcReceive.
  2661. //
  2662. if (fReceivedAllFragments ||
  2663. (PipeWaitLength && ConsecutiveDataBytes >= PipeWaitLength))
  2664. {
  2665. FinishSendOrReceive(FALSE);
  2666. }
  2667. }
  2668. RPC_STATUS
  2669. DG_SCALL::ImpersonateClient()
  2670. /*++
  2671. Routine Description:
  2672. Force the current thread to impersonate the client of this DG_SCALL.
  2673. Note that the current thread might not be the thread executing the
  2674. server manager routine.
  2675. Arguments:
  2676. none
  2677. Return Value:
  2678. result of impersonating, or RPC_S_NO_CONTEXT_AVAILABLE if this is
  2679. an insecure call.
  2680. --*/
  2681. {
  2682. RPC_STATUS Status;
  2683. if (!Connection->ActiveSecurityContext)
  2684. {
  2685. return RPC_S_NO_CONTEXT_AVAILABLE;
  2686. }
  2687. Status = SetThreadSecurityContext(Connection->ActiveSecurityContext);
  2688. if (RPC_S_OK != Status)
  2689. {
  2690. return Status;
  2691. }
  2692. Status = Connection->ActiveSecurityContext->ImpersonateClient();
  2693. if (RPC_S_OK != Status)
  2694. {
  2695. ClearThreadSecurityContext();
  2696. }
  2697. return Status;
  2698. }
  2699. RPC_STATUS
  2700. DG_SCALL::RevertToSelf (
  2701. )
  2702. {
  2703. SECURITY_CONTEXT * SecurityContext = ClearThreadSecurityContext();
  2704. if (SecurityContext)
  2705. {
  2706. SecurityContext->RevertToSelf();
  2707. }
  2708. return(RPC_S_OK);
  2709. }
  2710. RPC_STATUS
  2711. DG_SCALL::InquireAuthClient (
  2712. OUT RPC_AUTHZ_HANDLE * Privs,
  2713. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  2714. OUT unsigned long * AuthenticationLevel,
  2715. OUT unsigned long * AuthenticationService,
  2716. OUT unsigned long * pAuthorizationService,
  2717. IN unsigned long Flags
  2718. )
  2719. {
  2720. if (0 == Connection->ActiveSecurityContext)
  2721. {
  2722. if ( (Connection->TransportInterface->InquireAuthClient) )
  2723. {
  2724. RPC_STATUS Status;
  2725. SID *pSid;
  2726. Status = Connection->TransportInterface->InquireAuthClient(
  2727. RemoteAddress,
  2728. ServerPrincipalName,
  2729. &pSid,
  2730. AuthenticationLevel,
  2731. AuthenticationService,
  2732. pAuthorizationService );
  2733. if ( (Status == RPC_S_OK)
  2734. && (ARGUMENT_PRESENT(ServerPrincipalName)))
  2735. {
  2736. Status = ConvertSidToUserW(pSid,(RPC_CHAR**)Privs);
  2737. }
  2738. return Status;
  2739. }
  2740. else
  2741. {
  2742. return RPC_S_BINDING_HAS_NO_AUTH;
  2743. }
  2744. }
  2745. if (AuthenticationLevel)
  2746. {
  2747. *AuthenticationLevel = Connection->ActiveSecurityContext->AuthenticationLevel;
  2748. }
  2749. if (AuthenticationService)
  2750. {
  2751. *AuthenticationService = Connection->ActiveSecurityContext->AuthenticationService;
  2752. }
  2753. if (Privs || pAuthorizationService)
  2754. {
  2755. if (!Privileges)
  2756. {
  2757. Connection->ActiveSecurityContext->GetDceInfo(&Privileges, &AuthorizationService);
  2758. }
  2759. if (Privs)
  2760. {
  2761. *Privs = Privileges;
  2762. }
  2763. if (pAuthorizationService)
  2764. {
  2765. *pAuthorizationService = AuthorizationService;
  2766. }
  2767. }
  2768. if (ARGUMENT_PRESENT(ServerPrincipalName))
  2769. {
  2770. RPC_STATUS Status;
  2771. Status = GlobalRpcServer->InquirePrincipalName(
  2772. *AuthenticationService,
  2773. ServerPrincipalName
  2774. );
  2775. ASSERT(Status == RPC_S_OK ||
  2776. Status == RPC_S_OUT_OF_MEMORY );
  2777. return Status;
  2778. }
  2779. return(RPC_S_OK);
  2780. }
  2781. RPC_STATUS
  2782. DG_SCALL::GetAssociationContextCollection (
  2783. OUT ContextCollection **CtxCollection
  2784. )
  2785. {
  2786. RPC_STATUS Status = Connection->GetAssociationGroup(RemoteAddress);
  2787. if (Status)
  2788. {
  2789. return Status;
  2790. }
  2791. ASSERT( Connection->pAssocGroup );
  2792. Status = Connection->pAssocGroup->GetAssociationContextCollection(CtxCollection);
  2793. return (Status);
  2794. }
  2795. void
  2796. DG_SCALL::InquireObjectUuid (
  2797. OUT RPC_UUID * ObjectUuid
  2798. )
  2799. {
  2800. ObjectUuid->CopyUuid(&pSavedPacket->Header.ObjectId);
  2801. }
  2802. RPC_STATUS
  2803. DG_SCALL::ToStringBinding (
  2804. OUT RPC_CHAR * * StringBinding
  2805. )
  2806. /*++
  2807. Routine Description:
  2808. We need to convert this particular SCALL into a string binding.
  2809. Typically, we get the SCALL in Message structure. An SCall is associated
  2810. with a particular address. We just ask the address to create a string
  2811. binding
  2812. Arguments:
  2813. StringBinding - Returns the string representation of the binding
  2814. handle.
  2815. Return Value:
  2816. RPC_S_OK - The operation completed successfully.
  2817. RPC_S_OUT_OF_MEMORY - We do not have enough memory available to
  2818. allocate space for the string binding.
  2819. --*/
  2820. {
  2821. BINDING_HANDLE * BindingHandle;
  2822. RPC_STATUS Status;
  2823. BindingHandle = Connection->pAddress->InquireBinding();
  2824. if (BindingHandle == 0)
  2825. return(RPC_S_OUT_OF_MEMORY);
  2826. BindingHandle->SetObjectUuid(&pSavedPacket->Header.ObjectId);
  2827. Status = BindingHandle->ToStringBinding(StringBinding);
  2828. BindingHandle->BindingFree();
  2829. return Status;
  2830. }
  2831. RPC_STATUS
  2832. DG_SCALL::ConvertToServerBinding (
  2833. OUT RPC_BINDING_HANDLE * pServerBinding
  2834. )
  2835. {
  2836. return CreateReverseBinding(pServerBinding, FALSE);
  2837. }
  2838. RPC_STATUS
  2839. DG_SCALL::CreateReverseBinding (
  2840. OUT RPC_BINDING_HANDLE * pServerBinding,
  2841. BOOL IncludeEndpoint
  2842. )
  2843. {
  2844. RPC_STATUS Status;
  2845. RPC_CHAR * ClientAddress;
  2846. RPC_CHAR * ClientEndpoint;
  2847. RPC_CHAR * StringBinding;
  2848. ClientAddress = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * Connection->TransportInterface->AddressStringSize);
  2849. if (!ClientAddress)
  2850. {
  2851. return RPC_S_OUT_OF_MEMORY;
  2852. }
  2853. Status = Connection->TransportInterface->QueryAddress(RemoteAddress, ClientAddress);
  2854. if ( Status != RPC_S_OK )
  2855. {
  2856. return(Status);
  2857. }
  2858. if (IncludeEndpoint)
  2859. {
  2860. ClientEndpoint = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * Connection->TransportInterface->EndpointStringSize);
  2861. if (!ClientEndpoint)
  2862. {
  2863. return RPC_S_OUT_OF_MEMORY;
  2864. }
  2865. Status = Connection->TransportInterface->QueryEndpoint(RemoteAddress, ClientEndpoint);
  2866. if ( Status != RPC_S_OK )
  2867. {
  2868. return(Status);
  2869. }
  2870. Status = RpcStringBindingCompose(0,
  2871. Connection->pAddress->InqRpcProtocolSequence(),
  2872. ClientAddress,
  2873. ClientEndpoint,
  2874. 0,
  2875. &StringBinding
  2876. );
  2877. }
  2878. else
  2879. {
  2880. Status = RpcStringBindingCompose(0,
  2881. Connection->pAddress->InqRpcProtocolSequence(),
  2882. ClientAddress,
  2883. 0,
  2884. 0,
  2885. &StringBinding
  2886. );
  2887. }
  2888. if ( Status != RPC_S_OK )
  2889. {
  2890. return(Status);
  2891. }
  2892. Status = RpcBindingFromStringBinding(StringBinding, pServerBinding);
  2893. if (RPC_S_OK == Status)
  2894. {
  2895. Status = RpcBindingSetObject(*pServerBinding,
  2896. (UUID *) &pSavedPacket->Header.ObjectId
  2897. );
  2898. RpcStringFree(&StringBinding);
  2899. }
  2900. return(Status);
  2901. }
  2902. RPC_STATUS
  2903. DG_SCALL::ConvertSidToUserW(
  2904. IN SID *pSid,
  2905. OUT RPC_CHAR **ppwsPrincipal
  2906. )
  2907. {
  2908. // Called by InquireAuthClient to convert the SID passed up by the
  2909. // client to a "Domain\User" string. The DG_SCALL cashes the last
  2910. // SID (pCachedSid). If the new SID to convert matches the cashed
  2911. // SID then just return that one (don't have to hit the domain server).
  2912. //
  2913. #define MAX_USERNAME_SIZE 256
  2914. #define MAX_DOMAIN_SIZE 256
  2915. RPC_STATUS Status = RPC_S_OK;
  2916. WCHAR wsName[MAX_USERNAME_SIZE];
  2917. WCHAR wsDomain[MAX_DOMAIN_SIZE];
  2918. DWORD dwNameSize;
  2919. DWORD dwDomainSize;
  2920. DWORD dwSize;
  2921. SID_NAME_USE sidType;
  2922. if ( (pCachedSid) && (pSid)
  2923. && (IsValidSid(pSid)) && (EqualSid(pCachedSid,pSid)) )
  2924. {
  2925. //
  2926. // Great! SIDs match...
  2927. //
  2928. #ifdef DBG
  2929. DbgPrint("DG_SCALL::ConvertSidToUserW(): Cash hit.\n");
  2930. #endif
  2931. *ppwsPrincipal = (RPC_CHAR*)I_RpcAllocate(dwCachedUserNameSize);
  2932. if (*ppwsPrincipal)
  2933. RpcpStringCopy(*ppwsPrincipal,pwsCachedUserName);
  2934. else
  2935. Status = RPC_S_OUT_OF_MEMORY;
  2936. }
  2937. else if ( (pSid) && (IsValidSid(pSid)) )
  2938. {
  2939. dwNameSize = sizeof(wsName);
  2940. dwDomainSize = sizeof(wsDomain);
  2941. if (LookupAccountSidW( NULL,
  2942. pSid,
  2943. wsName,
  2944. &dwNameSize,
  2945. wsDomain,
  2946. &dwDomainSize,
  2947. &sidType) )
  2948. {
  2949. //
  2950. // Got a new SID, remember it for next time.
  2951. //
  2952. *ppwsPrincipal = 0;
  2953. if (pCachedSid)
  2954. {
  2955. I_RpcFree(pCachedSid);
  2956. pCachedSid = 0;
  2957. }
  2958. if (pwsCachedUserName)
  2959. {
  2960. I_RpcFree(pwsCachedUserName);
  2961. pwsCachedUserName = 0;
  2962. }
  2963. dwCachedUserNameSize = 0;
  2964. dwSize = GetLengthSid(pSid);
  2965. pCachedSid = (SID*)I_RpcAllocate(dwSize);
  2966. if (pCachedSid == 0)
  2967. {
  2968. return RPC_S_OUT_OF_MEMORY;
  2969. }
  2970. if (!CopySid(dwSize,pCachedSid,pSid))
  2971. {
  2972. return RPC_S_OUT_OF_MEMORY;
  2973. }
  2974. dwSize = sizeof(RPC_CHAR) * (2 + wcslen(wsName) + wcslen(wsDomain));
  2975. pwsCachedUserName = (RPC_CHAR*)I_RpcAllocate(dwSize);
  2976. if (pwsCachedUserName == 0)
  2977. {
  2978. return RPC_S_OUT_OF_MEMORY;
  2979. }
  2980. RpcpStringCopy(pwsCachedUserName,wsDomain);
  2981. RpcpStringCat(pwsCachedUserName,RPC_CONST_STRING("\\"));
  2982. RpcpStringCat(pwsCachedUserName,wsName);
  2983. *ppwsPrincipal = (RPC_CHAR*)I_RpcAllocate(dwSize);
  2984. if (*ppwsPrincipal)
  2985. {
  2986. RpcpStringCopy(*ppwsPrincipal,pwsCachedUserName);
  2987. dwCachedUserNameSize = dwSize;
  2988. }
  2989. else
  2990. {
  2991. I_RpcFree(pCachedSid);
  2992. pCachedSid = 0;
  2993. dwCachedUserNameSize = 0;
  2994. Status = RPC_S_OUT_OF_MEMORY;
  2995. }
  2996. }
  2997. else
  2998. {
  2999. //
  3000. // LookupAccountSidW() failed. Lookup its error and return.
  3001. //
  3002. Status = GetLastError();
  3003. *ppwsPrincipal = 0;
  3004. }
  3005. }
  3006. else
  3007. {
  3008. #ifdef DBG
  3009. DbgPrint("DG_SCALL::ConvertSidToUserW(): No SID to convert.\n");
  3010. #endif
  3011. *ppwsPrincipal = 0;
  3012. }
  3013. return Status;
  3014. }
  3015. DG_SCALL *
  3016. DG_SCONNECTION::RemoveIdleCalls(
  3017. DG_SCALL * List,
  3018. BOOL Aggressive,
  3019. RPC_INTERFACE * Interface
  3020. )
  3021. {
  3022. if (TRUE == Mutex.TryRequest())
  3023. {
  3024. if (BlockIdleCallRemoval)
  3025. {
  3026. Mutex.Clear();
  3027. return 0;
  3028. }
  3029. long CurrentTime = GetTickCount();
  3030. PDG_SCALL Node = 0;
  3031. if (CachedCalls)
  3032. {
  3033. for (Node = CachedCalls->Next; Node; Node = Node->Next)
  3034. {
  3035. ASSERT( !Node->InvalidHandle(DG_SCALL_TYPE) );
  3036. ASSERT(Node->TimeStamp != 0x31415926);
  3037. if (CurrentTime - Node->TimeStamp > IDLE_SCALL_LIFETIME)
  3038. {
  3039. break;
  3040. }
  3041. }
  3042. }
  3043. ActiveCalls.RemoveIdleCalls(Aggressive, Interface);
  3044. if (Node)
  3045. {
  3046. PDG_SCALL Next = Node->Next;
  3047. Node->Next = 0;
  3048. Node = Next;
  3049. }
  3050. Mutex.Clear();
  3051. while (Node)
  3052. {
  3053. ASSERT( !Node->InvalidHandle(DG_SCALL_TYPE) );
  3054. ASSERT(Node->TimeStamp != 0x31415926);
  3055. PDG_SCALL Next = Node->Next;
  3056. Node->Next = List;
  3057. List = Node;
  3058. Node = Next;
  3059. }
  3060. }
  3061. return List;
  3062. }
  3063. BOOL
  3064. DG_SCONNECTION::HasExpired()
  3065. {
  3066. if (GetTickCount() - TimeStamp > FIVE_MINUTES_IN_MSEC &&
  3067. 0 == ReferenceCount)
  3068. {
  3069. CLAIM_MUTEX Lock(Mutex);
  3070. if (GetTickCount() - TimeStamp > FIVE_MINUTES_IN_MSEC &&
  3071. 0 == ReferenceCount)
  3072. {
  3073. return TRUE;
  3074. }
  3075. }
  3076. return FALSE;
  3077. }
  3078. BOOL
  3079. DG_SCALL::HasExpired(
  3080. BOOL Aggressive,
  3081. RPC_INTERFACE * ExpiringInterface
  3082. )
  3083. {
  3084. long CurrentTime = CurrentTimeInMsec();
  3085. if (CurrentTime - TimeStamp < 40 * 1000 )
  3086. {
  3087. return FALSE;
  3088. }
  3089. AsyncStatus = RPC_S_CALL_FAILED;
  3090. if (PipeWaitType != PWT_NONE)
  3091. {
  3092. #ifdef DEBUGRPC
  3093. DbgPrint("RPC DG: aborting an abandoned pipe operation on %x\n", this);
  3094. #endif
  3095. FinishSendOrReceive(TRUE);
  3096. }
  3097. else if (State == CallDispatched ||
  3098. State == CallAfterDispatch )
  3099. {
  3100. #ifdef DEBUGRPC
  3101. DbgPrint("RPC DG: possible blockage: scall %lx has been dispatched for %u seconds\n",
  3102. this, (CurrentTime - TimeStamp)/1000 );
  3103. #endif
  3104. return FALSE;
  3105. }
  3106. return Cleanup();
  3107. }
  3108. PDG_SCONNECTION
  3109. SERVER_ACTIVITY_TABLE::FindOrCreate(
  3110. DG_ADDRESS * Address,
  3111. DG_PACKET * Packet
  3112. )
  3113. /*++
  3114. Routine Description:
  3115. Looks for connection matching the packet's activity uuid. If the activity
  3116. hint is not 0xffff, we search in that hash bucket, otherwise we create
  3117. a hash value and look there.
  3118. If a connection is found or created, its mutex is taken.
  3119. Arguments:
  3120. pPacket - data to find call (activity uuid and activity hint)
  3121. Return Value:
  3122. the new call, or zero
  3123. --*/
  3124. {
  3125. unsigned Hash = Packet->Header.ActivityHint;
  3126. if (Hash == 0xffff)
  3127. {
  3128. Hash = MakeHash(&Packet->Header.ActivityId);
  3129. }
  3130. //
  3131. // This can happen only if someone is sending garbage.
  3132. //
  3133. if (Hash >= BUCKET_COUNT)
  3134. {
  3135. return 0;
  3136. }
  3137. RequestHashMutex(Hash);
  3138. PDG_SCONNECTION Connection = 0;
  3139. UUID_HASH_TABLE_NODE * pNode = UUID_HASH_TABLE::Lookup(
  3140. &Packet->Header.ActivityId,
  3141. Hash
  3142. );
  3143. if (pNode)
  3144. {
  3145. Connection = DG_SCONNECTION::FromHashNode(pNode);
  3146. if (FALSE == Connection->Mutex.TryRequest())
  3147. {
  3148. Connection->TimeStamp = GetTickCount();
  3149. ReleaseHashMutex(Hash);
  3150. // If the connection is busy more than five minutes,
  3151. // then the connection will go away and this will crash.
  3152. //
  3153. Connection->Mutex.Request();
  3154. }
  3155. else
  3156. {
  3157. ReleaseHashMutex(Hash);
  3158. }
  3159. }
  3160. else if (Packet->Header.PacketType == DG_REQUEST)
  3161. {
  3162. if ((Packet->Header.PacketFlags & DG_PF_FORWARDED) &&
  3163. (Packet->Header.PacketFlags2 & DG_PF2_FORWARDED_2) == 0)
  3164. {
  3165. //
  3166. // This packet doesn't have correct auth info. We can't
  3167. // instantiate a connection without it.
  3168. //
  3169. }
  3170. else
  3171. {
  3172. Connection = Address->AllocateConnection();
  3173. if (Connection)
  3174. {
  3175. ServerConnections->BeginIdlePruning();
  3176. Connection->Activate(&Packet->Header, (unsigned short) Hash);
  3177. Connection->Mutex.Request();
  3178. UUID_HASH_TABLE::Add(&Connection->ActivityNode, Hash);
  3179. }
  3180. }
  3181. ReleaseHashMutex(Hash);
  3182. }
  3183. else
  3184. {
  3185. ReleaseHashMutex(Hash);
  3186. }
  3187. return Connection;
  3188. }
  3189. void SERVER_ACTIVITY_TABLE::Prune()
  3190. /*++
  3191. Routine Description:
  3192. Remove idle connections and calls from the activity table.
  3193. Each call to this fn cleans one bucket.
  3194. --*/
  3195. {
  3196. unsigned Bucket;
  3197. long CurrentTime = GetTickCount();
  3198. //
  3199. // Don't check the whole table too often.
  3200. //
  3201. if (CurrentTime - LastFinishTime < IDLE_SCONNECTION_SWEEP_INTERVAL)
  3202. {
  3203. return;
  3204. }
  3205. Bucket = InterlockedIncrement(&BucketCounter) % BUCKET_COUNT;
  3206. PruneSpecificBucket(Bucket, FALSE, 0);
  3207. if (Bucket == BUCKET_COUNT-1)
  3208. {
  3209. LastFinishTime = CurrentTime;
  3210. }
  3211. }
  3212. void
  3213. SERVER_ACTIVITY_TABLE::BeginIdlePruning()
  3214. {
  3215. if (!fPruning)
  3216. {
  3217. if (InterlockedIncrement(&fPruning) > 1)
  3218. {
  3219. InterlockedDecrement(&fPruning);
  3220. return;
  3221. }
  3222. IdleScavengerTimer.Initialize( PruneWhileIdle, 0 );
  3223. DelayedProcedures->Add(&IdleScavengerTimer, IDLE_SCONNECTION_SWEEP_INTERVAL, FALSE);
  3224. }
  3225. }
  3226. void
  3227. SERVER_ACTIVITY_TABLE::PruneWhileIdle( PVOID unused )
  3228. {
  3229. if (GetTickCount() - ServerConnections->LastFinishTime > IDLE_SCONNECTION_SWEEP_INTERVAL)
  3230. {
  3231. BOOL fEmpty = ServerConnections->PruneEntireTable( 0 );
  3232. if (fEmpty)
  3233. {
  3234. InterlockedDecrement(&fPruning);
  3235. return;
  3236. }
  3237. }
  3238. DelayedProcedures->Add(&ServerConnections->IdleScavengerTimer, IDLE_SCONNECTION_SWEEP_INTERVAL+5000, FALSE);
  3239. }
  3240. BOOL
  3241. SERVER_ACTIVITY_TABLE::PruneEntireTable(
  3242. RPC_INTERFACE * Interface
  3243. )
  3244. {
  3245. BOOL Empty = TRUE;
  3246. unsigned Bucket;
  3247. //
  3248. // Make sure this thread has an associated THREAD.
  3249. // This won't be true for the RpcServerListen thread.
  3250. //
  3251. ThreadSelf();
  3252. for (Bucket = 0; Bucket < BUCKET_COUNT; ++Bucket)
  3253. {
  3254. Empty &= PruneSpecificBucket( Bucket, TRUE, Interface );
  3255. }
  3256. LastFinishTime = GetTickCount();
  3257. return Empty;
  3258. }
  3259. BOOL
  3260. SERVER_ACTIVITY_TABLE::PruneSpecificBucket(
  3261. unsigned Bucket,
  3262. BOOL Aggressive,
  3263. RPC_INTERFACE * Interface
  3264. )
  3265. {
  3266. if (!Buckets[Bucket])
  3267. {
  3268. return TRUE;
  3269. }
  3270. //
  3271. // Scan the bucket for idle calls and connections.
  3272. // Remove them from the table, but don't delete them.
  3273. //
  3274. DG_SCALL * IdleCalls = 0;
  3275. UUID_HASH_TABLE_NODE * pNode;
  3276. UUID_HASH_TABLE_NODE * IdleConnections = 0;
  3277. unsigned Inactive = 0;
  3278. RequestHashMutex(Bucket);
  3279. pNode = Buckets[Bucket];
  3280. while (pNode)
  3281. {
  3282. UUID_HASH_TABLE_NODE * pNext = pNode->pNext;
  3283. DG_SCONNECTION * Connection = DG_SCONNECTION::FromHashNode(pNode);
  3284. IdleCalls = Connection->RemoveIdleCalls( IdleCalls, Aggressive, Interface );
  3285. if (Connection->HasExpired())
  3286. {
  3287. UUID_HASH_TABLE::Remove(pNode, Bucket);
  3288. pNode->pNext = IdleConnections;
  3289. IdleConnections = pNode;
  3290. }
  3291. pNode = pNext;
  3292. }
  3293. BOOL Empty = TRUE;
  3294. if (Buckets[Bucket])
  3295. {
  3296. Empty = FALSE;
  3297. }
  3298. ReleaseHashMutex(Bucket);
  3299. //
  3300. // Now delete the idle objects.
  3301. //
  3302. while (IdleCalls)
  3303. {
  3304. ++Inactive;
  3305. DG_SCALL * Call = IdleCalls;
  3306. IdleCalls = Call->Next;
  3307. delete Call;
  3308. }
  3309. while (IdleConnections)
  3310. {
  3311. DG_SCONNECTION * Connection = DG_SCONNECTION::FromHashNode(IdleConnections);
  3312. IdleConnections = IdleConnections->pNext;
  3313. Connection->Deactivate();
  3314. }
  3315. LogEvent(SU_STABLE, EV_PRUNE, IntToPtr(Bucket), 0, Inactive);
  3316. return Empty;
  3317. }
  3318. ASSOCIATION_GROUP *
  3319. ASSOC_GROUP_TABLE::FindOrCreate(
  3320. RPC_UUID * pUuid,
  3321. unsigned short InitialPduSize
  3322. )
  3323. /*++
  3324. Routine Description:
  3325. Looks for an association group with the given UUID.
  3326. If one is not found then a new one is created.
  3327. Arguments:
  3328. pUuid - CAS uuid to find or create
  3329. Return Value:
  3330. ptr to the association group if found or created
  3331. zero if not found and a new one could not be created
  3332. --*/
  3333. {
  3334. ASSOCIATION_GROUP * pGroup;
  3335. unsigned Hash = MakeHash(pUuid);
  3336. RequestHashMutex(Hash);
  3337. UUID_HASH_TABLE_NODE * pNode = UUID_HASH_TABLE::Lookup(pUuid, Hash);
  3338. if (pNode)
  3339. {
  3340. ASSOCIATION_GROUP::ContainingRecord(pNode)->IncrementRefCount();
  3341. }
  3342. else
  3343. {
  3344. RPC_STATUS Status = RPC_S_OK;
  3345. pGroup = new ASSOCIATION_GROUP(pUuid, InitialPduSize, &Status);
  3346. if (!pGroup || Status != RPC_S_OK)
  3347. {
  3348. delete pGroup;
  3349. pGroup = 0;
  3350. }
  3351. else
  3352. {
  3353. pNode = &pGroup->Node;
  3354. UUID_HASH_TABLE::Add(pNode, Hash);
  3355. }
  3356. }
  3357. ReleaseHashMutex(Hash);
  3358. if (pNode)
  3359. {
  3360. return ASSOCIATION_GROUP::ContainingRecord(pNode);
  3361. }
  3362. else
  3363. {
  3364. return 0;
  3365. }
  3366. }
  3367. void
  3368. ASSOC_GROUP_TABLE::DecrementRefCount(
  3369. ASSOCIATION_GROUP * pClient
  3370. )
  3371. {
  3372. UUID_HASH_TABLE_NODE * pNode = &pClient->Node;
  3373. unsigned Hash = MakeHash(&pNode->Uuid);
  3374. RequestHashMutex(Hash);
  3375. pClient->RequestMutex();
  3376. if (0 == pClient->DecrementRefCount())
  3377. {
  3378. UUID_HASH_TABLE::Remove(pNode, Hash);
  3379. delete pClient;
  3380. }
  3381. else
  3382. {
  3383. pClient->ClearMutex();
  3384. }
  3385. ReleaseHashMutex(Hash);
  3386. }
  3387. inline RPC_STATUS
  3388. DG_SCONNECTION::CreateCallbackBindingAndReleaseMutex(
  3389. DG_TRANSPORT_ADDRESS RemoteAddress
  3390. )
  3391. {
  3392. RPC_STATUS Status;
  3393. RPC_CHAR * StringBinding;
  3394. RPC_CHAR * Address;
  3395. RPC_CHAR * Endpoint;
  3396. unsigned Length;
  3397. unsigned AddressLength;
  3398. unsigned EndpointLength;
  3399. unsigned ProtocolLength;
  3400. Callback.Binding = 0;
  3401. Address = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * pAddress->Endpoint.TransportInterface->AddressStringSize);
  3402. Endpoint = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) * pAddress->Endpoint.TransportInterface->EndpointStringSize);
  3403. if (!Address || !Endpoint)
  3404. {
  3405. Mutex.Clear();
  3406. return RPC_S_OUT_OF_MEMORY;
  3407. }
  3408. Status = pAddress->Endpoint.TransportInterface->QueryAddress(RemoteAddress, Address);
  3409. if ( Status != RPC_S_OK )
  3410. {
  3411. Mutex.Clear();
  3412. return Status;
  3413. }
  3414. Status = pAddress->Endpoint.TransportInterface->QueryEndpoint(RemoteAddress, Endpoint);
  3415. if ( Status != RPC_S_OK )
  3416. {
  3417. Mutex.Clear();
  3418. return Status;
  3419. }
  3420. ProtocolLength = StringLengthWithEscape(pAddress->InqRpcProtocolSequence());
  3421. AddressLength = StringLengthWithEscape(Address);
  3422. EndpointLength = StringLengthWithEscape(Endpoint);
  3423. StringBinding = (RPC_CHAR *) _alloca(sizeof(RPC_CHAR) *
  3424. ( ProtocolLength
  3425. + 1
  3426. + AddressLength
  3427. + 1
  3428. + EndpointLength
  3429. + 1
  3430. + 1
  3431. ));
  3432. if (!StringBinding)
  3433. {
  3434. Mutex.Clear();
  3435. return RPC_S_OUT_OF_MEMORY;
  3436. }
  3437. StringCopyEscapeCharacters(StringBinding, pAddress->InqRpcProtocolSequence());
  3438. Length = ProtocolLength;
  3439. StringBinding[Length++] = RPC_CONST_CHAR(':');
  3440. StringCopyEscapeCharacters(StringBinding + Length, Address);
  3441. Length += AddressLength;
  3442. StringBinding[Length++] = RPC_CONST_CHAR('[');
  3443. StringCopyEscapeCharacters(StringBinding + Length, Endpoint);
  3444. Length += EndpointLength;
  3445. StringBinding[Length++] = RPC_CONST_CHAR(']');
  3446. StringBinding[Length] = 0;
  3447. //
  3448. // We are entering the expensive phase of the callback. Let's release
  3449. // the call mutex so that other threads can respond to client PINGs etc.
  3450. //
  3451. IncrementRefCount();
  3452. Mutex.Clear();
  3453. pAddress->CheckThreadPool();
  3454. //
  3455. // Create a binding handle to the client endpoint. It's important to do it
  3456. // outside the call mutex because it causes a lot of memory allocation.
  3457. //
  3458. Status = RpcBindingFromStringBinding(StringBinding, &Callback.Binding);
  3459. return Status;
  3460. }
  3461. inline void
  3462. DG_SCONNECTION::SubmitCallbackIfNecessary(
  3463. PDG_SCALL Call,
  3464. PDG_PACKET Packet,
  3465. DG_TRANSPORT_ADDRESS RemoteAddress
  3466. )
  3467. /*++
  3468. Routine Description:
  3469. doc:callback
  3470. This function determines whether the server should issue a conv callback
  3471. to the client, and submits an async call if so.
  3472. - The first non-idempotent call on a given activity ID requires a callback
  3473. in order to guarantee the call wasn't executed by a prior server
  3474. instance. If the activity stays quiet for 5 minutes and the
  3475. DG_SCONNECTION is thrown away, the next call will force another callback.
  3476. - Each security context requires a callback; this allows the cleint to
  3477. transfer the session key securely to the server.
  3478. In NT 5.0 beta 1:
  3479. This function submits callbacks from the 'msconv' interface because that
  3480. notifies an NT5 or better client that the server supports the
  3481. DG_PF2_UNRELATED bit to overlap calls.
  3482. In NT 5 beta 2:
  3483. The callback request is sent with the DG_PF2_UNRELATED bit set, even
  3484. though it doesn'nt need to be set. That tells teh client that overlapped
  3485. calls are OK.
  3486. If ms_conv_who_are_you_auth fails, the server will try conv_who_are_you_auth.
  3487. If ms_conv_who_are_you2 fails, the server will try conv_who_are_you2, which
  3488. is supported by NT 3.51 and NT 4.0, as well as all current DCE systems;
  3489. if that fails, we try conv_who_are_you which is all that NT 3.5 and the old
  3490. UNIX NCA servers support. I doubt that we have ever tested interop with NCA...
  3491. A connection is allowed only a single oustanding callback at a time. This
  3492. should not be a significant restriction.
  3493. The rule is that a thread must hold the connection mutex if it wants to
  3494. change Callback.State from NoCallbackAttempted to any other value. It can
  3495. then release the mutex and party on the other members of Callback, since
  3496. all other instances of this procedure will exit immediately
  3497. if Callback.State != NoCallbackAttempted.
  3498. In a nutshell, this function
  3499. - creates a binding handle to the client,
  3500. - releases the connection mutex,
  3501. - fills Callback.* with the info needed by FinishConvCallback(), and
  3502. - calls an conv or msconv stub
  3503. When the async call is complete (or fails), some thread will call
  3504. ConvNotificationRoutine() which will either submit another async call
  3505. or call FinishConvCallback() to mop up. For a successful secure callback,
  3506. FinishConvCallback() will also call AcceptThirdLeg and then set
  3507. ActiveSeurityContext to be the newly created context. For a failed
  3508. callback, FinishConvCallback will notify the DG_SCALL that started
  3509. all this, so it can send a REJECT to the client.
  3510. A wrinkle is that two objects need access to Packet: the DG_SCALL
  3511. is using it as [in] stub data, and this fn uses it for AcceptFirstTime.
  3512. So future code shuffling needs to make sure the call doesn't die during
  3513. a callback, and that the call doesn't delete the packet until
  3514. AcceptFirstTime is complete.
  3515. --*/
  3516. {
  3517. RPC_STATUS Status = RPC_S_OK;
  3518. //
  3519. // Has a callback already been attempted?
  3520. //
  3521. if (Callback.State != NoCallbackAttempted)
  3522. {
  3523. return;
  3524. }
  3525. //
  3526. // Is a callback unnecessary?
  3527. //
  3528. DG_SECURITY_TRAILER * Verifier = (DG_SECURITY_TRAILER *)
  3529. (Packet->Header.Data + Packet->GetPacketBodyLen());
  3530. unsigned char KeySequenceNumber = Verifier->key_vers_num;
  3531. if (Packet->Header.AuthProto == 0)
  3532. {
  3533. if (pAssocGroup ||
  3534. (Packet->Header.PacketFlags & DG_PF_IDEMPOTENT))
  3535. {
  3536. return;
  3537. }
  3538. }
  3539. else
  3540. {
  3541. //
  3542. // See if we have already established a security context
  3543. // for this client.
  3544. //
  3545. SECURITY_CONTEXT * CurrentContext = SecurityContextDict.Find(KeySequenceNumber);
  3546. if (CurrentContext)
  3547. {
  3548. return;
  3549. }
  3550. }
  3551. //
  3552. // A callback is needed.
  3553. //
  3554. Callback.State = SetupInProgress;
  3555. Callback.Call = Call;
  3556. Callback.Binding = 0;
  3557. Callback.Credentials = 0;
  3558. Callback.TokenBuffer = 0;
  3559. Callback.ResponseBuffer = 0;
  3560. Callback.SecurityContext = 0;
  3561. Callback.ThirdLegNeeded = FALSE;
  3562. Callback.DataRep = 0x00ffffff & (*(unsigned long *) Packet->Header.DataRep);
  3563. Callback.KeySequence = KeySequenceNumber;
  3564. Callback.Call->IncrementRefCount();
  3565. Status = CreateCallbackBindingAndReleaseMutex( RemoteAddress );
  3566. if (Status)
  3567. {
  3568. FinishConvCallback(Status);
  3569. return;
  3570. }
  3571. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  3572. if (Status)
  3573. {
  3574. FinishConvCallback(Status);
  3575. return;
  3576. }
  3577. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  3578. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  3579. Callback.AsyncState.UserInfo = this;
  3580. if (Packet->Header.AuthProto)
  3581. {
  3582. unsigned long AuthenticationService = Packet->Header.AuthProto;
  3583. unsigned long AuthenticationLevel = Verifier->protection_level;
  3584. //
  3585. // OSF clients sometimes send these levels.
  3586. //
  3587. if (AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT ||
  3588. AuthenticationLevel == RPC_C_AUTHN_LEVEL_CALL)
  3589. {
  3590. AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT;
  3591. }
  3592. //
  3593. // Create an empty security context.
  3594. //
  3595. CLIENT_AUTH_INFO Info;
  3596. Info.AuthenticationService = AuthenticationService;
  3597. Info.AuthenticationLevel = AuthenticationLevel;
  3598. Info.ServerPrincipalName = 0;
  3599. Info.PacHandle = 0;
  3600. Info.AuthorizationService= 0;
  3601. Callback.SecurityContext = new SECURITY_CONTEXT(&Info, KeySequenceNumber, TRUE, &Status);
  3602. if (!Callback.SecurityContext)
  3603. {
  3604. Status = RPC_S_OUT_OF_MEMORY;
  3605. }
  3606. CallTestHook( TH_RPC_SECURITY_SERVER_CONTEXT_CREATED, Callback.SecurityContext, this );
  3607. if (Status)
  3608. {
  3609. FinishConvCallback(Status);
  3610. return;
  3611. }
  3612. //
  3613. // Get my security credentials.
  3614. //
  3615. Status = pAddress->Server->AcquireCredentials(
  3616. AuthenticationService,
  3617. AuthenticationLevel,
  3618. &Callback.Credentials
  3619. );
  3620. if (Status)
  3621. {
  3622. LogError(SU_SCONN, EV_STATUS, this, (void *) 100, Status );
  3623. FinishConvCallback(Status);
  3624. return;
  3625. }
  3626. //
  3627. // Allocate challenge and response buffers.
  3628. //
  3629. Callback.TokenLength = Callback.Credentials->MaximumTokenLength();
  3630. Callback.TokenBuffer = new unsigned char [2 * Callback.TokenLength];
  3631. Callback.ResponseBuffer = Callback.TokenBuffer + Callback.TokenLength;
  3632. if (!Callback.TokenBuffer)
  3633. {
  3634. FinishConvCallback(RPC_S_OUT_OF_MEMORY);
  3635. return;
  3636. }
  3637. //
  3638. // Get a skeletal context and a challenge from the security package.
  3639. //
  3640. DCE_INIT_SECURITY_INFO DceInitSecurityInfo;
  3641. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  3642. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  3643. SECURITY_BUFFER InputBuffers[4];
  3644. SECURITY_BUFFER OutputBuffers[4];
  3645. DCE_INIT_SECURITY_INFO InitSecurityInfo;
  3646. InputBufferDescriptor.ulVersion = 0;
  3647. InputBufferDescriptor.cBuffers = 4;
  3648. InputBufferDescriptor.pBuffers = InputBuffers;
  3649. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3650. InputBuffers[0].pvBuffer = &Packet->Header;
  3651. InputBuffers[0].cbBuffer = sizeof(NCA_PACKET_HEADER);
  3652. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3653. InputBuffers[1].pvBuffer = Packet->Header.Data;
  3654. InputBuffers[1].cbBuffer = Packet->GetPacketBodyLen();
  3655. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3656. InputBuffers[2].pvBuffer = Verifier;
  3657. InputBuffers[2].cbBuffer = sizeof(DG_SECURITY_TRAILER);
  3658. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3659. InputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3660. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3661. OutputBufferDescriptor.ulVersion = 0;
  3662. OutputBufferDescriptor.cBuffers = 4;
  3663. OutputBufferDescriptor.pBuffers = OutputBuffers;
  3664. OutputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3665. OutputBuffers[0].pvBuffer = 0;
  3666. OutputBuffers[0].cbBuffer = 0;
  3667. OutputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3668. OutputBuffers[1].pvBuffer = 0;
  3669. OutputBuffers[1].cbBuffer = 0;
  3670. OutputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3671. OutputBuffers[2].pvBuffer = Callback.TokenBuffer;
  3672. OutputBuffers[2].cbBuffer = Callback.TokenLength;
  3673. OutputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3674. OutputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3675. OutputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3676. DceInitSecurityInfo.PacketType = ~0;
  3677. DceInitSecurityInfo.AuthorizationService = ~0;
  3678. DceInitSecurityInfo.DceSecurityInfo.SendSequenceNumber = ~0;
  3679. DceInitSecurityInfo.DceSecurityInfo.ReceiveSequenceNumber = KeySequenceNumber;
  3680. DceInitSecurityInfo.DceSecurityInfo.AssociationUuid = Packet->Header.ActivityId;
  3681. Status = Callback.SecurityContext->AcceptFirstTime(
  3682. Callback.Credentials,
  3683. &InputBufferDescriptor,
  3684. &OutputBufferDescriptor,
  3685. AuthenticationLevel,
  3686. Callback.DataRep,
  3687. FALSE
  3688. );
  3689. LogEvent( SU_SCONN, EV_SEC_ACCEPT1, this, IntToPtr(Status), I_RpcGetExtendedError());
  3690. switch (Status)
  3691. {
  3692. case RPC_S_OK:
  3693. {
  3694. break;
  3695. }
  3696. case RPC_P_CONTINUE_NEEDED:
  3697. {
  3698. Callback.ThirdLegNeeded = TRUE;
  3699. break;
  3700. }
  3701. case RPC_P_COMPLETE_NEEDED:
  3702. {
  3703. #ifdef DEBUGRPC
  3704. DbgPrint("RPC: dg does not support RPC_P_COMPLETE_NEEDED from AcceptSecurityContext\n");
  3705. #endif
  3706. break;
  3707. }
  3708. case RPC_P_COMPLETE_AND_CONTINUE:
  3709. {
  3710. Callback.ThirdLegNeeded = TRUE;
  3711. #ifdef DEBUGRPC
  3712. DbgPrint("RPC: dg does not support RPC_P_COMPLETE_AND_CONTINUE from AcceptSecurityContext\n");
  3713. #endif
  3714. break;
  3715. }
  3716. default:
  3717. {
  3718. LogError( SU_SCONN, EV_SEC_ACCEPT1, this, IntToPtr(Status), I_RpcGetExtendedError());
  3719. FinishConvCallback(Status);
  3720. return;
  3721. }
  3722. }
  3723. Callback.TokenLength = OutputBuffers[2].cbBuffer;
  3724. Callback.State = ConvWayAuthInProgress;
  3725. Callback.DataIndex = 0;
  3726. Callback.Status = 0;
  3727. _conv_who_are_you_auth(
  3728. &Callback.AsyncState,
  3729. Callback.Binding,
  3730. (UUID *) &ActivityNode.Uuid,
  3731. ProcessStartTime,
  3732. Callback.TokenBuffer,
  3733. Callback.TokenLength,
  3734. Callback.Credentials->MaximumTokenLength(),
  3735. &Callback.ClientSequence,
  3736. &Callback.CasUuid,
  3737. Callback.ResponseBuffer,
  3738. &Callback.ResponseLength,
  3739. &Callback.Status
  3740. );
  3741. //
  3742. // We have to take the mutex before leaving this fn, regardless of error.
  3743. // Do it here so the check of Callback.State is protected.
  3744. //
  3745. Mutex.Request();
  3746. //
  3747. // If there is an error, see whether it is caused a notification. If so,
  3748. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  3749. // If the state is unchanged, this thread must clean up.
  3750. //
  3751. if (Callback.Status && Callback.State == ConvWayAuthInProgress)
  3752. {
  3753. FinishConvCallback(Callback.Status);
  3754. //
  3755. // The mutex was recursively claimed by FinishConvCallback().
  3756. // Get rid of the recursive one.
  3757. //
  3758. Mutex.Clear();
  3759. }
  3760. }
  3761. else
  3762. {
  3763. BlockIdleCallRemoval = FALSE;
  3764. Callback.State = ConvWay2InProgress;
  3765. Callback.Status = 0;
  3766. _conv_who_are_you2(
  3767. &Callback.AsyncState,
  3768. Callback.Binding,
  3769. (UUID *) &ActivityNode.Uuid,
  3770. ProcessStartTime,
  3771. &Callback.ClientSequence,
  3772. &Callback.CasUuid,
  3773. &Callback.Status
  3774. );
  3775. //
  3776. // We have to take the mutex before leaving this fn, regardless of error.
  3777. // Do it here so the check of Callback.State is protected.
  3778. //
  3779. Mutex.Request();
  3780. //
  3781. // If there is an error, see whether it is caused a notification. If so,
  3782. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  3783. // If the state is unchanged, this thread must clean up.
  3784. //
  3785. if (Callback.Status && Callback.State == ConvWay2InProgress)
  3786. {
  3787. FinishConvCallback(Callback.Status);
  3788. //
  3789. // The mutex was recursively claimed by FinishConvCallback().
  3790. // Get rid of the recursive one.
  3791. //
  3792. Mutex.Clear();
  3793. }
  3794. }
  3795. Mutex.VerifyOwned();
  3796. }
  3797. RPC_STATUS
  3798. DG_SCONNECTION::FinishConvCallback(
  3799. RPC_STATUS Status
  3800. )
  3801. {
  3802. BlockIdleCallRemoval = FALSE;
  3803. if (!Status && Callback.ThirdLegNeeded )
  3804. {
  3805. #ifdef TRY_MSCONV_INTERFACE
  3806. ASSERT( Callback.State == ConvWayAuthInProgress ||
  3807. Callback.State == MsConvWayAuthInProgress );
  3808. #else
  3809. ASSERT( Callback.State == ConvWayAuthInProgress ||
  3810. Callback.State == ConvWayAuthMoreInProgress );
  3811. #endif
  3812. //
  3813. // Give the challenge response to the security package.
  3814. //
  3815. DCE_INIT_SECURITY_INFO DceInitSecurityInfo;
  3816. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  3817. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  3818. SECURITY_BUFFER InputBuffers[4];
  3819. SECURITY_BUFFER OutputBuffers[4];
  3820. InputBufferDescriptor.ulVersion = 0;
  3821. InputBufferDescriptor.cBuffers = 4;
  3822. InputBufferDescriptor.pBuffers = InputBuffers;
  3823. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3824. InputBuffers[0].pvBuffer = 0;
  3825. InputBuffers[0].cbBuffer = 0;
  3826. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  3827. InputBuffers[1].pvBuffer = 0;
  3828. InputBuffers[1].cbBuffer = 0;
  3829. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3830. InputBuffers[2].pvBuffer = Callback.ResponseBuffer;
  3831. InputBuffers[2].cbBuffer = Callback.DataIndex;
  3832. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3833. InputBuffers[3].pvBuffer = &DceInitSecurityInfo;
  3834. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3835. DceInitSecurityInfo.PacketType = ~0;
  3836. DceInitSecurityInfo.AuthorizationService = ~0;
  3837. DceInitSecurityInfo.DceSecurityInfo.SendSequenceNumber = ~0;
  3838. DceInitSecurityInfo.DceSecurityInfo.ReceiveSequenceNumber = Callback.KeySequence;
  3839. DceInitSecurityInfo.DceSecurityInfo.AssociationUuid = ActivityNode.Uuid;
  3840. OutputBufferDescriptor.ulVersion = 0;
  3841. OutputBufferDescriptor.cBuffers = 0;
  3842. OutputBufferDescriptor.pBuffers = 0;
  3843. Status = Callback.SecurityContext->AcceptThirdLeg(
  3844. Callback.DataRep,
  3845. &InputBufferDescriptor,
  3846. &OutputBufferDescriptor
  3847. );
  3848. LogEvent( SU_SCONN, EV_SEC_ACCEPT3, this, IntToPtr(Status), I_RpcGetExtendedError());
  3849. }
  3850. if (Callback.Binding)
  3851. {
  3852. RpcBindingFree(&Callback.Binding);
  3853. }
  3854. delete Callback.TokenBuffer;
  3855. if (Callback.Credentials)
  3856. {
  3857. Callback.Credentials->DereferenceCredentials();
  3858. }
  3859. if (RPC_S_OK == Status)
  3860. {
  3861. Mutex.Request();
  3862. DecrementRefCount();
  3863. Callback.Call->DecrementRefCount();
  3864. if (0 == pAssocGroup)
  3865. {
  3866. ASSOCIATION_GROUP * Cas;
  3867. Cas = AssociationGroups->FindOrCreate(&Callback.CasUuid,
  3868. (unsigned short) pAddress->Endpoint.TransportInterface->BasePduSize);
  3869. if (0 == Cas)
  3870. {
  3871. // We want to retry later.
  3872. Callback.State = NoCallbackAttempted;
  3873. delete Callback.SecurityContext;
  3874. return RPC_S_OUT_OF_MEMORY;
  3875. }
  3876. pAssocGroup = Cas;
  3877. }
  3878. if (Callback.SecurityContext)
  3879. {
  3880. SecurityContextDict.Insert(
  3881. Callback.SecurityContext->AuthContextId,
  3882. Callback.SecurityContext
  3883. );
  3884. if (MaxKeySeq <= Callback.KeySequence)
  3885. {
  3886. MaxKeySeq = Callback.KeySequence;
  3887. ActiveSecurityContext = Callback.SecurityContext;
  3888. }
  3889. }
  3890. else
  3891. {
  3892. ASSERT( Callback.State != ConvWayAuthInProgress &&
  3893. Callback.State != MsConvWayAuthInProgress );
  3894. }
  3895. if (Callback.ClientSequence == CurrentCall->GetSequenceNumber())
  3896. {
  3897. Callback.State = CallbackSucceeded;
  3898. }
  3899. else
  3900. {
  3901. Callback.State = CallbackFailed;
  3902. Status = RPC_S_CALL_FAILED;
  3903. PDG_SCALL Call = Callback.Call;
  3904. do
  3905. {
  3906. PDG_SCALL Next;
  3907. Next = ActiveCalls.Successor(Call);
  3908. Call->ConvCallbackFailed(Status);
  3909. Call = Next;
  3910. }
  3911. while ( Call );
  3912. }
  3913. }
  3914. else
  3915. {
  3916. LogError( SU_SCONN, EV_SEC_ACCEPT3, this, IntToPtr(Status), I_RpcGetExtendedError());
  3917. delete Callback.SecurityContext;
  3918. Mutex.Request();
  3919. DecrementRefCount();
  3920. if (RPC_S_SERVER_UNAVAILABLE == Status ||
  3921. RPC_S_CALL_FAILED_DNE == Status ||
  3922. RPC_S_CALL_FAILED == Status ||
  3923. RPC_S_PROTOCOL_ERROR == Status)
  3924. {
  3925. Status = NCA_STATUS_WHO_ARE_YOU_FAILED;
  3926. }
  3927. if (Status == RPC_S_OUT_OF_MEMORY ||
  3928. Status == RPC_S_OUT_OF_RESOURCES )
  3929. {
  3930. Callback.State = NoCallbackAttempted;
  3931. }
  3932. else
  3933. {
  3934. Callback.State = CallbackFailed;
  3935. }
  3936. Callback.Call->DecrementRefCount();
  3937. //
  3938. // Map SSPI errors to access-denied. SSPI errors are facility code 0009 (see windows.h),
  3939. // therefore all security errors are of the form 0x8009xxxx. (Again, see wondows.h)
  3940. //
  3941. if (0x80090000UL == (Status & 0xffff0000UL))
  3942. {
  3943. #ifdef DEBUGRPC
  3944. if (Status != SEC_E_NO_IMPERSONATION &&
  3945. Status != SEC_E_UNSUPPORTED_FUNCTION )
  3946. {
  3947. PrintToDebugger("RPC DG: mapping security error %lx to access-denied\n", Status);
  3948. }
  3949. #endif
  3950. Status = RPC_S_SEC_PKG_ERROR;
  3951. }
  3952. PDG_SCALL Call = Callback.Call;
  3953. do
  3954. {
  3955. PDG_SCALL Next;
  3956. Next = ActiveCalls.Successor(Call);
  3957. Call->ConvCallbackFailed(Status);
  3958. Call = Next;
  3959. }
  3960. while ( Call );
  3961. }
  3962. return Status;
  3963. }
  3964. void
  3965. ConvCallCompletedWrapper(
  3966. PVOID Connection
  3967. )
  3968. {
  3969. PDG_SCONNECTION(Connection)->ConvCallCompleted();
  3970. }
  3971. // it's a static procedure
  3972. void RPC_ENTRY
  3973. DG_SCONNECTION::ConvNotificationRoutine (
  3974. RPC_ASYNC_STATE * pAsync,
  3975. void * Reserved,
  3976. RPC_ASYNC_EVENT Event
  3977. )
  3978. {
  3979. //
  3980. // This function is called when the callback completes. The current thread
  3981. // is holding the connection mutex for the callback, so we can't linger
  3982. // in this procedure. The PostEvent call will cause all the expensive
  3983. // operations to occur in a separate thread.
  3984. //
  3985. PDG_SCONNECTION Connection = PDG_SCONNECTION(pAsync->UserInfo);
  3986. ASSERT( Event == RpcCallComplete );
  3987. ASSERT( Connection->Callback.AsyncState.UserInfo == Connection );
  3988. Connection->pAddress->Endpoint.TransportInterface->PostEvent( DG_EVENT_CALLBACK_COMPLETE, Connection);
  3989. }
  3990. void
  3991. DG_SCONNECTION::ConvCallCompleted()
  3992. {
  3993. RPC_STATUS Status;
  3994. //
  3995. // Ensure a thread is listening for new packets. We are in an expensive function.
  3996. //
  3997. pAddress->CheckThreadPool();
  3998. do
  3999. {
  4000. Status = RpcAsyncCompleteCall( &Callback.AsyncState, 0 );
  4001. if (RPC_S_INVALID_ASYNC_CALL != Status)
  4002. {
  4003. break;
  4004. }
  4005. Sleep(10);
  4006. }
  4007. while ( 1 );
  4008. LogEvent(SU_SCONN, EV_STATUS, this, 0, Status);
  4009. ASSERT( Status != RPC_S_INVALID_ASYNC_CALL &&
  4010. Status != RPC_S_INVALID_ASYNC_HANDLE );
  4011. if (!Status)
  4012. {
  4013. if (Callback.Status == ERROR_SHUTDOWN_IN_PROGRESS)
  4014. {
  4015. Callback.Status = RPC_P_CLIENT_SHUTDOWN_IN_PROGRESS;
  4016. }
  4017. Status = Callback.Status;
  4018. LogEvent(SU_SCONN, EV_STATUS, this, 0, Status);
  4019. }
  4020. if (!Status)
  4021. {
  4022. if (Callback.State == ConvWayInProgress)
  4023. {
  4024. Status = UuidCreate((UUID *) &Callback.CasUuid);
  4025. if (Status == RPC_S_UUID_LOCAL_ONLY)
  4026. {
  4027. Status = RPC_S_OK;
  4028. }
  4029. if (Status)
  4030. {
  4031. FinishConvCallback(Status);
  4032. Mutex.Clear();
  4033. return;
  4034. }
  4035. }
  4036. else if (Callback.State == ConvWayAuthInProgress ||
  4037. Callback.State == ConvWayAuthMoreInProgress )
  4038. {
  4039. Callback.DataIndex += Callback.ResponseLength;
  4040. }
  4041. FinishConvCallback(Status);
  4042. CallDispatchLoop();
  4043. Mutex.Clear();
  4044. }
  4045. else switch (Callback.State)
  4046. {
  4047. case ConvWayAuthInProgress:
  4048. case ConvWayAuthMoreInProgress:
  4049. {
  4050. if (RPC_S_SERVER_UNAVAILABLE == Status ||
  4051. RPC_S_CALL_FAILED_DNE == Status ||
  4052. RPC_S_CALL_FAILED == Status ||
  4053. RPC_S_PROTOCOL_ERROR == Status)
  4054. {
  4055. Callback.Status = NCA_STATUS_WHO_ARE_YOU_FAILED;
  4056. }
  4057. Callback.DataIndex += Callback.ResponseLength;
  4058. if (NCA_STATUS_PARTIAL_CREDENTIALS == Status)
  4059. {
  4060. Callback.State = ConvWayAuthMoreInProgress;
  4061. Callback.Status = 0;
  4062. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4063. if (Status)
  4064. {
  4065. FinishConvCallback(Status);
  4066. Mutex.Clear();
  4067. return;
  4068. }
  4069. if (Callback.Credentials->MaximumTokenLength() <= Callback.DataIndex)
  4070. {
  4071. FinishConvCallback(RPC_S_PROTOCOL_ERROR);
  4072. Mutex.Clear();
  4073. return;
  4074. }
  4075. _conv_who_are_you_auth_more(
  4076. &Callback.AsyncState,
  4077. Callback.Binding,
  4078. (UUID *) &ActivityNode.Uuid,
  4079. ProcessStartTime,
  4080. Callback.DataIndex,
  4081. Callback.Credentials->MaximumTokenLength() - Callback.DataIndex,
  4082. Callback.ResponseBuffer + Callback.DataIndex,
  4083. &Callback.ResponseLength,
  4084. &Callback.Status
  4085. );
  4086. //
  4087. // If there is an error, see whether it is caused a notification. If so,
  4088. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4089. // If the state is unchanged, this thread must clean up.
  4090. //
  4091. if (Callback.Status)
  4092. {
  4093. Mutex.Request();
  4094. if (Callback.State == ConvWayAuthMoreInProgress)
  4095. {
  4096. FinishConvCallback(Callback.Status);
  4097. //
  4098. // The mutex was recursively claimed by FinishConvCallback().
  4099. //
  4100. Mutex.Clear();
  4101. Mutex.Clear();
  4102. return;
  4103. }
  4104. else
  4105. {
  4106. Mutex.Clear();
  4107. }
  4108. }
  4109. break;
  4110. }
  4111. FinishConvCallback(Callback.Status);
  4112. Mutex.Clear();
  4113. break;
  4114. }
  4115. case ConvWay2InProgress:
  4116. {
  4117. Callback.State = ConvWayInProgress;
  4118. Callback.Status = 0;
  4119. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4120. if (Status)
  4121. {
  4122. FinishConvCallback(Status);
  4123. Mutex.Clear();
  4124. return;
  4125. }
  4126. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  4127. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  4128. Callback.AsyncState.UserInfo = this;
  4129. _conv_who_are_you(
  4130. &Callback.AsyncState,
  4131. Callback.Binding,
  4132. (UUID *) &ActivityNode.Uuid,
  4133. ProcessStartTime,
  4134. &Callback.ClientSequence,
  4135. &Callback.Status
  4136. );
  4137. //
  4138. // If there is an error, see whether it is caused a notification. If so,
  4139. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4140. // If the state is unchanged, this thread must clean up.
  4141. //
  4142. if (Callback.Status)
  4143. {
  4144. Mutex.Request();
  4145. if (Callback.State == ConvWayInProgress)
  4146. {
  4147. FinishConvCallback(Callback.Status);
  4148. //
  4149. // The mutex was recursively claimed by FinishConvCallback().
  4150. //
  4151. Mutex.Clear();
  4152. Mutex.Clear();
  4153. return;
  4154. }
  4155. else
  4156. {
  4157. Mutex.Clear();
  4158. }
  4159. }
  4160. break;
  4161. }
  4162. case ConvWayInProgress:
  4163. {
  4164. FinishConvCallback(Callback.Status);
  4165. Mutex.Clear();
  4166. break;
  4167. }
  4168. default:
  4169. {
  4170. #ifdef DBG
  4171. DbgPrint("RPC dg: unexpected callback state %x in connection %x\n", Callback.State, this);
  4172. ASSERT( 0 );
  4173. break;
  4174. #endif
  4175. }
  4176. }
  4177. Mutex.VerifyNotOwned();
  4178. }
  4179. RPC_STATUS
  4180. DG_SCONNECTION::GetAssociationGroup(
  4181. DG_TRANSPORT_ADDRESS RemoteAddress
  4182. )
  4183. {
  4184. if (pAssocGroup)
  4185. {
  4186. return RPC_S_OK;
  4187. }
  4188. Mutex.Request();
  4189. if (pAssocGroup)
  4190. {
  4191. Mutex.Clear();
  4192. return RPC_S_OK;
  4193. }
  4194. if (Callback.State == NoCallbackAttempted)
  4195. {
  4196. //
  4197. // A callback is needed.
  4198. //
  4199. RPC_STATUS Status;
  4200. Callback.State = SetupInProgress;
  4201. Callback.Binding = 0;
  4202. Callback.Credentials = 0;
  4203. Callback.TokenBuffer = 0;
  4204. Callback.ResponseBuffer = 0;
  4205. Callback.SecurityContext = 0;
  4206. Callback.ThirdLegNeeded = FALSE;
  4207. Callback.DataRep = 0; // used only by secure c/b
  4208. Callback.KeySequence = 0; // used only by secure c/b
  4209. Callback.Call = (DG_SCALL *) RpcpGetThreadContext();
  4210. if (NULL == Callback.Call)
  4211. {
  4212. Callback.State = CallbackFailed;
  4213. Mutex.Clear();
  4214. return RPC_S_OUT_OF_MEMORY;
  4215. }
  4216. Callback.Call->IncrementRefCount();
  4217. Status = CreateCallbackBindingAndReleaseMutex( RemoteAddress );
  4218. if (Status)
  4219. {
  4220. FinishConvCallback(Status);
  4221. Mutex.Clear();
  4222. return Status;
  4223. }
  4224. Status = RpcAsyncInitializeHandle(&Callback.AsyncState, sizeof(Callback.AsyncState));
  4225. if (Status)
  4226. {
  4227. FinishConvCallback(Status);
  4228. Mutex.Clear();
  4229. return Status;
  4230. }
  4231. Callback.AsyncState.NotificationType = RpcNotificationTypeCallback;
  4232. Callback.AsyncState.u.NotificationRoutine = ConvNotificationRoutine;
  4233. Callback.AsyncState.UserInfo = this;
  4234. //
  4235. // If this were a secure connection, we wouldn't get into the
  4236. // unmarshalling routine w/o a callback, and we would be here now.
  4237. // So use conv_who_are_you2.
  4238. //
  4239. Callback.State = ConvWay2InProgress;
  4240. Callback.Status = 0;
  4241. _conv_who_are_you2(
  4242. &Callback.AsyncState,
  4243. Callback.Binding,
  4244. (UUID *) &ActivityNode.Uuid,
  4245. ProcessStartTime,
  4246. &Callback.ClientSequence,
  4247. &Callback.CasUuid,
  4248. &Callback.Status
  4249. );
  4250. //
  4251. // If there is an error, see whether it is caused a notification. If so,
  4252. // ConvCallCompleted() has changed the callback state and this thread should do nothing.
  4253. // If the state is unchanged, this thread must clean up.
  4254. //
  4255. if (Callback.Status)
  4256. {
  4257. Mutex.Request();
  4258. if (Callback.State == ConvWay2InProgress)
  4259. {
  4260. FinishConvCallback(Callback.Status);
  4261. //
  4262. // The mutex was recursively claimed by FinishConvCallback().
  4263. //
  4264. Mutex.Clear();
  4265. Mutex.Clear();
  4266. return Callback.Status;
  4267. }
  4268. else
  4269. {
  4270. Mutex.Clear();
  4271. }
  4272. }
  4273. }
  4274. else
  4275. {
  4276. Mutex.Clear();
  4277. }
  4278. Mutex.VerifyNotOwned();
  4279. //
  4280. // Wait for the result. This is not quite as efficient as using event notification,
  4281. // but it's a lot simpler, and that's important at this late stage of the ship process.
  4282. //
  4283. while (Callback.State != CallbackSucceeded &&
  4284. Callback.State != CallbackFailed)
  4285. {
  4286. Sleep(500);
  4287. }
  4288. return Callback.Status;
  4289. }
  4290. RPC_STATUS
  4291. DG_SCONNECTION::MakeApplicationSecurityCallback(
  4292. RPC_INTERFACE * Interface,
  4293. PDG_SCALL Call
  4294. )
  4295. {
  4296. RPC_STATUS Status = RPC_S_OK;
  4297. if (!ActiveSecurityContext)
  4298. {
  4299. LogError(SU_SCONN, EV_STATUS, this, (void *) 112, RPC_S_ACCESS_DENIED );
  4300. Status = RPC_S_ACCESS_DENIED;
  4301. }
  4302. else
  4303. {
  4304. unsigned Info = InterfaceCallbackResults.Find(Interface);
  4305. if ((Info & CBI_VALID) == 0 ||
  4306. (Info & CBI_CONTEXT_MASK) != ActiveSecurityContext->AuthContextId ||
  4307. (Info & CBI_SEQUENCE_MASK) != (Interface->SequenceNumber << CBI_SEQUENCE_SHIFT))
  4308. {
  4309. RPC_STATUS MyStatus;
  4310. MyStatus = Interface->CheckSecurityIfNecessary(Call);
  4311. if (RPC_S_OK == MyStatus)
  4312. {
  4313. LogEvent(SU_SCONN, EV_STATUS, this, (void *) 114, MyStatus );
  4314. Info = CBI_ALLOWED;
  4315. }
  4316. else
  4317. {
  4318. LogError(SU_SCONN, EV_STATUS, this, (void *) 114, MyStatus );
  4319. Info = 0;
  4320. }
  4321. Info |= CBI_VALID;
  4322. Info |= ActiveSecurityContext->AuthContextId;
  4323. Info |= (Interface->SequenceNumber << CBI_SEQUENCE_SHIFT);
  4324. InterfaceCallbackResults.Update(Interface, Info);
  4325. //
  4326. // If the callback routine impersonated the client,
  4327. // restore the thread to its native security context.
  4328. //
  4329. RevertToSelf();
  4330. }
  4331. else
  4332. {
  4333. LogEvent(SU_SCONN, EV_STATUS, this, (void *)115, Info);
  4334. }
  4335. if (0 == (Info & CBI_ALLOWED))
  4336. {
  4337. Status = RPC_S_ACCESS_DENIED;
  4338. LogError(SU_SCONN, EV_STATUS, this, (void *) 113, Status );
  4339. }
  4340. }
  4341. return Status;
  4342. }
  4343. RPC_STATUS
  4344. DG_SCONNECTION::SealAndSendPacket(
  4345. IN DG_ENDPOINT * SourceEndpoint,
  4346. IN DG_TRANSPORT_ADDRESS RemoteAddress,
  4347. IN UNALIGNED NCA_PACKET_HEADER *Header,
  4348. IN unsigned long DataOffset
  4349. )
  4350. {
  4351. ASSERT( 0 == ActivityNode.CompareUuid(&Header->ActivityId) );
  4352. if (DG_REJECT == Header->PacketType)
  4353. {
  4354. return SendSecurePacket( SourceEndpoint,
  4355. RemoteAddress,
  4356. Header,
  4357. DataOffset,
  4358. 0
  4359. );
  4360. }
  4361. else
  4362. {
  4363. return SendSecurePacket( SourceEndpoint,
  4364. RemoteAddress,
  4365. Header,
  4366. DataOffset,
  4367. ActiveSecurityContext
  4368. );
  4369. }
  4370. }
  4371. RPC_STATUS
  4372. DG_SCALL::Cancel(
  4373. void * ThreadHandle
  4374. )
  4375. {
  4376. Connection->Mutex.Request();
  4377. ++Cancelled;
  4378. BasePacketFlags2 |= DG_PF2_CANCEL_PENDING;
  4379. Connection->Mutex.Clear();
  4380. return RPC_S_OK;
  4381. }
  4382. unsigned
  4383. DG_SCALL::TestCancel()
  4384. {
  4385. if (!Cancelled)
  4386. {
  4387. return 0;
  4388. }
  4389. unsigned CancelCount;
  4390. Connection->Mutex.Request();
  4391. CancelCount = Cancelled;
  4392. Cancelled = 0;
  4393. BasePacketFlags2 &= ~(DG_PF2_CANCEL_PENDING);
  4394. Connection->Mutex.Clear();
  4395. return CancelCount;
  4396. }
  4397. RPC_STATUS
  4398. DG_SCALL::WaitForPipeEvent()
  4399. {
  4400. RPC_STATUS Status = RPC_S_OK;
  4401. unsigned Locus;
  4402. if (!PipeWaitEvent)
  4403. {
  4404. PipeWaitEvent = new EVENT(&Status, FALSE);
  4405. if (!PipeWaitEvent)
  4406. {
  4407. Status = RPC_S_OUT_OF_MEMORY;
  4408. }
  4409. else if (Status != RPC_S_OK)
  4410. {
  4411. delete PipeWaitEvent;
  4412. PipeWaitEvent = 0;
  4413. }
  4414. if (Status)
  4415. {
  4416. PipeWaitType = PWT_NONE;
  4417. PipeThreadId = 0;
  4418. return Status;
  4419. }
  4420. }
  4421. IncrementRefCount();
  4422. Connection->Mutex.Clear();
  4423. PipeWaitEvent->Wait();
  4424. Connection->Mutex.Request();
  4425. DecrementRefCount();
  4426. ASSERT(PipeThreadId == GetCurrentThreadId());
  4427. PipeThreadId = 0;
  4428. if (TerminateWhenConvenient)
  4429. {
  4430. Status = RPC_S_CALL_FAILED;
  4431. }
  4432. return Status;
  4433. }
  4434. BOOL
  4435. DG_SCALL::FinishSendOrReceive(
  4436. BOOL Abort
  4437. )
  4438. {
  4439. RPC_ASYNC_EVENT Event;
  4440. if (Abort)
  4441. {
  4442. TerminateWhenConvenient = TRUE;
  4443. }
  4444. switch (PipeWaitType)
  4445. {
  4446. case PWT_NONE: return FALSE;
  4447. case PWT_SEND: Event = RpcSendComplete; break;
  4448. case PWT_RECEIVE: Event = RpcReceiveComplete; break;
  4449. default: ASSERT(0 && "bad pipe wait type"); return FALSE;
  4450. }
  4451. ASSERT( PipeThreadId != 0 );
  4452. PipeWaitType = PWT_NONE;
  4453. if (!pAsync)
  4454. {
  4455. PipeWaitEvent->Raise();
  4456. return TRUE;
  4457. }
  4458. if (Event == RpcSendComplete)
  4459. {
  4460. if (FinalSendBufferPresent)
  4461. {
  4462. PipeThreadId = 0;
  4463. return FALSE;
  4464. }
  4465. }
  4466. IssueNotification( Event );
  4467. return TRUE;
  4468. }
  4469. RPC_STATUS
  4470. DG_SCALL::Receive(
  4471. PRPC_MESSAGE Message,
  4472. unsigned Size
  4473. )
  4474. /*++
  4475. Routine Description:
  4476. When a server stub calls I_RpcReceive, this fn will be called
  4477. in short order.
  4478. Sync case: the fn waits until the requested buffer bytes are available,
  4479. copies them to Message->Buffer, and returns.
  4480. Async case: the fn returns the data if available now, otherwise
  4481. RPC_S_ASYNC_CALL_PENDING. The app will be notified when the
  4482. data becomes available. It can also poll.
  4483. The action depends upon Message->RpcFlags:
  4484. RPC_BUFFER_PARTIAL:
  4485. Data is stored beginning at Message->Buffer[0].
  4486. Wait only until <Message->BufferLength> bytes are available;
  4487. we may resize the buffer if the fragment data exceeds the
  4488. current buffer length.
  4489. RPC_BUFFER_EXTRA:
  4490. Data is stored beginning at Message->Buffer[Message->BufferLength].
  4491. Arguments:
  4492. Message - the request.
  4493. Message->Buffer is explicitly allowed to be zero, in which case this
  4494. fn is responsible for allocating it.
  4495. Return Value:
  4496. the usual error codes
  4497. --*/
  4498. {
  4499. RPC_STATUS Status = RPC_S_OK;
  4500. unsigned Locus;
  4501. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4502. {
  4503. LogEvent(SU_SCALL, EV_PROC, this, Message, 'A' + (('R' + (('c' + ('v' << 8)) << 8)) << 8));
  4504. }
  4505. else
  4506. {
  4507. LogEvent(SU_SCALL, EV_PROC, this, Message, 'R' + (('e' + (('c' + ('v' << 8)) << 8)) << 8));
  4508. }
  4509. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Size);
  4510. Connection->Mutex.Request();
  4511. if (TerminateWhenConvenient)
  4512. {
  4513. FreeBuffer(Message);
  4514. Status = RPC_S_CALL_FAILED;
  4515. if (pAsync)
  4516. {
  4517. //
  4518. // case c) from doc:appref
  4519. //
  4520. DecrementRefCount();
  4521. Cleanup();
  4522. }
  4523. Connection->Mutex.Clear();
  4524. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4525. return Status;
  4526. }
  4527. //
  4528. // Determine whether we already have enough data on hand.
  4529. //
  4530. BOOL fEnoughData;
  4531. if (Message->RpcFlags & RPC_BUFFER_PARTIAL)
  4532. {
  4533. ASSERT(Size);
  4534. if (fReceivedAllFragments || ConsecutiveDataBytes >= Size)
  4535. {
  4536. fEnoughData = TRUE;
  4537. }
  4538. else
  4539. {
  4540. fEnoughData = FALSE;
  4541. PipeWaitLength = Size;
  4542. }
  4543. }
  4544. else
  4545. {
  4546. fEnoughData = fReceivedAllFragments;
  4547. PipeWaitLength = 0;
  4548. }
  4549. //
  4550. // Wait for enough data.
  4551. //
  4552. if (!fEnoughData)
  4553. {
  4554. if (Message->RpcFlags & RPC_BUFFER_NONOTIFY)
  4555. {
  4556. Connection->Mutex.Clear();
  4557. LogEvent(SU_SCALL, EV_STATUS, this, 0, RPC_S_ASYNC_CALL_PENDING);
  4558. return RPC_S_ASYNC_CALL_PENDING;
  4559. }
  4560. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4561. {
  4562. ASSERT((PWT_NONE == PipeWaitType && 0 == PipeThreadId) ||
  4563. (PWT_RECEIVE == PipeWaitType && GetCurrentThreadId() == PipeThreadId));
  4564. PipeWaitType = PWT_RECEIVE;
  4565. PipeThreadId = GetCurrentThreadId();
  4566. Connection->Mutex.Clear();
  4567. LogEvent(SU_SCALL, EV_STATUS, this, 0, RPC_S_ASYNC_CALL_PENDING);
  4568. return RPC_S_ASYNC_CALL_PENDING;
  4569. }
  4570. else
  4571. {
  4572. ASSERT(PWT_NONE == PipeWaitType);
  4573. ASSERT(0 == PipeThreadId);
  4574. PipeWaitType = PWT_RECEIVE;
  4575. PipeThreadId = GetCurrentThreadId();
  4576. Status = WaitForPipeEvent();
  4577. if (Status)
  4578. {
  4579. //
  4580. // I would like to delete the buffer here, but NDR has already saved Message->Buffer
  4581. // somewhere else and will later ask that it be deleted again.
  4582. //
  4583. // FreeBuffer(Message);
  4584. if (pAsync)
  4585. {
  4586. //
  4587. // case c) from doc:appref
  4588. //
  4589. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4590. SealAndSendPacket(&pSavedPacket->Header);
  4591. DecrementRefCount();
  4592. Cleanup();
  4593. }
  4594. Connection->Mutex.Clear();
  4595. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4596. return Status;
  4597. }
  4598. }
  4599. }
  4600. //
  4601. // This is here only for async receive case, but the if() clause
  4602. // would only slow us down.
  4603. //
  4604. ASSERT( PipeWaitType == PWT_NONE );
  4605. PipeThreadId = 0;
  4606. //
  4607. // For secure RPC, verify packet integrity.
  4608. //
  4609. if (Connection->AuthInfo.AuthenticationLevel > RPC_C_AUTHN_LEVEL_NONE)
  4610. {
  4611. PDG_PACKET pScan = pReceivedPackets;
  4612. do
  4613. {
  4614. Status = Connection->VerifyRequestPacket(pScan);
  4615. pScan = pScan->pNext;
  4616. }
  4617. while (pScan && Status == RPC_S_OK);
  4618. }
  4619. if (RPC_S_OK == Status)
  4620. {
  4621. Status = AssembleBufferFromPackets(Message);
  4622. }
  4623. if (Status)
  4624. {
  4625. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4626. FreeBuffer(Message);
  4627. }
  4628. Connection->Mutex.Clear();
  4629. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, Message->BufferLength);
  4630. return Status;
  4631. }
  4632. RPC_STATUS
  4633. DG_SCALL::Send(
  4634. PRPC_MESSAGE Message
  4635. )
  4636. /*++
  4637. Routine Description:
  4638. Transfers a pipe data buffer to the client.
  4639. Arguments:
  4640. Message - the usual data
  4641. Return Value:
  4642. the usual suspects
  4643. --*/
  4644. {
  4645. RPC_STATUS Status;
  4646. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4647. {
  4648. LogEvent(SU_SCALL, EV_PROC, this, Message, 'A' + (('S' + (('n' + ('d' << 8)) << 8)) << 8));
  4649. }
  4650. else
  4651. {
  4652. LogEvent(SU_SCALL, EV_PROC, this, Message, 'S' + (('e' + (('n' + ('d' << 8)) << 8)) << 8));
  4653. }
  4654. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  4655. //
  4656. // No notification occurs on the buffer containing the [out] static args.
  4657. // This is consistent with synchronous pipes.
  4658. //
  4659. if (!(Message->RpcFlags & RPC_BUFFER_PARTIAL))
  4660. {
  4661. FinalSendBufferPresent = TRUE;
  4662. Message->RpcFlags |= RPC_BUFFER_NONOTIFY;
  4663. }
  4664. Connection->Mutex.Request();
  4665. ASSERT(fReceivedAllFragments);
  4666. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4667. {
  4668. ASSERT(pAsync);
  4669. }
  4670. else
  4671. {
  4672. ASSERT(State == CallDispatched ||
  4673. State == CallSendingResponse ||
  4674. State == CallAfterDispatch );
  4675. }
  4676. if (TerminateWhenConvenient)
  4677. {
  4678. FreeBuffer(Message);
  4679. SetState(CallSendingResponse);
  4680. Status = RPC_S_CALL_FAILED;
  4681. if (pAsync)
  4682. {
  4683. //
  4684. // case c) from doc:appref
  4685. //
  4686. DecrementRefCount();
  4687. Cleanup();
  4688. }
  4689. Connection->Mutex.Clear();
  4690. LogError(SU_SCALL, EV_STATUS, this, (void *) 1 , Status);
  4691. return Status;
  4692. }
  4693. SetFragmentLengths();
  4694. if ((Message->RpcFlags & RPC_BUFFER_PARTIAL) &&
  4695. Message->BufferLength < (ULONG) MaxFragmentSize * SendWindowSize )
  4696. {
  4697. if (pAsync)
  4698. {
  4699. IssueNotification( RpcSendComplete );
  4700. }
  4701. Connection->Mutex.Clear();
  4702. LogEvent(SU_SCALL, EV_STATUS, this, (void *) 2, RPC_S_SEND_INCOMPLETE);
  4703. return RPC_S_SEND_INCOMPLETE;
  4704. }
  4705. if (State != CallSendingResponse)
  4706. {
  4707. SetState(CallSendingResponse);
  4708. CleanupReceiveWindow();
  4709. }
  4710. //
  4711. // Set the message buffer as the current send buffer.
  4712. //
  4713. Status = PushBuffer(Message);
  4714. //
  4715. // Ignore normal send errors - they are usually transient and a retry fixes the problem.
  4716. //
  4717. if (Status == RPC_P_SEND_FAILED)
  4718. {
  4719. Status = 0;
  4720. }
  4721. if (Status)
  4722. {
  4723. FreeBuffer(Message);
  4724. if (pAsync)
  4725. {
  4726. //
  4727. // case c) from doc:appref
  4728. //
  4729. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4730. SealAndSendPacket(&pSavedPacket->Header);
  4731. DecrementRefCount();
  4732. Cleanup();
  4733. }
  4734. Connection->Mutex.Clear();
  4735. LogError(SU_SCALL, EV_STATUS, this, (void *) 3, Status);
  4736. return Status;
  4737. }
  4738. PipeWaitType = PWT_SEND;
  4739. PipeThreadId = GetCurrentThreadId();
  4740. if (Message->RpcFlags & RPC_BUFFER_ASYNC)
  4741. {
  4742. }
  4743. else
  4744. {
  4745. Status = WaitForPipeEvent();
  4746. if (Status)
  4747. {
  4748. if (pAsync)
  4749. {
  4750. //
  4751. // case c) from doc:appref
  4752. //
  4753. InitErrorPacket(pSavedPacket, DG_FAULT, Status);
  4754. SealAndSendPacket(&pSavedPacket->Header);
  4755. DecrementRefCount();
  4756. Cleanup();
  4757. }
  4758. Connection->Mutex.Clear();
  4759. LogError(SU_SCALL, EV_STATUS, this, (void *) 4, Status);
  4760. return Status;
  4761. }
  4762. }
  4763. if (pAsync && !(Message->RpcFlags & RPC_BUFFER_PARTIAL))
  4764. {
  4765. //
  4766. // case b) from doc:appref
  4767. // Don't nuke the call, just remove the extra reference
  4768. //
  4769. DecrementRefCount();
  4770. }
  4771. Connection->Mutex.Clear();
  4772. //
  4773. // Be careful looking at member data from here on!
  4774. //
  4775. //
  4776. // if this was a PARTIAL send and the buffer did not occupy an even
  4777. // number of packets, the message buffer and length now reflect
  4778. // the unsent portion.
  4779. //
  4780. if (!Status && Message->BufferLength)
  4781. {
  4782. Status = RPC_S_SEND_INCOMPLETE;
  4783. }
  4784. if (Status)
  4785. {
  4786. LogEvent(SU_SCALL, EV_STATUS, this, 0, Status);
  4787. }
  4788. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, Message->BufferLength);
  4789. return Status;
  4790. }
  4791. RPC_STATUS
  4792. DG_SCALL::AsyncSend (
  4793. IN OUT PRPC_MESSAGE Message
  4794. )
  4795. {
  4796. return Send(Message);
  4797. }
  4798. RPC_STATUS
  4799. DG_SCALL::AsyncReceive (
  4800. IN OUT PRPC_MESSAGE Message,
  4801. IN unsigned int Size
  4802. )
  4803. {
  4804. return Receive(Message, Size);
  4805. }
  4806. RPC_STATUS
  4807. DG_SCALL::InqLocalConnAddress (
  4808. IN OUT void *Buffer,
  4809. IN OUT unsigned long *BufferSize,
  4810. OUT unsigned long *AddressFormat
  4811. )
  4812. /*++
  4813. Routine Description:
  4814. This routine is used by a server application to inquire about the local
  4815. address on which a call is made.
  4816. Arguments:
  4817. Buffer - The buffer that will receive the output address
  4818. BufferSize - the size of the supplied Buffer on input. On output the
  4819. number of bytes written to the buffer. If the buffer is too small
  4820. to receive all the output data, ERROR_MORE_DATA is returned,
  4821. nothing is written to the buffer, and BufferSize is set to
  4822. the size of the buffer needed to return all the data.
  4823. AddressFormat - a constant indicating the format of the returned address.
  4824. Currently supported for datagrams is RPC_P_ADDR_FORMAT_TCP_IPV4.
  4825. Return Values:
  4826. RPC_S_OK - success.
  4827. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
  4828. operation.
  4829. RPC_S_INVALID_BINDING - The supplied client binding is invalid.
  4830. RPC_S_CANNOT_SUPPORT - The local address was inquired for a protocol
  4831. sequence that doesn't support this type of functionality. Currently
  4832. only ncacn_ip_tcp supports it.
  4833. RPC_S_* or Win32 error for other errors
  4834. --*/
  4835. {
  4836. if (*BufferSize < sizeof(DWORD))
  4837. {
  4838. *BufferSize = sizeof(DWORD);
  4839. return ERROR_MORE_DATA;
  4840. }
  4841. *AddressFormat = RPC_P_ADDR_FORMAT_TCP_IPV4;
  4842. *(DWORD *)Buffer = LocalAddress;
  4843. return RPC_S_OK;
  4844. }
  4845. RPC_STATUS
  4846. DG_SCALL::SetAsyncHandle (
  4847. IN RPC_ASYNC_STATE * hAsync
  4848. )
  4849. {
  4850. THREAD *MyThread = RpcpGetThreadPointer();
  4851. ASSERT(MyThread);
  4852. LogEvent(SU_SCALL, EV_PROC, this, 0, 'S' + (('e' + (('t' + ('H' << 8)) << 8)) << 8));
  4853. MyThread->fAsync = TRUE;
  4854. Connection->Mutex.Request();
  4855. ASSERT( State == CallDispatched );
  4856. ASSERT(0 == pAsync);
  4857. pAsync = hAsync;
  4858. IncrementRefCount();
  4859. Connection->Mutex.Clear();
  4860. return RPC_S_OK;
  4861. }
  4862. RPC_STATUS
  4863. DG_SCALL::AbortAsyncCall (
  4864. IN PRPC_ASYNC_STATE pAsync,
  4865. IN unsigned long ExceptionCode
  4866. )
  4867. {
  4868. LogEvent(SU_SCALL, EV_PROC, this, 0, 'A' + (('b' + (('t' + ('C' << 8)) << 8)) << 8));
  4869. Connection->Mutex.Request();
  4870. ASSERT( State == CallDispatched ||
  4871. State == CallAfterDispatch );
  4872. if ( State != CallDispatched &&
  4873. State != CallAfterDispatch )
  4874. {
  4875. Connection->Mutex.Clear();
  4876. return RPC_S_INVALID_ASYNC_CALL;
  4877. }
  4878. SetState(CallSendingResponse);
  4879. CleanupReceiveWindow();
  4880. // case d) from doc:appref
  4881. //
  4882. InitErrorPacket(pSavedPacket, DG_FAULT, ExceptionCode);
  4883. SealAndSendPacket(&pSavedPacket->Header);
  4884. DecrementRefCount();
  4885. Cleanup();
  4886. Connection->Mutex.Clear();
  4887. return RPC_S_OK;
  4888. }
  4889. BOOL
  4890. DG_SCALL::IssueNotification (
  4891. IN RPC_ASYNC_EVENT Event
  4892. )
  4893. {
  4894. LogEvent(SU_SCALL, EV_NOTIFY, this, 0, Event);
  4895. if (Event == RpcSendComplete && !(pAsync->Flags & RPC_C_NOTIFY_ON_SEND_COMPLETE))
  4896. {
  4897. return TRUE;
  4898. }
  4899. if (pAsync->NotificationType == RpcNotificationTypeApc)
  4900. {
  4901. IncrementRefCount();
  4902. }
  4903. int i;
  4904. for (i=1; i < 3; ++i)
  4905. {
  4906. if (CALL::IssueNotification(Event))
  4907. {
  4908. return TRUE;
  4909. }
  4910. Sleep(200);
  4911. }
  4912. DecrementRefCount();
  4913. return FALSE;
  4914. }
  4915. void
  4916. DG_SCALL::FreeAPCInfo (
  4917. IN RPC_APC_INFO *pAPCInfo
  4918. )
  4919. {
  4920. LogEvent(SU_SCALL, EV_APC, this);
  4921. Connection->Mutex.Request();
  4922. DecrementRefCount();
  4923. BOOL Final = FALSE;
  4924. if (pAPCInfo->Event == RpcSendComplete &&
  4925. !(BufferFlags & RPC_BUFFER_PARTIAL))
  4926. {
  4927. Final = TRUE;
  4928. }
  4929. CALL::FreeAPCInfo(pAPCInfo);
  4930. if (Final)
  4931. {
  4932. Cleanup();
  4933. }
  4934. Connection->Mutex.Clear();
  4935. }
  4936. void
  4937. DG_SCALL::FreePipeBuffer (
  4938. IN PRPC_MESSAGE Message
  4939. )
  4940. {
  4941. FreeBuffer(Message);
  4942. }
  4943. RPC_STATUS
  4944. DG_SCALL::ReallocPipeBuffer (
  4945. IN PRPC_MESSAGE Message,
  4946. IN unsigned int NewSize
  4947. )
  4948. {
  4949. LogEvent(SU_SCALL, EV_PROC, this, Message, 'R' + (('B' + (('u' + ('f' << 8)) << 8)) << 8));
  4950. LogEvent(SU_SCALL, EV_BUFFER_IN, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  4951. Connection->Mutex.Request();
  4952. if (TerminateWhenConvenient)
  4953. {
  4954. Connection->Mutex.Clear();
  4955. LogError(SU_SCALL, EV_STATUS, this, 0, RPC_S_CALL_FAILED);
  4956. return RPC_S_CALL_FAILED;
  4957. }
  4958. RPC_STATUS Status;
  4959. //
  4960. // If we are updating the [in] buffer, we need to inform
  4961. // DispatchToStubWorker of the new [in] buffer.
  4962. //
  4963. void * OldBuffer = Message->Buffer;
  4964. Status = CommonReallocBuffer(Message, NewSize);
  4965. if (Status == RPC_S_OK)
  4966. {
  4967. if (OldBuffer == DispatchBuffer)
  4968. {
  4969. DispatchBuffer = Message->Buffer;
  4970. }
  4971. // The ReservedForRuntime field is a local variable of ProcessRpcCall,
  4972. // so it is valid only during dispatch.
  4973. //
  4974. if (State == CallDispatched)
  4975. {
  4976. PRPC_RUNTIME_INFO Info = (PRPC_RUNTIME_INFO) Message->ReservedForRuntime;
  4977. if (OldBuffer == Info->OldBuffer)
  4978. {
  4979. Info->OldBuffer = Message->Buffer;
  4980. }
  4981. }
  4982. #ifdef MONITOR_SERVER_PACKET_COUNT
  4983. if (Message->Buffer != OldBuffer)
  4984. {
  4985. ASSERT( DG_PACKET::FromStubData(Message->Buffer)->pCount == 0 );
  4986. DG_PACKET::FromStubData(Message->Buffer)->pCount = &OutstandingPacketCount;
  4987. InterlockedIncrement( &OutstandingPacketCount );
  4988. LogEvent( SU_SCALL, '(', this, DG_PACKET::FromStubData(Message->Buffer), OutstandingPacketCount );
  4989. }
  4990. #endif
  4991. }
  4992. Connection->Mutex.Clear();
  4993. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, Message->Buffer, (Message->RpcFlags << 4) | Message->BufferLength);
  4994. if (Status)
  4995. {
  4996. LogError(SU_SCALL, EV_STATUS, this, 0, Status);
  4997. }
  4998. return Status;
  4999. }