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.

7805 lines
217 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. osfsvr.cxx
  5. Abstract:
  6. This file contains the server side implementation of the OSF connection
  7. oriented RPC protocol engine.
  8. Author:
  9. Michael Montague (mikemon) 17-Jul-1990
  10. Revision History:
  11. Mazhar Mohammed (mazharm) 2/1/97 major rehaul to support async
  12. - Added support for Async RPC, Pipes
  13. - Changed it to operate as a state machine
  14. - Changed class structure
  15. - Got rid of the TRANS classes
  16. Kamen Moutafov (kamenm) Jan-2000 Support for multiple transfer syntaxes
  17. Kamen Moutafov (KamenM) Dec 99 - Feb 2000 - Support for cell debugging stuff
  18. Kamen Moutafov (KamenM) Mar-2000 Support for extended error info
  19. --*/
  20. #include <precomp.hxx>
  21. #include <wincrypt.h>
  22. #include <rpcssl.h>
  23. #include <thrdctx.hxx>
  24. #include <hndlsvr.hxx>
  25. #include <osfpcket.hxx>
  26. #include <secsvr.hxx>
  27. #include <osfsvr.hxx>
  28. #include <sdict2.hxx>
  29. #include <rpccfg.h>
  30. #include <schnlsp.h> // for UNISP_RPC_ID
  31. #include <charconv.hxx>
  32. extern long GroupIdCounter;
  33. // explicit placement new operator
  34. inline
  35. PVOID __cdecl
  36. operator new(
  37. size_t size,
  38. PVOID pPlacement
  39. )
  40. {
  41. return pPlacement;
  42. }
  43. OSF_ADDRESS::OSF_ADDRESS (
  44. IN TRANS_INFO * RpcTransInfo,
  45. IN OUT RPC_STATUS * Status
  46. ) : RPC_ADDRESS(Status)
  47. /*++
  48. Routine Description:
  49. --*/
  50. {
  51. RPC_CONNECTION_TRANSPORT *RpcServerInfo =
  52. (RPC_CONNECTION_TRANSPORT *) RpcTransInfo->InqTransInfo();
  53. int i;
  54. RPC_STATUS OriginalFailureStatus;
  55. ObjectType = OSF_ADDRESS_TYPE;
  56. ActiveCallCount = 0;
  57. ServerListeningFlag = 0;
  58. ServerInfo = RpcServerInfo;
  59. TransInfo = RpcTransInfo;
  60. SetupAddressOccurred = 0;
  61. if (IsServerSideDebugInfoEnabled())
  62. {
  63. DebugCell = (DebugEndpointInfo *)AllocateCell(&DebugCellTag);
  64. if (DebugCell == NULL)
  65. {
  66. *Status = RPC_S_OUT_OF_MEMORY;
  67. }
  68. else
  69. {
  70. DebugCell->TypeHeader = 0;
  71. DebugCell->Type = dctEndpointInfo;
  72. DebugCell->ProtseqType = (UCHAR)RpcServerInfo->TransId;
  73. DebugCell->Status = desAllocated;
  74. memset(DebugCell->EndpointName, 0, sizeof(DebugCell->EndpointName));
  75. }
  76. }
  77. else
  78. DebugCell = NULL;
  79. #if defined(_WIN64)
  80. ASSERT((MutexAllocationSize % 8) == 0);
  81. #else
  82. ASSERT((MutexAllocationSize % 4) == 0);
  83. #endif
  84. OriginalFailureStatus = RPC_S_OK;
  85. for (i = 0; i < NumberOfAssociationsDictionaries; i ++)
  86. {
  87. // explicit placement
  88. new (GetAssociationBucketMutex(i)) MUTEX (Status,
  89. TRUE // pre-allocate semaphores
  90. );
  91. // if there is a failure, remember it, so that subsequent successes
  92. // don't overwrite the failure
  93. if ((*Status != RPC_S_OK) && (OriginalFailureStatus == RPC_S_OK))
  94. {
  95. OriginalFailureStatus = *Status;
  96. }
  97. // don't check the status - the constructors will
  98. // check it. Also, we need to invoke all constructors
  99. // to give them a chance to initialize enough of the
  100. // object so that it can be destroyed properly
  101. }
  102. if (OriginalFailureStatus != RPC_S_OK)
  103. *Status = OriginalFailureStatus;
  104. }
  105. RPC_STATUS
  106. OSF_ADDRESS::ServerSetupAddress (
  107. IN RPC_CHAR * NetworkAddress,
  108. IN RPC_CHAR * *Endpoint,
  109. IN unsigned int PendingQueueSize,
  110. IN void * SecurityDescriptor, OPTIONAL
  111. IN unsigned long EndpointFlags,
  112. IN unsigned long NICFlags,
  113. OUT NETWORK_ADDRESS_VECTOR **ppNetworkAddressVector
  114. )
  115. /*++
  116. Routine Description:
  117. At this point, we need to setup the loadable transport interface.
  118. We also need to obtain the network address for this server. After
  119. allocating a buffer to hold the network address, we will call
  120. the loadable transport interface to let it do its thing.
  121. Arguments:
  122. Endpoint - Supplies the endpoint to be used will this address.
  123. NetworkAddress - Returns the network address for this server. The
  124. ownership of the buffer allocated to contain the network address
  125. passes to the caller.
  126. SecurityDescriptor - Optionally supplies a security descriptor to
  127. be placed on this address. Whether or not this is suppored depends
  128. on the particular combination of transport interface and operating
  129. system.
  130. PendingQueueSize - Supplies the size of the queue of pending
  131. requests which should be created by the transport. Some transports
  132. will not be able to make use of this value, while others will.
  133. RpcProtocolSequence - Supplies the protocol sequence for which we
  134. are trying to setup an address. This argument is necessary so
  135. that a single transport interface dll can support more than one
  136. protocol sequence.
  137. Return Value:
  138. RPC_S_OK - We successfully setup this address.
  139. RPC_S_INVALID_SECURITY_DESC - The supplied security descriptor is
  140. invalid.
  141. RPC_S_CANT_CREATE_ENDPOINT - The endpoint format is correct, but
  142. the endpoint can not be created.
  143. RPC_S_INVALID_ENDPOINT_FORMAT - The endpoint is not a valid
  144. endpoint for this particular transport interface.
  145. RPC_S_OUT_OF_RESOURCES - Insufficient resources are available to
  146. setup the address.
  147. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to setup
  148. the address.
  149. --*/
  150. {
  151. RPC_STATUS Status;
  152. Status = ServerInfo->Listen(InqRpcTransportAddress(),
  153. NetworkAddress,
  154. Endpoint,
  155. PendingQueueSize,
  156. SecurityDescriptor,
  157. EndpointFlags,
  158. NICFlags,
  159. ppNetworkAddressVector);
  160. if ( Status == RPC_S_OK )
  161. {
  162. SetupAddressOccurred = 1;
  163. }
  164. VALIDATE(Status)
  165. {
  166. RPC_S_OK,
  167. RPC_S_INVALID_SECURITY_DESC,
  168. RPC_S_INVALID_ARG,
  169. RPC_S_CANT_CREATE_ENDPOINT,
  170. RPC_S_INVALID_ENDPOINT_FORMAT,
  171. RPC_S_OUT_OF_RESOURCES,
  172. RPC_S_PROTSEQ_NOT_SUPPORTED,
  173. RPC_S_DUPLICATE_ENDPOINT,
  174. RPC_S_OUT_OF_MEMORY,
  175. RPC_S_SERVER_UNAVAILABLE
  176. } END_VALIDATE;
  177. return(Status);
  178. }
  179. #ifndef NO_PLUG_AND_PLAY
  180. void
  181. OSF_ADDRESS::PnpNotify (
  182. )
  183. {
  184. ServerInfo->PnpNotify();
  185. }
  186. #endif
  187. RPC_STATUS
  188. OSF_ADDRESS::CompleteListen (
  189. )
  190. /*++
  191. Function Name:CompleteListen
  192. Parameters:
  193. Description:
  194. Returns:
  195. --*/
  196. {
  197. if (ServerInfo->CompleteListen != 0)
  198. {
  199. ServerInfo->CompleteListen(InqRpcTransportAddress());
  200. }
  201. if (DebugCell)
  202. {
  203. CStackAnsi AnsiEndpoint;
  204. int i;
  205. RPC_STATUS RpcStatus;
  206. i = RpcpStringLength(InqEndpoint()) + 1;
  207. *(AnsiEndpoint.GetPAnsiString()) = (char *)_alloca(i);
  208. RpcStatus = AnsiEndpoint.Attach(InqEndpoint(), i, i * 2);
  209. // note that effectively ignore the result. That's ok - we don't
  210. // want servers to be unable to start because of code page issues
  211. // in the debug path. If this fails and we ignore it, the worse
  212. // that can happen is to have empty endpoint in the debug cell
  213. // - not a big deal.
  214. if (RpcStatus == RPC_S_OK)
  215. {
  216. strncpy(DebugCell->EndpointName, AnsiEndpoint, sizeof(DebugCell->EndpointName));
  217. }
  218. DebugCell->Status = desActive;
  219. }
  220. return(RPC_S_OK);
  221. }
  222. RPC_STATUS
  223. OSF_ADDRESS::ServerStartingToListen (
  224. IN unsigned int MinimumCallThreads,
  225. IN unsigned int MaximumConcurrentCalls
  226. )
  227. /*++
  228. Routine Description:
  229. Arguments:
  230. MinimumCallThreads - Supplies the minimum number of threads to have
  231. available to receive remote procedure calls.
  232. MaximumConcurrentCalls - Unused.
  233. Return Value:
  234. RPC_S_OK - Ok, this address is all ready to start listening for
  235. remote procedure calls.
  236. RPC_S_OUT_OF_THREADS - We could not create enough threads so that we
  237. have least the minimum number of call threads required (as
  238. specified by the MinimumCallThreads argument).
  239. --*/
  240. {
  241. RPC_STATUS Status;
  242. UNUSED(MaximumConcurrentCalls);
  243. UNUSED(MinimumCallThreads);
  244. Status = TransInfo->StartServerIfNecessary();
  245. if (Status == RPC_S_OK)
  246. {
  247. ServerListeningFlag = 1;
  248. }
  249. return Status;
  250. }
  251. OSF_ADDRESS::~OSF_ADDRESS (
  252. )
  253. /*++
  254. Routine Description:
  255. We need to clean up the address after it has been partially
  256. initialized. This routine will only be called before FireUpManager
  257. is called, but it may have been called before or after one of
  258. SetupAddressWithEndpoint or SetupAddressUnknownEndpoint is called.
  259. We will keep track of whether or not SetupAddress* occurred
  260. successfully; if so, we need to call AbortSetupAddress to give the
  261. loadable transport module a chance to clean things up.
  262. --*/
  263. {
  264. int i;
  265. if (SetupAddressOccurred != 0)
  266. ServerInfo->AbortListen(InqRpcTransportAddress());
  267. for (i = 0; i < NumberOfAssociationsDictionaries; i ++)
  268. {
  269. GetAssociationBucketMutex(i)->Free();
  270. }
  271. if (DebugCell != NULL)
  272. {
  273. FreeCell(DebugCell, &DebugCellTag);
  274. }
  275. }
  276. OSF_SCONNECTION *
  277. OSF_ADDRESS::NewConnection (
  278. )
  279. /*++
  280. Routine Description:
  281. We will create a new connection which belongs to this address.
  282. Arguments:
  283. ConnectionKey - Supplies the connection key specified for this
  284. connection by the loadable transport.
  285. Return Value:
  286. The new connection will be returned unless insufficient memory
  287. is available, in which case, zero will be returned.
  288. --*/
  289. {
  290. OSF_SCONNECTION * SConnection;
  291. RPC_STATUS Status = RPC_S_OK;
  292. SConnection = new (ServerInfo->ServerConnectionSize)
  293. OSF_SCONNECTION (
  294. this,
  295. ServerInfo,
  296. &Status);
  297. if ( Status != RPC_S_OK )
  298. {
  299. //
  300. // Server serverinfo to 0, so it doesn't call close
  301. //
  302. SConnection->ServerInfo = 0;
  303. delete SConnection;
  304. SConnection = 0;
  305. }
  306. if ( SConnection == 0 )
  307. {
  308. return(0);
  309. }
  310. //
  311. // Add a reference for the receive that is going to be posted by the
  312. // transport
  313. //
  314. SConnection->AddReference(); // CONN++
  315. return(SConnection);
  316. }
  317. unsigned int
  318. OSF_ADDRESS::TransSecondarySize (
  319. )
  320. {
  321. unsigned int Length = RpcpStringLength(InqEndpoint()) + 1;
  322. // Will be converted to ANSI in the wire, no need to multiply by
  323. // sizeof(RPC_CHAR).
  324. return(Length);
  325. }
  326. RPC_STATUS
  327. OSF_ADDRESS::TransSecondary (
  328. IN unsigned char * Address,
  329. IN unsigned int AddressLength
  330. )
  331. {
  332. RPC_STATUS Status;
  333. unsigned char *AnsiAddress;
  334. AnsiAddress = UnicodeToAnsiString(InqEndpoint(),&Status);
  335. if (Status != RPC_S_OK)
  336. {
  337. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  338. ASSERT(AnsiAddress == 0);
  339. return Status;
  340. }
  341. RpcpMemoryCopy(Address,AnsiAddress,AddressLength);
  342. delete AnsiAddress;
  343. return (RPC_S_OK);
  344. }
  345. void
  346. OSF_ADDRESS::ServerStoppedListening (
  347. )
  348. /*++
  349. Routine Description:
  350. We just need to indicate that the server is no longer listening, and
  351. set the minimum call threads to one.
  352. --*/
  353. {
  354. ServerListeningFlag = 0;
  355. }
  356. OSF_ASSOCIATION *
  357. OSF_ADDRESS::RemoveAssociation (
  358. IN int Key,
  359. IN OSF_ASSOCIATION *pAssociation
  360. )
  361. {
  362. int HashBucketNumber;
  363. OSF_ASSOCIATION *pAssociationRemoved;
  364. AddressMutex.VerifyNotOwned();
  365. HashBucketNumber = GetHashBucketForAssociation(pAssociation->AssocGroupId());
  366. // verify the the bucket is locked
  367. GetAssociationBucketMutex(HashBucketNumber)->VerifyOwned();
  368. pAssociationRemoved = Associations[HashBucketNumber].Delete(Key);
  369. return pAssociationRemoved;
  370. }
  371. int
  372. OSF_ADDRESS::AddAssociation (
  373. IN OSF_ASSOCIATION * TheAssociation
  374. )
  375. {
  376. int HashBucketNumber;
  377. int Key;
  378. HashBucketNumber = GetHashBucketForAssociation(TheAssociation->AssocGroupId());
  379. AddressMutex.VerifyNotOwned();
  380. // lock the bucket
  381. GetAssociationBucketMutex(HashBucketNumber)->Request();
  382. Key = Associations[HashBucketNumber].Insert(TheAssociation);
  383. // unlock the bucket
  384. GetAssociationBucketMutex(HashBucketNumber)->Clear();
  385. return Key;
  386. }
  387. OSF_ASSOCIATION *
  388. OSF_ADDRESS::FindAssociation (
  389. IN unsigned long AssociationGroupId,
  390. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  391. )
  392. // The AddressMutex has already been requested.
  393. {
  394. DictionaryCursor cursor;
  395. OSF_ASSOCIATION * Association;
  396. OSF_ASSOCIATION_DICT *pAssocDict;
  397. int HashBucketNumber;
  398. // get the hashed bucket
  399. HashBucketNumber = GetHashBucketForAssociation(AssociationGroupId);
  400. pAssocDict = &Associations[HashBucketNumber];
  401. AddressMutex.VerifyNotOwned();
  402. // lock the bucket
  403. GetAssociationBucketMutex(HashBucketNumber)->Request();
  404. // lookup the association in the bucket
  405. pAssocDict->Reset(cursor);
  406. while ( (Association = pAssocDict->Next(cursor)) != 0 )
  407. {
  408. if ( Association->IsMyAssocGroupId(AssociationGroupId,
  409. ClientProcess) != 0 )
  410. {
  411. Association->AddConnection();
  412. GetAssociationBucketMutex(HashBucketNumber)->Clear();
  413. return(Association);
  414. }
  415. }
  416. // unlock the bucket
  417. GetAssociationBucketMutex(HashBucketNumber)->Clear();
  418. return(0);
  419. }
  420. void
  421. OSF_ADDRESS::DestroyContextHandlesForInterface (
  422. IN RPC_SERVER_INTERFACE PAPI * RpcInterfaceInformation,
  423. IN BOOL RundownContextHandles
  424. )
  425. /*++
  426. Function Name: DestroyContextHandlesForInterface
  427. Parameters:
  428. RpcInterfaceInformation - the interface for which context handles
  429. are to be unregistered
  430. RundownContextHandles - if non-zero, rundown the context handles. If
  431. FALSE, destroy the runtime portion of the context handle resource,
  432. but don't call the user rundown routine.
  433. Description:
  434. The implementation fo context handle destruction for the connection
  435. oriented protocols. It will walk the list of associations, and for
  436. each one it will ask the association to destroy the context handles
  437. for that interface
  438. Returns:
  439. --*/
  440. {
  441. int i;
  442. MUTEX *CurrentBucketMutex;
  443. DictionaryCursor cursor;
  444. OSF_ASSOCIATION_DICT *CurrentAssocDict;
  445. OSF_ASSOCIATION *CurrentAssociation;
  446. BOOL CopyOfDictionaryUsed;
  447. OSF_ASSOCIATION_DICT AssocDictCopy;
  448. OSF_ASSOCIATION_DICT *AssocDictToUse;
  449. BOOL Res;
  450. // N.B. We may or we may not own the ServerMutex here - be prepared
  451. // for both occasions. The first implication is not to call functions
  452. // that take the server mutex.
  453. for (i = 0; i < NumberOfAssociationsDictionaries; i ++)
  454. {
  455. CurrentBucketMutex = GetAssociationBucketMutex(i);
  456. CurrentBucketMutex->Request();
  457. CurrentAssocDict = &Associations[i];
  458. CopyOfDictionaryUsed = AssocDictCopy.ExpandToSize(CurrentAssocDict->Size());
  459. if (CopyOfDictionaryUsed)
  460. {
  461. CurrentAssocDict->Reset(cursor);
  462. while ( (CurrentAssociation = CurrentAssocDict->Next(cursor)) != 0 )
  463. {
  464. Res = AssocDictCopy.Insert(CurrentAssociation);
  465. ASSERT(Res != -1);
  466. // artifically add a connection count to keep it alive
  467. // while we destroy the contexts
  468. CurrentAssociation->AddConnection();
  469. }
  470. CurrentBucketMutex->Clear();
  471. AssocDictToUse = &AssocDictCopy;
  472. }
  473. else
  474. {
  475. AssocDictToUse = CurrentAssocDict;
  476. }
  477. AssocDictToUse->Reset(cursor);
  478. while ( (CurrentAssociation = AssocDictToUse->Next(cursor)) != 0 )
  479. {
  480. // call into the association to destroy the context handles
  481. CurrentAssociation->DestroyContextHandlesForInterface(
  482. RpcInterfaceInformation,
  483. RundownContextHandles);
  484. }
  485. if (CopyOfDictionaryUsed)
  486. {
  487. while ( (CurrentAssociation = AssocDictCopy.Next(cursor)) != 0 )
  488. {
  489. // remove the extra refcounts
  490. CurrentAssociation->RemoveConnection();
  491. }
  492. AssocDictCopy.DeleteAll();
  493. }
  494. else
  495. {
  496. CurrentBucketMutex->Clear();
  497. }
  498. }
  499. }
  500. OSF_SBINDING::OSF_SBINDING ( // Constructor.
  501. IN RPC_INTERFACE * TheInterface,
  502. IN int PContext,
  503. IN int SelectedTransferSyntaxIndex
  504. )
  505. {
  506. PresentContext = PContext;
  507. Interface = TheInterface;
  508. SequenceNumber = 0;
  509. CurrentSecId = -1;
  510. this->SelectedTransferSyntaxIndex = SelectedTransferSyntaxIndex;
  511. }
  512. OSF_SCALL::OSF_SCALL (
  513. IN OSF_SCONNECTION *Connection,
  514. IN OUT RPC_STATUS *Status
  515. ) : CallMutex(Status), SyncEvent(Status, 0)
  516. {
  517. ObjectType = OSF_SCALL_TYPE;
  518. Thread = 0;
  519. CallOrphaned = 0;
  520. CancelPending = 0;
  521. SavedHeader = 0;
  522. SavedHeaderSize = 0;
  523. this->Connection = Connection;
  524. SendContext = (char *) this+sizeof(OSF_SCALL);
  525. SetReferenceCount(0);
  526. if (IsServerSideDebugInfoEnabled())
  527. {
  528. if (*Status != RPC_S_OK)
  529. {
  530. DebugCell = NULL;
  531. return;
  532. }
  533. DebugCell = (DebugCallInfo *)AllocateCell(&CellTag);
  534. if (DebugCell == NULL)
  535. *Status = RPC_S_OUT_OF_MEMORY;
  536. else
  537. {
  538. memset(DebugCell, 0, sizeof(DebugCallInfo));
  539. DebugCell->Type = dctCallInfo;
  540. DebugCell->Status = (BYTE)csAllocated;
  541. GetDebugCellIDFromDebugCell((DebugCellUnion *)Connection->DebugCell,
  542. &Connection->DebugCellTag, &DebugCell->Connection);
  543. DebugCell->LastUpdateTime = NtGetTickCount();
  544. // if this is the call for the connection,
  545. // it will be NULL. If this is a subsequent
  546. // call on the connection, the CachedSCall would
  547. // have been set already.
  548. if (Connection->CachedSCall == NULL)
  549. DebugCell->CallFlags = DBGCELL_CACHED_CALL;
  550. }
  551. }
  552. else
  553. DebugCell = NULL;
  554. //
  555. // we don't need to initialize ObjectUuidSpecified, ActualBufferLength,
  556. // FirstFrag and Alertcount
  557. //
  558. }
  559. OSF_SCALL::~OSF_SCALL (
  560. )
  561. {
  562. if (SavedHeader != 0)
  563. {
  564. ASSERT(SavedHeaderSize != 0) ;
  565. RpcpFarFree(SavedHeader);
  566. }
  567. if (DebugCell != NULL)
  568. {
  569. FreeCell(DebugCell, &CellTag);
  570. }
  571. }
  572. void
  573. OSF_SCALL::InquireObjectUuid (
  574. OUT RPC_UUID * ObjectUuid
  575. )
  576. /*++
  577. Routine Description:
  578. This routine copies the object uuid from the server connection into
  579. the supplied ObjectUuid argument.
  580. Arguments:
  581. ObjectUuid - Returns a copy of the object uuid in the server connection.
  582. --*/
  583. {
  584. if (ObjectUuidSpecified == 0)
  585. ObjectUuid->SetToNullUuid();
  586. else
  587. ObjectUuid->CopyUuid(&(this->ObjectUuid));
  588. }
  589. void
  590. OSF_SCALL::SendFault (
  591. IN RPC_STATUS Status,
  592. IN int DidNotExecute
  593. )
  594. {
  595. p_context_id_t p_cont = 0;
  596. if (CurrentBinding)
  597. p_cont = (p_context_id_t)CurrentBinding->GetPresentationContext();
  598. Connection->SendFault(Status, DidNotExecute, CallId, p_cont);
  599. }
  600. RPC_STATUS
  601. OSF_SCALL::SendReceive (
  602. IN OUT PRPC_MESSAGE Message
  603. )
  604. /*++
  605. Routine Description:
  606. Arguments:
  607. Message - Supplies the request to send to the server and returns the
  608. response received from the server.
  609. Return Value:
  610. RPC_S_OK - We successfully sent a remote procedure call request to the
  611. server and received back a response.
  612. --*/
  613. {
  614. RPC_STATUS Status, ExceptionCode;
  615. unsigned int RemoteFaultOccured = 0;
  616. RPC_MESSAGE RpcMessage ;
  617. RPC_RUNTIME_INFO RuntimeInfo ;
  618. PRPC_DISPATCH_TABLE DispatchTableToUse;
  619. if (CurrentState == CallAborted)
  620. {
  621. return RPC_S_CALL_FAILED;
  622. }
  623. CallStack += 1;
  624. Address->Server->OutgoingCallback();
  625. FirstFrag = 1;
  626. SyncEvent.Lower();
  627. Status = SendRequestOrResponse(Message, rpc_request);
  628. if (Status != RPC_S_OK)
  629. {
  630. CallStack -= 1;
  631. return Status;
  632. }
  633. for (;TRUE;)
  634. {
  635. if (CurrentState == CallAborted)
  636. {
  637. Status = RPC_S_CALL_FAILED;
  638. break;
  639. }
  640. //
  641. // In the callback case, when the receive event is kicked,
  642. // we have either received a fault or we have received a complete
  643. // response/request
  644. //
  645. SyncEvent.Wait();
  646. switch (CurrentState)
  647. {
  648. case ReceivedCallback:
  649. //
  650. // Just received a new callback,
  651. // need to dispatch it
  652. //
  653. RuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  654. RpcMessage.Handle = (RPC_BINDING_HANDLE) this;
  655. RpcMessage.Buffer = DispatchBuffer ;
  656. RpcMessage.BufferLength = DispatchBufferOffset;
  657. RpcMessage.RpcFlags = RPC_BUFFER_COMPLETE;
  658. RpcMessage.DataRepresentation = Connection->DataRep;
  659. RpcMessage.ReservedForRuntime = &RuntimeInfo ;
  660. CurrentBinding->GetSelectedTransferSyntaxAndDispatchTable(
  661. &RpcMessage.TransferSyntax, &DispatchTableToUse);
  662. RpcMessage.ProcNum = ProcNum;
  663. //
  664. // Dispatch the callback
  665. //
  666. if ( ObjectUuidSpecified != 0 )
  667. {
  668. Status = CurrentBinding->GetInterface()
  669. ->DispatchToStubWithObject(
  670. &RpcMessage,
  671. &ObjectUuid,
  672. 1,
  673. DispatchTableToUse,
  674. &ExceptionCode);
  675. }
  676. else
  677. {
  678. Status = CurrentBinding->GetInterface()
  679. ->DispatchToStub(
  680. &RpcMessage,
  681. 1,
  682. DispatchTableToUse,
  683. &ExceptionCode);
  684. }
  685. //
  686. // Send the reponse
  687. //
  688. if ( Status != RPC_S_OK )
  689. {
  690. VALIDATE(Status)
  691. {
  692. RPC_P_EXCEPTION_OCCURED,
  693. RPC_S_PROCNUM_OUT_OF_RANGE
  694. } END_VALIDATE;
  695. if ( Status == RPC_S_PROCNUM_OUT_OF_RANGE )
  696. {
  697. SendFault(RPC_S_PROCNUM_OUT_OF_RANGE, 1);
  698. }
  699. else
  700. {
  701. SendFault(ExceptionCode, 0);
  702. Status = ExceptionCode;
  703. }
  704. continue;
  705. }
  706. FirstFrag = 1;
  707. Status = SendRequestOrResponse(&RpcMessage, rpc_response);
  708. if ( Status == RPC_S_CALL_FAILED_DNE )
  709. {
  710. Status = RPC_S_CALL_FAILED;
  711. }
  712. //
  713. // if the client went away, it is wise to simple go away
  714. //
  715. if (Status != RPC_S_OK)
  716. {
  717. break;
  718. }
  719. //
  720. // Go back to waiting for our original reply
  721. //
  722. continue;
  723. case ReceivedCallbackReply:
  724. //
  725. // Received a reply to our callback
  726. // need to return to the caller with the reply
  727. //
  728. Message->Buffer = DispatchBuffer;
  729. Message->BufferLength = DispatchBufferOffset;
  730. Message->DataRepresentation = Connection->DataRep;
  731. Status = RPC_S_OK;
  732. break;
  733. case ReceivedFault:
  734. //
  735. // Received a fault, fail the call / propagate status
  736. // code
  737. //
  738. Status = AsyncStatus;
  739. break;
  740. case CallAborted:
  741. //
  742. // Call aborted, possibly because
  743. //
  744. Status = RPC_S_CALL_FAILED;
  745. break;
  746. default:
  747. //
  748. // Something bad happened, go back to looking
  749. ASSERT(0);
  750. }
  751. break;
  752. }
  753. //
  754. // We need this so the response to the original call can be sent
  755. // correctly.
  756. //
  757. FirstFrag = 1;
  758. CallStack -= 1;
  759. if ( Status == RPC_S_OK )
  760. {
  761. Message->Handle = (RPC_BINDING_HANDLE) this;
  762. }
  763. return(Status);
  764. }
  765. RPC_STATUS
  766. OSF_SCALL::NegotiateTransferSyntax (
  767. IN OUT PRPC_MESSAGE Message
  768. )
  769. {
  770. // this can happen in the callback case only.
  771. // Just return the already negotiated transfer syntax
  772. PRPC_DISPATCH_TABLE Ignored;
  773. CurrentBinding->GetSelectedTransferSyntaxAndDispatchTable(&Message->TransferSyntax,
  774. &Ignored);
  775. return RPC_S_OK;
  776. }
  777. RPC_STATUS
  778. OSF_SCALL::GetBuffer (
  779. IN OUT PRPC_MESSAGE Message,
  780. IN UUID *ObjectUuid
  781. )
  782. {
  783. ULONG BufferLengthToAllocate;
  784. Message->Handle = (RPC_BINDING_HANDLE) this;
  785. if (Message->RpcFlags & RPC_BUFFER_PARTIAL &&
  786. Message->BufferLength < Connection->MaxFrag)
  787. {
  788. ActualBufferLength = Connection->MaxFrag ;
  789. }
  790. else
  791. {
  792. ActualBufferLength = Message->BufferLength ;
  793. }
  794. // In addition to saving space for the request (or response) header,
  795. // we want to save space for security information if necessary.
  796. BufferLengthToAllocate = ActualBufferLength
  797. + sizeof(rpcconn_request)
  798. + (2* Connection->AdditionalSpaceForSecurity);
  799. if (TransGetBuffer(&Message->Buffer, BufferLengthToAllocate))
  800. {
  801. ActualBufferLength = 0 ;
  802. RpcpErrorAddRecord(EEInfoGCRuntime,
  803. RPC_S_OUT_OF_MEMORY,
  804. EEInfoDLOSF_SCALL__GetBuffer10,
  805. BufferLengthToAllocate);
  806. return(RPC_S_OUT_OF_MEMORY);
  807. }
  808. Message->Buffer = (unsigned char *) Message->Buffer
  809. + sizeof(rpcconn_request);
  810. return(RPC_S_OK);
  811. }
  812. RPC_STATUS
  813. OSF_SCALL::GetBufferDo (
  814. OUT void ** ppBuffer,
  815. IN unsigned int culRequiredLength,
  816. IN BOOL fDataValid,
  817. IN unsigned int DataLength,
  818. IN unsigned long Extra
  819. )
  820. {
  821. void *NewBuffer;
  822. if (TransGetBuffer(&NewBuffer,
  823. culRequiredLength + sizeof(rpcconn_request)))
  824. {
  825. return(RPC_S_OUT_OF_MEMORY);
  826. }
  827. if (fDataValid)
  828. {
  829. ASSERT(DataLength < culRequiredLength);
  830. NewBuffer = (unsigned char *) NewBuffer + sizeof(rpcconn_request);
  831. RpcpMemoryCopy(NewBuffer, *ppBuffer, DataLength);
  832. TransFreeBuffer((unsigned char *) *ppBuffer-sizeof(rpcconn_request));
  833. *ppBuffer = NewBuffer;
  834. }
  835. else
  836. {
  837. *ppBuffer = (unsigned char *) NewBuffer + sizeof(rpcconn_request);
  838. }
  839. return(RPC_S_OK);
  840. }
  841. void
  842. OSF_SCALL::FreeBufferDo (
  843. IN void *pBuffer
  844. )
  845. {
  846. #if DBG
  847. if (pBuffer == DispatchBuffer)
  848. {
  849. LogEvent(SU_SCALL, EV_DELETE, this, pBuffer, 1, 1);
  850. }
  851. #endif
  852. TransFreeBuffer((unsigned char *) pBuffer - sizeof(rpcconn_request));
  853. }
  854. void
  855. OSF_SCALL::FreeBuffer (
  856. IN PRPC_MESSAGE Message
  857. )
  858. {
  859. TransFreeBuffer((unsigned char *) Message->Buffer
  860. - sizeof(rpcconn_request));
  861. ActualBufferLength = 0;
  862. }
  863. void
  864. OSF_SCALL::FreePipeBuffer (
  865. IN PRPC_MESSAGE Message
  866. )
  867. {
  868. TransFreeBuffer((unsigned char *) Message->Buffer
  869. - sizeof(rpcconn_request));
  870. }
  871. RPC_STATUS
  872. OSF_SCALL::ReallocPipeBuffer (
  873. IN PRPC_MESSAGE Message,
  874. IN unsigned int NewSize
  875. )
  876. {
  877. void *TempBuffer ;
  878. RPC_STATUS Status ;
  879. unsigned int SizeToAlloc ;
  880. if (NewSize > ActualBufferLength)
  881. {
  882. SizeToAlloc = (NewSize > Connection->MaxFrag) ?
  883. NewSize:Connection->MaxFrag ;
  884. Status = TransGetBuffer(&TempBuffer,
  885. SizeToAlloc + sizeof(rpcconn_request) + sizeof(UUID)
  886. + (2* Connection->AdditionalSpaceForSecurity) );
  887. if ( Status != RPC_S_OK )
  888. {
  889. ASSERT( Status == RPC_S_OUT_OF_MEMORY );
  890. return(RPC_S_OUT_OF_MEMORY);
  891. }
  892. if (ActualBufferLength > 0)
  893. {
  894. RpcpMemoryCopy((char *) TempBuffer+sizeof(rpcconn_request),
  895. Message->Buffer, Message->BufferLength) ;
  896. OSF_SCALL::FreePipeBuffer(Message) ;
  897. }
  898. Message->Buffer = (char *) TempBuffer + sizeof(rpcconn_request);
  899. ActualBufferLength = SizeToAlloc ;
  900. }
  901. Message->BufferLength = NewSize ;
  902. return (RPC_S_OK) ;
  903. }
  904. RPC_STATUS
  905. OSF_SCALL::TransGetBuffer (
  906. OUT void * * Buffer,
  907. IN unsigned int BufferLength
  908. )
  909. /*++
  910. Routine Description:
  911. We need a buffer to receive data into or to put data into to be sent.
  912. This should be really simple, but we need to make sure that buffer we
  913. return is aligned on an 8 byte boundary. The stubs make this requirement.
  914. Arguments:
  915. Buffer - Returns a pointer to the buffer.
  916. BufferLength - Supplies the required length of the buffer in bytes.
  917. Return Value:
  918. RPC_S_OK - We successfully allocated a buffer of at least the required
  919. size.
  920. RPC_S_OUT_OF_MEMORY - There is insufficient memory available to allocate
  921. the required buffer.
  922. --*/
  923. {
  924. void *Memory;
  925. //
  926. // The NT memory allocator returns memory which is aligned by at least
  927. // 8, so we dont need to worry about aligning it.
  928. //
  929. Memory = CoAllocateBuffer(BufferLength);
  930. if ( Memory == 0 )
  931. {
  932. return(RPC_S_OUT_OF_MEMORY);
  933. }
  934. ASSERT( IsBufferAligned(Memory) );
  935. *Buffer = Memory;
  936. return(RPC_S_OK);
  937. }
  938. void
  939. OSF_SCALL::TransFreeBuffer (
  940. IN void * Buffer
  941. )
  942. /*++
  943. Routine Description:
  944. We need to free a buffer which was allocated via TransGetBuffer. The
  945. only tricky part is remembering to remove the padding before actually
  946. freeing the memory.
  947. --*/
  948. {
  949. CoFreeBuffer(Buffer);
  950. }
  951. BOOL
  952. OSF_SCALL::BeginRpcCall (
  953. IN rpcconn_common * Packet,
  954. IN unsigned int PacketLength
  955. )
  956. /*++
  957. Routine Description:
  958. Arguments:
  959. Packet - Supplies the packet we received from the connection. Ownership
  960. of this buffer passes to this routine.
  961. PacketLength - Supplies the length of the packet in bytes.
  962. Return Value:
  963. A non-zero return value indicates that the connection should not
  964. be placed in the receive any state; instead, the thread should just
  965. forget about the connection and go back to waiting for more new
  966. procedure calls.
  967. --*/
  968. {
  969. RPC_STATUS Status;
  970. unsigned long SizeofHeaderToSave = 0;
  971. int retval ;
  972. BOOL fReceivePosted;
  973. unsigned int HeaderSize = sizeof(rpcconn_request);
  974. THREAD *ThisThread;
  975. ActivateCall();
  976. //
  977. // Save the unbyteswapped header for the security related stuff
  978. // Especially if SECURITY is on. For Request/Resonse we save just
  979. // the greater of rpc_req or rpc_resp. We havent byteswapped anything..
  980. // but if auth_length is 0, byteswapping is irrelevant..
  981. //
  982. if (Packet->auth_length != 0)
  983. {
  984. if ((Packet->PTYPE == rpc_request) || (Packet->PTYPE == rpc_response))
  985. {
  986. SizeofHeaderToSave = sizeof(rpcconn_request);
  987. if ( (Packet->pfc_flags & PFC_OBJECT_UUID) != 0 )
  988. {
  989. SizeofHeaderToSave += sizeof(UUID);
  990. }
  991. }
  992. if (SavedHeaderSize < SizeofHeaderToSave)
  993. {
  994. if (SavedHeader != 0)
  995. {
  996. ASSERT(SavedHeaderSize != 0);
  997. RpcpFarFree(SavedHeader);
  998. }
  999. SavedHeader = RpcpFarAllocate(SizeofHeaderToSave);
  1000. if (SavedHeader == 0)
  1001. {
  1002. Status = RPC_S_PROTOCOL_ERROR;
  1003. goto Cleanup;
  1004. }
  1005. SavedHeaderSize = SizeofHeaderToSave;
  1006. RpcpMemoryCopy(SavedHeader, Packet, SizeofHeaderToSave);
  1007. }
  1008. else if (SizeofHeaderToSave != 0)
  1009. {
  1010. RpcpMemoryCopy(SavedHeader, Packet, SizeofHeaderToSave);
  1011. }
  1012. }
  1013. if (Packet->pfc_flags & PFC_PENDING_CANCEL)
  1014. {
  1015. RpcCancelThread(GetCurrentThread());
  1016. }
  1017. Status = ValidatePacket(Packet, PacketLength);
  1018. CallId = Packet->call_id;
  1019. if (Status != RPC_S_OK)
  1020. {
  1021. ASSERT(Status == RPC_S_PROTOCOL_ERROR);
  1022. //
  1023. // It is not the first packet, so we need to send a fault instead,
  1024. // and then we will blow the connection away.
  1025. //
  1026. goto Cleanup;
  1027. }
  1028. //
  1029. // We need to figure out about security: do we need to put authentication
  1030. // information into each packet, and if so, how much space should we
  1031. // reserve. When we allocated the buffer (see OSF_SCALL::GetBuffer)
  1032. // we saved space for security information. We did so we could just
  1033. // stick the authentication information into there without having to
  1034. // copy anything
  1035. //
  1036. if (Connection->AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  1037. {
  1038. ASSERT(Connection->AdditionalSpaceForSecurity >=
  1039. MAXIMUM_SECURITY_BLOCK_SIZE);
  1040. MaxSecuritySize = Connection->AdditionalSpaceForSecurity
  1041. - MAXIMUM_SECURITY_BLOCK_SIZE;
  1042. if (MaxSecuritySize == sizeof(sec_trailer))
  1043. {
  1044. MaxSecuritySize = 0;
  1045. }
  1046. else
  1047. {
  1048. //
  1049. // We need to arrange things so that the length of the stub data
  1050. // is a multiple of MAXIMUM_SECURITY_BLOCK_SIZE:
  1051. // this is a requirement of the security package.
  1052. //
  1053. MaximumFragmentLength -= ((MaximumFragmentLength - HeaderSize
  1054. - MaxSecuritySize) % MAXIMUM_SECURITY_BLOCK_SIZE);
  1055. }
  1056. }
  1057. ASSERT(Packet->PTYPE == rpc_request);
  1058. CurrentBinding = Connection->LookupBinding(
  1059. ((rpcconn_request *) Packet)->p_cont_id);
  1060. if (CurrentBinding)
  1061. {
  1062. RPC_INTERFACE *CurrentInterface = CurrentBinding->GetInterface();
  1063. ASSERT(CurrentState == NewRequest);
  1064. //
  1065. // Check the security callback on this connection
  1066. // - If IF does not require a security callback, just dispatch
  1067. // - If IF requires a callback and current call is insecure - send a fault
  1068. // and fail the call
  1069. // - If IF requires a callback, have the binding confirm that for this id
  1070. // we did callback once before
  1071. // - If we never did callback.. ever, SBinding->CheckSecurity will force
  1072. // a security callback
  1073. if (CurrentInterface->IsSecurityCallbackReqd() != 0)
  1074. {
  1075. if (Connection->CurrentSecurityContext == 0)
  1076. {
  1077. Status = RPC_S_ACCESS_DENIED;
  1078. goto Cleanup;
  1079. }
  1080. Status = Connection->CurrentSecurityContext->CheckForFailedThirdLeg();
  1081. if (Status != RPC_S_OK)
  1082. {
  1083. goto Cleanup;
  1084. }
  1085. ASSERT(Connection->CurrentSecurityContext->FullyConstructed() );
  1086. ThisThread = RpcpGetThreadPointer();
  1087. // set the current context for this thread so that the app
  1088. // can use the security callback. We'll whack it afterwards
  1089. // as the actual call may not get dispatched on this thread
  1090. RpcpSetThreadContextWithThread(ThisThread, this);
  1091. Status = CurrentBinding->CheckSecurity(this,
  1092. Connection->CurrentSecurityContext->AuthContextId);
  1093. RpcpSetThreadContextWithThread(ThisThread, 0);
  1094. if (Status != RPC_S_OK)
  1095. {
  1096. fSecurityFailure = 1;
  1097. if (Packet->pfc_flags & PFC_LAST_FRAG)
  1098. {
  1099. Status = RPC_S_ACCESS_DENIED;
  1100. Connection->CleanupPac();
  1101. goto Cleanup;
  1102. }
  1103. SendFault(RPC_S_ACCESS_DENIED, 1);
  1104. Connection->TransFreeBuffer(Packet);
  1105. return 0;
  1106. }
  1107. }
  1108. if (CurrentInterface->IsPipeInterface())
  1109. {
  1110. fPipeCall = 1;
  1111. if (DebugCell)
  1112. {
  1113. DebugCell->CallFlags |= DBGCELL_PIPE_CALL;
  1114. }
  1115. }
  1116. if (CurrentInterface->IsAutoListenInterface())
  1117. {
  1118. CurrentInterface->BeginAutoListenCall();
  1119. }
  1120. fReceivePosted = ProcessReceivedPDU(Packet, PacketLength, 1);
  1121. return fReceivePosted;
  1122. }
  1123. else
  1124. {
  1125. //
  1126. // We did not find a binding, which indicates the client tried
  1127. // to make a remote procedure call on an unknown interface.
  1128. //
  1129. Status = RPC_S_UNKNOWN_IF;
  1130. }
  1131. Cleanup:
  1132. Connection->TransFreeBuffer(Packet);
  1133. //
  1134. // No one else can come in until we post the next receive,
  1135. // so it is ok to send the fault before making the call
  1136. // available
  1137. //
  1138. SendFault(Status,1);
  1139. if (Status != RPC_S_UNKNOWN_IF)
  1140. {
  1141. Connection->fDontFlush = (CurrentState == NewRequest);
  1142. //
  1143. // We are going to kill the connection, do't post another receive
  1144. //
  1145. fReceivePosted = 1;
  1146. Connection->OSF_SCONNECTION::Delete();
  1147. }
  1148. else
  1149. {
  1150. fReceivePosted = 0;
  1151. }
  1152. //
  1153. // If the call has not been dispatched yet, DispatchBuffer needs to be freed
  1154. //
  1155. ASSERT(fCallDispatched == 0);
  1156. ASSERT(DispatchBuffer == 0);
  1157. if (Connection->fExclusive)
  1158. {
  1159. DeactivateCall();
  1160. Connection->CachedSCallAvailable = 1;
  1161. }
  1162. //
  1163. // Remove the reply reference for this call
  1164. //
  1165. OSF_SCALL::RemoveReference(); // CALL--
  1166. //
  1167. // Remove the dispatch reference for this call
  1168. //
  1169. OSF_SCALL::RemoveReference(); // CALL--
  1170. return fReceivePosted;
  1171. }
  1172. #define SC_CLEANUP(_status, _dne) {Status = _status; fDNE = _dne; goto Cleanup;}
  1173. BOOL
  1174. OSF_SCALL::ProcessReceivedPDU (
  1175. IN rpcconn_common * Packet,
  1176. IN unsigned int PacketLength,
  1177. IN BOOL fDispatch
  1178. )
  1179. /*++
  1180. Function Name:ProcessReceivedPDU
  1181. Parameters:
  1182. Description:
  1183. Returns:
  1184. --*/
  1185. {
  1186. RPC_STATUS Status = RPC_S_OK;
  1187. rpcconn_request *Request = (rpcconn_request *) Packet;
  1188. int FragmentLength = (int) PacketLength;
  1189. unsigned char PTYPE, Flags;
  1190. unsigned short OpNum;
  1191. unsigned long Drep;
  1192. int MyCallStack = CallStack;
  1193. BOOL fDNE = 0;
  1194. BOOL fReceivePosted = 0;
  1195. BOOL fCallCleanedUp = FALSE;
  1196. if (fSecurityFailure)
  1197. {
  1198. if (Packet->pfc_flags & PFC_LAST_FRAG)
  1199. {
  1200. Connection->TransFreeBuffer(Packet);
  1201. goto Cleanup2;
  1202. }
  1203. Connection->TransFreeBuffer(Packet);
  1204. return 0;
  1205. }
  1206. switch (Packet->PTYPE)
  1207. {
  1208. case rpc_request :
  1209. case rpc_response:
  1210. if (!fDispatch)
  1211. {
  1212. //
  1213. // This must be a request or response
  1214. // save the maximum of req/resonse size [i.e. sizeof request]
  1215. // also, we are not saving the first frag. here .. hence
  1216. // the approp. memory is already set aside
  1217. //
  1218. ASSERT((Connection->AuthInfo.AuthenticationLevel
  1219. == RPC_C_AUTHN_LEVEL_NONE)
  1220. || (SavedHeaderSize >= sizeof(rpcconn_request)));
  1221. if (Connection->AuthInfo.AuthenticationLevel
  1222. != RPC_C_AUTHN_LEVEL_NONE)
  1223. {
  1224. if (SavedHeader == NULL)
  1225. {
  1226. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 1);
  1227. }
  1228. RpcpMemoryCopy(SavedHeader, Packet, sizeof(rpcconn_request));
  1229. }
  1230. Status = ValidatePacket(Packet, PacketLength);
  1231. if (Status != RPC_S_OK )
  1232. {
  1233. ASSERT(Status == RPC_S_PROTOCOL_ERROR );
  1234. SC_CLEANUP(Status, 1);
  1235. }
  1236. }
  1237. if (Packet->call_id != CallId)
  1238. {
  1239. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  1240. }
  1241. Flags = Request->common.pfc_flags;
  1242. Drep = *((unsigned long *) Request->common.drep);
  1243. OpNum = Request->opnum;
  1244. PTYPE=Request->common.PTYPE;
  1245. Status = Connection->EatAuthInfoFromPacket(
  1246. Request,
  1247. &FragmentLength,
  1248. &SavedHeader,
  1249. &SavedHeaderSize);
  1250. if (Status != RPC_S_OK )
  1251. {
  1252. VALIDATE(Status)
  1253. {
  1254. RPC_S_PROTOCOL_ERROR,
  1255. ERROR_SHUTDOWN_IN_PROGRESS,
  1256. RPC_S_ACCESS_DENIED,
  1257. ERROR_PASSWORD_MUST_CHANGE,
  1258. ERROR_PASSWORD_EXPIRED,
  1259. ERROR_ACCOUNT_DISABLED,
  1260. ERROR_INVALID_LOGON_HOURS
  1261. } END_VALIDATE;
  1262. fSecurityFailure = 1;
  1263. if (Packet->pfc_flags & PFC_LAST_FRAG
  1264. || (Status == RPC_S_PROTOCOL_ERROR))
  1265. {
  1266. SC_CLEANUP(Status, 0);
  1267. }
  1268. SendFault(RPC_S_ACCESS_DENIED, 1);
  1269. Connection->TransFreeBuffer(Packet);
  1270. return 0;
  1271. }
  1272. //
  1273. // Ok, if the packet contains an object uuid, we need to shift
  1274. // the stub data so that the packet does not contain an object
  1275. // uuid.
  1276. //
  1277. if ((Flags & PFC_OBJECT_UUID) != 0)
  1278. {
  1279. if (CallStack != 0 )
  1280. {
  1281. //
  1282. // There can not be an object uuid in the message.
  1283. // This is an error.
  1284. //
  1285. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  1286. }
  1287. //
  1288. // First save away the object UUID so that we can get it later.
  1289. //
  1290. ObjectUuidSpecified = 1;
  1291. RpcpMemoryCopy(&ObjectUuid, Request + 1, sizeof(UUID));
  1292. if (DataConvertEndian(((unsigned char *) &Drep)) != 0 )
  1293. {
  1294. ByteSwapUuid(&ObjectUuid);
  1295. }
  1296. //
  1297. // Now shift the stub data so that the packet is as if there is
  1298. // no object UUID in the packet.
  1299. //
  1300. RpcpMemoryCopy(Request + 1,
  1301. ((unsigned char *) (Request + 1))
  1302. + sizeof(UUID), FragmentLength);
  1303. }
  1304. //
  1305. // we need to keep this peice of code here, because
  1306. // we need to allocate stuff in the callback case.
  1307. //
  1308. if (Flags & PFC_FIRST_FRAG)
  1309. {
  1310. //
  1311. // Optimize for the single PDU RPC case
  1312. //
  1313. if ((Flags & PFC_LAST_FRAG) != 0)
  1314. {
  1315. CurrentState = CallCompleted;
  1316. DispatchBuffer = (void *) (Request+1);
  1317. DispatchBufferOffset = FragmentLength;
  1318. //
  1319. // Buffers will be freed by callee
  1320. //
  1321. ASSERT(Status == RPC_S_OK);
  1322. return DispatchRPCCall (PTYPE, OpNum);
  1323. }
  1324. if (Request->alloc_hint)
  1325. {
  1326. AllocHint = Request->alloc_hint;
  1327. }
  1328. else
  1329. {
  1330. AllocHint = FragmentLength;
  1331. }
  1332. // check the packet size. Note that we check it on first frag
  1333. // only. If they decrease it, we don't care. We will recheck
  1334. // it in all paths below if caller icnreases it.
  1335. if (CurrentBinding->GetInterface()->CallSizeLimitReached(AllocHint))
  1336. {
  1337. fSecurityFailure = 1;
  1338. SendFault(RPC_S_ACCESS_DENIED, 1);
  1339. Connection->TransFreeBuffer(Packet);
  1340. return 0;
  1341. }
  1342. DispatchBufferOffset = 0;
  1343. Status = GetBufferDo(&DispatchBuffer, AllocHint);
  1344. if (Status != RPC_S_OK)
  1345. {
  1346. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 0);
  1347. }
  1348. }
  1349. else
  1350. {
  1351. if (DispatchBuffer == 0)
  1352. {
  1353. //
  1354. // Looks like it is the first fragment on the call, and it doesn't have
  1355. // the first-frag bit set
  1356. //
  1357. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  1358. }
  1359. }
  1360. if (fPipeCall == 0 || CallStack)
  1361. {
  1362. //
  1363. // Non-pipe case
  1364. //
  1365. if (DispatchBufferOffset+FragmentLength > AllocHint)
  1366. {
  1367. Status = GetBufferDo(
  1368. &DispatchBuffer,
  1369. DispatchBufferOffset+FragmentLength,
  1370. 1,
  1371. DispatchBufferOffset);
  1372. if (Status != RPC_S_OK)
  1373. {
  1374. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 0);
  1375. }
  1376. AllocHint = DispatchBufferOffset + FragmentLength;
  1377. if (CurrentBinding->GetInterface()->
  1378. CallSizeLimitReached(AllocHint))
  1379. {
  1380. fSecurityFailure = 1;
  1381. if (Packet->pfc_flags & PFC_LAST_FRAG)
  1382. {
  1383. SC_CLEANUP(RPC_S_ACCESS_DENIED, 0);
  1384. }
  1385. SendFault(RPC_S_ACCESS_DENIED, 1);
  1386. Connection->TransFreeBuffer(Packet);
  1387. return 0;
  1388. }
  1389. }
  1390. //
  1391. // Copy current buffer into the dispatch buffer
  1392. //
  1393. RpcpMemoryCopy(
  1394. (char *) DispatchBuffer+DispatchBufferOffset,
  1395. Request+1,
  1396. FragmentLength);
  1397. DispatchBufferOffset += FragmentLength;
  1398. Connection->TransFreeBuffer(Packet);
  1399. if (Flags & PFC_LAST_FRAG)
  1400. {
  1401. CurrentState = CallCompleted;
  1402. //
  1403. // Buffers will be freed by callee
  1404. //
  1405. ASSERT(Status == RPC_S_OK);
  1406. return DispatchRPCCall (PTYPE, OpNum);
  1407. }
  1408. }
  1409. else
  1410. {
  1411. //
  1412. // Pipe call
  1413. //
  1414. ASSERT(PTYPE == rpc_request);
  1415. //
  1416. // If it is a pipe call, we need to dispatch as soon as we get
  1417. // at least alloc hint bytes. If it is not a pipe call, we wait until
  1418. // we get the last fragment.
  1419. //
  1420. if (!fCallDispatched)
  1421. {
  1422. if (DispatchBufferOffset+FragmentLength > AllocHint)
  1423. {
  1424. Status = GetBufferDo(
  1425. &DispatchBuffer,
  1426. DispatchBufferOffset+FragmentLength,
  1427. 1,
  1428. DispatchBufferOffset);
  1429. if (Status != RPC_S_OK)
  1430. {
  1431. SC_CLEANUP(Status, 0);
  1432. }
  1433. AllocHint = DispatchBufferOffset + FragmentLength;
  1434. if (CurrentBinding->GetInterface()->
  1435. CallSizeLimitReached(AllocHint))
  1436. {
  1437. fSecurityFailure = 1;
  1438. if (Packet->pfc_flags & PFC_LAST_FRAG)
  1439. {
  1440. SC_CLEANUP(RPC_S_ACCESS_DENIED, 0);
  1441. }
  1442. SendFault(RPC_S_ACCESS_DENIED, 1);
  1443. Connection->TransFreeBuffer(Packet);
  1444. return 0;
  1445. }
  1446. }
  1447. //
  1448. // Copy the buffer in
  1449. //
  1450. RpcpMemoryCopy(
  1451. (char *) DispatchBuffer+DispatchBufferOffset,
  1452. Request+1,
  1453. FragmentLength);
  1454. DispatchBufferOffset += FragmentLength;
  1455. Connection->TransFreeBuffer(Packet);
  1456. ASSERT(Status == RPC_S_OK);
  1457. if (DispatchBufferOffset == AllocHint)
  1458. {
  1459. ASSERT(fSecurityFailure == 0);
  1460. if (Flags & PFC_LAST_FRAG)
  1461. {
  1462. CurrentState = CallCompleted;
  1463. }
  1464. else
  1465. {
  1466. //
  1467. // Buffers will be freed by callee
  1468. //
  1469. DispatchFlags = 0;
  1470. }
  1471. return DispatchRPCCall (PTYPE, OpNum);
  1472. }
  1473. }
  1474. else
  1475. {
  1476. //
  1477. // Once a pipe call is dispatched, we don't care about how
  1478. // big it gets. The manager routine has the option to abandon
  1479. // the call whenever it wants.
  1480. //
  1481. CallMutex.Request();
  1482. if ((Connection->fExclusive)
  1483. && (Connection->CachedSCallAvailable))
  1484. {
  1485. CallMutex.Clear();
  1486. ASSERT (Connection->CachedSCall == this);
  1487. Connection->TransFreeBuffer(Packet);
  1488. return 0;
  1489. }
  1490. //
  1491. // A pipe call is already in progress. We simply need to queue
  1492. // the buffer into the buffer queue. It get picked up later.
  1493. //
  1494. LogEvent(SU_SCALL, EV_BUFFER_IN, Request, this, 0, 1, 0);
  1495. if (BufferQueue.PutOnQueue(Request+1, FragmentLength))
  1496. {
  1497. CallMutex.Clear();
  1498. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 0);
  1499. }
  1500. RcvBufferLength += FragmentLength;
  1501. if ((Flags & PFC_LAST_FRAG) != 0)
  1502. {
  1503. CurrentState = CallCompleted;
  1504. }
  1505. if (pAsync == 0)
  1506. {
  1507. if (BufferQueue.Size() >= 4
  1508. && Connection->fExclusive
  1509. && CurrentState != CallCompleted)
  1510. {
  1511. fPeerChoked = 1;
  1512. fReceivePosted = 1;
  1513. }
  1514. CallMutex.Clear();
  1515. SyncEvent.Raise();
  1516. }
  1517. else
  1518. {
  1519. if (NeededLength > 0 && ((CurrentState == CallCompleted)
  1520. || (RcvBufferLength >= NeededLength)))
  1521. {
  1522. IssueNotification(RpcReceiveComplete);
  1523. }
  1524. else
  1525. {
  1526. //
  1527. // Cannot do this for non-exclusive connections because
  1528. // other calls will get blocked
  1529. //
  1530. if (BufferQueue.Size() >= 4
  1531. && Connection->fExclusive
  1532. && CurrentState != CallCompleted)
  1533. {
  1534. fPeerChoked = 1;
  1535. fReceivePosted = 1;
  1536. }
  1537. }
  1538. CallMutex.Clear();
  1539. }
  1540. //
  1541. // We received pipe data
  1542. // there's nothing to cleanup
  1543. //
  1544. return fReceivePosted;
  1545. }
  1546. }
  1547. return 0;
  1548. case rpc_fault:
  1549. Status = ((rpcconn_fault *)Packet)->status;
  1550. if ((Status == 0) &&
  1551. (Packet->frag_length >= FaultSizeWithoutEEInfo + 4))
  1552. {
  1553. //
  1554. // DCE 1.0.x style fault status:
  1555. // Zero status and stub data contains the fault.
  1556. //
  1557. Status = *(unsigned long *) ((unsigned char *)Packet + FaultSizeWithoutEEInfo);
  1558. }
  1559. if (DataConvertEndian(Packet->drep) != 0)
  1560. {
  1561. Status = RpcpByteSwapLong(Status);
  1562. }
  1563. if (Status == 0)
  1564. {
  1565. Status = RPC_S_CALL_FAILED;
  1566. }
  1567. AsyncStatus = MapFromNcaStatusCode(Status);
  1568. CurrentState = ReceivedFault;
  1569. SyncEvent.Raise();
  1570. Connection->TransFreeBuffer(Packet);
  1571. return 0;
  1572. case rpc_cancel:
  1573. case rpc_orphaned:
  1574. CancelPending = 1;
  1575. Connection->TransFreeBuffer(Packet);
  1576. return 0;
  1577. default :
  1578. //
  1579. // We should never reach here
  1580. //
  1581. ASSERT(0);
  1582. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  1583. break;
  1584. }
  1585. Cleanup:
  1586. //
  1587. // If we reach here it means that the call failed
  1588. // Every call to ProcessReceivedPDU has a reference on the call,
  1589. // the call is alive here
  1590. //
  1591. ASSERT(Status != RPC_S_OK);
  1592. Connection->TransFreeBuffer(Packet);
  1593. if ((MyCallStack == 0) && (fCallDispatched == 0))
  1594. {
  1595. CleanupCallAndSendFault(Status, 0);
  1596. fCallCleanedUp = TRUE;
  1597. }
  1598. else
  1599. {
  1600. SendFault(Status, 0);
  1601. }
  1602. Cleanup2:
  1603. //
  1604. // There is a chance that this error happened due to a bogus packet
  1605. // We need to make sure that we don't something bad in that case
  1606. //
  1607. if (MyCallStack == 0)
  1608. {
  1609. if (fCallDispatched == 0)
  1610. {
  1611. if (fCallCleanedUp == FALSE)
  1612. CleanupCall();
  1613. //
  1614. // We cannot continue to use this connection
  1615. //
  1616. Connection->fDontFlush = (CurrentState == NewRequest);
  1617. Connection->OSF_SCONNECTION::Delete();
  1618. //
  1619. // Remove the reference held by the dispatch
  1620. // thread
  1621. //
  1622. OSF_SCALL::RemoveReference(); // CALL--
  1623. //
  1624. // We just finished sending the reply (the fault)
  1625. // remove the reply reference
  1626. //
  1627. OSF_SCALL::RemoveReference(); // CALL--
  1628. }
  1629. else
  1630. {
  1631. //
  1632. // The call will go away when the dispatch completes
  1633. //
  1634. Connection->OSF_SCONNECTION::Delete();
  1635. }
  1636. return 1;
  1637. }
  1638. return 0;
  1639. }
  1640. RPC_STATUS
  1641. OSF_SCALL::Receive (
  1642. IN OUT PRPC_MESSAGE Message,
  1643. IN unsigned int Size
  1644. )
  1645. /*++
  1646. Function Name:Receive
  1647. Parameters:
  1648. Description:
  1649. Returns:
  1650. --*/
  1651. {
  1652. RPC_STATUS Status = RPC_S_OK;
  1653. BOOL fForceExtra = FALSE;
  1654. if (!EXTRA(Message) && Message->Buffer)
  1655. {
  1656. ASSERT(Message->Buffer != DispatchBuffer);
  1657. FreeBufferDo((char *)Message->Buffer);
  1658. Message->Buffer = 0;
  1659. Message->BufferLength = 0;
  1660. }
  1661. if (fSecurityFailure)
  1662. {
  1663. return RPC_S_ACCESS_DENIED;
  1664. }
  1665. Message->DataRepresentation = Connection->DataRep;
  1666. while (TRUE)
  1667. {
  1668. switch (CurrentState)
  1669. {
  1670. case CallCompleted:
  1671. //
  1672. // When the last frag is received on this call, the call state
  1673. // transitions to the Complete state. The call states are valid
  1674. // only when using Async and Pipes
  1675. //
  1676. Status = GetCoalescedBuffer(Message, fForceExtra);
  1677. break;
  1678. case CallCancelled:
  1679. Status = RPC_S_CALL_CANCELLED;
  1680. break;
  1681. case CallAborted:
  1682. ASSERT(AsyncStatus != RPC_S_OK);
  1683. Status = AsyncStatus;
  1684. break;
  1685. default:
  1686. if (RcvBufferLength > Connection->MaxFrag)
  1687. {
  1688. Status = GetCoalescedBuffer(Message, fForceExtra);
  1689. if (Status != RPC_S_OK)
  1690. {
  1691. break;
  1692. }
  1693. if (PARTIAL(Message) && Message->BufferLength >= Size)
  1694. {
  1695. break;
  1696. }
  1697. fForceExtra = TRUE;
  1698. }
  1699. else
  1700. {
  1701. //
  1702. // the call is not yet complete, wait for it.
  1703. //
  1704. SyncEvent.Wait();
  1705. }
  1706. continue;
  1707. }
  1708. break;
  1709. }
  1710. return Status;
  1711. }
  1712. RPC_STATUS
  1713. OSF_SCALL::AsyncReceive (
  1714. IN OUT PRPC_MESSAGE Message,
  1715. IN unsigned int Size
  1716. )
  1717. /*++
  1718. Function Name:AsyncReceive
  1719. Parameters:
  1720. Description:
  1721. Returns:
  1722. --*/
  1723. {
  1724. RPC_STATUS Status ;
  1725. int Extra = IsExtraMessage(Message);
  1726. ASSERT(EXTRA(Message) == 0 && PARTIAL(Message));
  1727. if (Message->Buffer)
  1728. {
  1729. ASSERT(Message->Buffer != DispatchBuffer);
  1730. FreeBufferDo((char *)Message->Buffer);
  1731. Message->Buffer = 0;
  1732. }
  1733. if (fSecurityFailure)
  1734. {
  1735. return RPC_S_ACCESS_DENIED;
  1736. }
  1737. switch (CurrentState)
  1738. {
  1739. case CallCompleted:
  1740. Status = GetCoalescedBuffer(Message, FALSE);
  1741. Message->DataRepresentation = Connection->DataRep;
  1742. break;
  1743. case CallCancelled:
  1744. Status = RPC_S_CALL_CANCELLED;
  1745. break;
  1746. case CallAborted:
  1747. Status = AsyncStatus;
  1748. break;
  1749. default:
  1750. CallMutex.Request();
  1751. if (RcvBufferLength < Size)
  1752. {
  1753. if (NOTIFY(Message))
  1754. {
  1755. NeededLength = Size ;
  1756. }
  1757. CallMutex.Clear() ;
  1758. return RPC_S_ASYNC_CALL_PENDING;
  1759. }
  1760. else
  1761. {
  1762. Status = GetCoalescedBuffer(Message, FALSE);
  1763. Message->DataRepresentation = Connection->DataRep;
  1764. }
  1765. CallMutex.Clear();
  1766. break;
  1767. }
  1768. return Status ;
  1769. }
  1770. RPC_STATUS
  1771. OSF_SCALL::SetAsyncHandle (
  1772. IN PRPC_ASYNC_STATE pAsync
  1773. )
  1774. /*++
  1775. Function Name:SetAsyncHandle
  1776. Parameters:
  1777. Description:
  1778. Returns:
  1779. --*/
  1780. {
  1781. this->pAsync = pAsync;
  1782. Thread->fAsync = TRUE;
  1783. if (DebugCell)
  1784. {
  1785. DebugCell->CallFlags |= DBGCELL_ASYNC_CALL;
  1786. }
  1787. return RPC_S_OK;
  1788. }
  1789. RPC_STATUS
  1790. OSF_SCALL::AbortAsyncCall (
  1791. IN PRPC_ASYNC_STATE pAsync,
  1792. IN unsigned long ExceptionCode
  1793. )
  1794. /*++
  1795. Function Name:AbortAsyncCall
  1796. Parameters:
  1797. Description:
  1798. Returns:
  1799. --*/
  1800. {
  1801. ASSERT(CurrentBinding);
  1802. CleanupCallAndSendFault(ExceptionCode, 0);
  1803. //
  1804. // The call was aborted asynchronously
  1805. // Remove the reference held for the reply.
  1806. //
  1807. RemoveReference(); // CALL--
  1808. return RPC_S_OK;
  1809. }
  1810. RPC_STATUS
  1811. OSF_SCALL::GetCoalescedBuffer (
  1812. IN PRPC_MESSAGE Message,
  1813. BOOL fForceExtra
  1814. )
  1815. /*++
  1816. Function Name:GetCoalescedBuffer
  1817. Parameters:
  1818. Message - the message structure that will receive the params
  1819. Description:
  1820. This routine will coalesce the buffers in the buffer queue into a single
  1821. buffer and return it in the Message structure. If the RPC_BUFFER_EXTRA
  1822. flag is set, the data is appended to the existing buffer in Message->Buffer.
  1823. Returns:
  1824. RPC_S_OK - the function was successful in doing its job
  1825. RPC_S_OUT_OF_MEMORY - ran out of memory.
  1826. --*/
  1827. {
  1828. char *Current;
  1829. UINT bufferlength;
  1830. UINT TotalLength;
  1831. RPC_STATUS Status;
  1832. void *NewBuffer, *Buffer;
  1833. int Extra = IsExtraMessage(Message);
  1834. BOOL fExtendedExtra = Extra | fForceExtra;
  1835. BOOL fSubmitReceive = 0;
  1836. CallMutex.Request();
  1837. if (RcvBufferLength == 0)
  1838. {
  1839. CallMutex.Clear();
  1840. return RPC_S_OK;
  1841. }
  1842. if (fExtendedExtra)
  1843. {
  1844. TotalLength = RcvBufferLength + Message->BufferLength;
  1845. }
  1846. else
  1847. {
  1848. TotalLength = RcvBufferLength;
  1849. }
  1850. Status = TransGetBuffer (&NewBuffer,
  1851. TotalLength+sizeof(rpcconn_request));
  1852. if (Status != RPC_S_OK)
  1853. {
  1854. CallMutex.Clear();
  1855. return RPC_S_OUT_OF_MEMORY;
  1856. }
  1857. NewBuffer = (char *) NewBuffer+sizeof(rpcconn_request);
  1858. if (fExtendedExtra && Message->Buffer)
  1859. {
  1860. RpcpMemoryCopy(NewBuffer, Message->Buffer, Message->BufferLength);
  1861. Current = (char *) NewBuffer + Message->BufferLength;
  1862. Connection->TransFreeBuffer((char *) Message->Buffer-sizeof(rpcconn_request));
  1863. if (Extra)
  1864. {
  1865. //
  1866. // Update the dispatch buffer, but only for the true EXTRA flag, not
  1867. // for the forced extra
  1868. //
  1869. ASSERT(Message->ReservedForRuntime) ;
  1870. ((PRPC_RUNTIME_INFO)Message->ReservedForRuntime)->OldBuffer = NewBuffer;
  1871. if ((CallStack == 0) && (Message->Buffer == DispatchBuffer))
  1872. DispatchBuffer = NewBuffer;
  1873. }
  1874. }
  1875. else
  1876. {
  1877. Current = (char *) NewBuffer;
  1878. }
  1879. while ((Buffer = BufferQueue.TakeOffQueue(&bufferlength)) != 0)
  1880. {
  1881. RpcpMemoryCopy(Current, Buffer, bufferlength);
  1882. Current += bufferlength;
  1883. Connection->TransFreeBuffer((char *) Buffer-sizeof(rpcconn_request));
  1884. }
  1885. Message->Buffer = NewBuffer;
  1886. Message->BufferLength = TotalLength;
  1887. RcvBufferLength = 0;
  1888. if (CurrentState == CallCompleted)
  1889. {
  1890. Message->RpcFlags = RPC_BUFFER_COMPLETE;
  1891. }
  1892. if (fPeerChoked)
  1893. {
  1894. fSubmitReceive = 1;
  1895. fPeerChoked = 0;
  1896. }
  1897. CallMutex.Clear();
  1898. if (fSubmitReceive)
  1899. {
  1900. Connection->TransAsyncReceive();
  1901. }
  1902. return RPC_S_OK;
  1903. }
  1904. void
  1905. OSF_SCALL::DispatchHelper ()
  1906. {
  1907. THREAD *MyThread;
  1908. RPC_STATUS Status, ExceptionCode;
  1909. DebugCallInfo *Cell;
  1910. DebugThreadInfo *ThreadCell;
  1911. ULONG TickCount;
  1912. PRPC_DISPATCH_TABLE DispatchTableToUse;
  1913. //
  1914. // We have a new RPC call. We need to dispatch it.
  1915. //
  1916. FirstCallRuntimeInfo.Length = sizeof(RPC_RUNTIME_INFO) ;
  1917. FirstCallRpcMessage.Handle = (RPC_BINDING_HANDLE) this;
  1918. FirstCallRpcMessage.Buffer = DispatchBuffer;
  1919. FirstCallRpcMessage.BufferLength = DispatchBufferOffset;
  1920. FirstCallRpcMessage.RpcFlags = DispatchFlags ;
  1921. FirstCallRpcMessage.DataRepresentation = Connection->DataRep;
  1922. FirstCallRpcMessage.ReservedForRuntime = &FirstCallRuntimeInfo ;
  1923. CurrentBinding->GetSelectedTransferSyntaxAndDispatchTable(&FirstCallRpcMessage.TransferSyntax,
  1924. &DispatchTableToUse);
  1925. FirstCallRpcMessage.ProcNum = ProcNum;
  1926. MyThread = (THREAD *) RpcpGetThreadPointer();
  1927. ASSERT(MyThread);
  1928. RpcpSetThreadContextWithThread(MyThread, this);
  1929. Thread = MyThread;
  1930. ThreadCell = Thread->DebugCell;
  1931. if (ThreadCell)
  1932. {
  1933. TickCount = NtGetTickCount();
  1934. Cell = DebugCell;
  1935. Cell->CallID = CallId;
  1936. Cell->ProcNum = (unsigned short)ProcNum;
  1937. Cell->Status = csDispatched;
  1938. Cell->LastUpdateTime = TickCount;
  1939. Cell->InterfaceUUIDStart
  1940. = CurrentBinding->GetInterface()->GetInterfaceFirstDWORD();
  1941. ThreadCell->Status = dtsDispatched;
  1942. ThreadCell->LastUpdateTime = TickCount;
  1943. GetDebugCellIDFromDebugCell((DebugCellUnion *)ThreadCell, &MyThread->DebugCellTag, &Cell->ServicingTID);
  1944. }
  1945. //
  1946. // Actually dispatch the RPC call
  1947. //
  1948. if ( ObjectUuidSpecified != 0 )
  1949. {
  1950. Status = CurrentBinding->GetInterface()->DispatchToStubWithObject(
  1951. &FirstCallRpcMessage,
  1952. &ObjectUuid,
  1953. 0,
  1954. DispatchTableToUse,
  1955. &ExceptionCode);
  1956. }
  1957. else
  1958. {
  1959. Status = CurrentBinding->GetInterface()->DispatchToStub(
  1960. &FirstCallRpcMessage,
  1961. 0,
  1962. DispatchTableToUse,
  1963. &ExceptionCode);
  1964. }
  1965. //
  1966. // We need to insure that the server thread stops impersonating
  1967. // the client at the end of the call, so we go ahead and call
  1968. // RevertToSelf, and dont worry about the return value.
  1969. //
  1970. OSF_SCALL::RevertToSelf();
  1971. if (ThreadCell)
  1972. {
  1973. ThreadCell->Status = dtsProcessing;
  1974. ThreadCell->LastUpdateTime = NtGetTickCount();
  1975. }
  1976. if(Status != RPC_S_OK)
  1977. {
  1978. //Thread = 0;
  1979. VALIDATE(Status)
  1980. {
  1981. RPC_S_PROCNUM_OUT_OF_RANGE,
  1982. RPC_S_UNKNOWN_IF,
  1983. RPC_S_NOT_LISTENING,
  1984. RPC_S_SERVER_TOO_BUSY,
  1985. RPC_S_UNSUPPORTED_TYPE,
  1986. RPC_P_EXCEPTION_OCCURED
  1987. } END_VALIDATE;
  1988. BOOL fDNE = 1;
  1989. if( Status == RPC_P_EXCEPTION_OCCURED )
  1990. {
  1991. fDNE=0;
  1992. Status = ExceptionCode;
  1993. }
  1994. else if ( Status == RPC_S_NOT_LISTENING )
  1995. {
  1996. Status = RPC_S_SERVER_TOO_BUSY;
  1997. }
  1998. while (CurrentBufferLength)
  1999. {
  2000. #if DBG
  2001. PrintToDebugger("RPC: Waiting for the async send....\n");
  2002. #endif
  2003. Sleep(200);
  2004. }
  2005. //
  2006. // There may be another thread still sending data on this call
  2007. // This will be taken care of in CleanupCall
  2008. //
  2009. CleanupCallAndSendFault(Status, fDNE);
  2010. // It is tempting to think that since an exception was
  2011. // raised, there will be no reply. However, in the pipe
  2012. // case we may make a bunch of sends, and still get
  2013. // an exception in the end. If there were no sends,
  2014. // remove the reply reference for the call
  2015. if (FirstSend)
  2016. {
  2017. OSF_SCALL::RemoveReference(); // CALL--
  2018. }
  2019. goto Cleanup;
  2020. }
  2021. if (MyThread->IsSyncCall())
  2022. {
  2023. ASSERT( FirstCallRpcMessage.Buffer != 0 );
  2024. if ( CallOrphaned )
  2025. {
  2026. CallOrphaned = 0;
  2027. Thread = 0;
  2028. //
  2029. // clear cancel if thread didn\'t notice it.
  2030. //
  2031. TestCancel();
  2032. goto Cleanup;
  2033. }
  2034. FirstCallRpcMessage.RpcFlags = 0;
  2035. OSF_SCALL::Send(&FirstCallRpcMessage);
  2036. }
  2037. Cleanup:
  2038. RpcpSetThreadContextWithThread(MyThread, 0);
  2039. }
  2040. BOOL
  2041. OSF_SCALL::DispatchRPCCall (
  2042. IN unsigned char PTYPE,
  2043. IN unsigned short OpNum
  2044. )
  2045. /*++
  2046. Routine Description:
  2047. Dispatch an new RPC call, or wake up thread that will dispatch a callback.
  2048. Arguments:
  2049. Packet - Supplies the packet we received from the connection. Ownership
  2050. of this buffer passes to this routine.
  2051. PacketLength - Supplies the length of the packet in bytes.
  2052. Return Value:
  2053. A non-zero return value indicates that the connection should not
  2054. be placed in the receive any state; instead, the thread should just
  2055. forget about the connection and go back to waiting for more new
  2056. procedure calls.
  2057. --*/
  2058. {
  2059. RPC_STATUS Status;
  2060. BOOL fNeedToSendFault;
  2061. OSF_SCONNECTION *LocalConnection;
  2062. if (CallStack > 0)
  2063. {
  2064. //
  2065. // This is a callback request/response. We just need to signal the Event
  2066. // and have it pick up the call
  2067. //
  2068. if (PTYPE == rpc_request)
  2069. {
  2070. CurrentState = ReceivedCallback;
  2071. ProcNum = OpNum;
  2072. }
  2073. else
  2074. {
  2075. CurrentState = ReceivedCallbackReply;
  2076. }
  2077. SyncEvent.Raise();
  2078. return 0;
  2079. }
  2080. ProcNum = OpNum;
  2081. fCallDispatched = 1;
  2082. if (Connection->fExclusive == 0 && Connection->MaybeQueueThisCall(this))
  2083. {
  2084. //
  2085. // We don't get to dispatch right now, looks like another call is
  2086. // currently dispatched. When the current call is done, it will do the
  2087. // right thing
  2088. //
  2089. return 0;
  2090. }
  2091. fNeedToSendFault = FALSE;
  2092. //
  2093. // Looks like we are really going to dispatch a call
  2094. // kick off another thread to go and pick up more requests
  2095. //
  2096. Status = Address->CreateThread();
  2097. if (Status == RPC_S_OK)
  2098. {
  2099. //
  2100. // Post another receive
  2101. //
  2102. Status = Connection->TransAsyncReceive();
  2103. }
  2104. else
  2105. {
  2106. Status = RPC_S_OUT_OF_MEMORY;
  2107. fNeedToSendFault = TRUE;
  2108. }
  2109. if (Status != RPC_S_OK)
  2110. {
  2111. FreeBufferDo(DispatchBuffer);
  2112. if (fNeedToSendFault)
  2113. CleanupCallAndSendFault(Status, 0);
  2114. else
  2115. CleanupCall();
  2116. if (Connection->fExclusive == 0)
  2117. {
  2118. //
  2119. // By the time we get here, calls may have piled up
  2120. //
  2121. Connection->AbortQueuedCalls();
  2122. }
  2123. //
  2124. // We cannot continue to use this connection
  2125. //
  2126. Connection->fDontFlush = (CurrentState == NewRequest);
  2127. Connection->Delete();
  2128. //
  2129. // Remove the reply reference
  2130. //
  2131. RemoveReference(); // CALL--
  2132. //
  2133. // Remove the dispatch reference
  2134. //
  2135. RemoveReference(); // CALL--
  2136. return 1;
  2137. }
  2138. // the call may have been cleaned up after this (though not
  2139. // destroyed) - save the connection in a local variable
  2140. LocalConnection = Connection;
  2141. //
  2142. // Dispatch the current call
  2143. //
  2144. DispatchHelper();
  2145. if (LocalConnection->fExclusive == 0)
  2146. {
  2147. LocalConnection->DispatchQueuedCalls();
  2148. }
  2149. //
  2150. // Remove the dispatch reference
  2151. //
  2152. RemoveReference(); // CALL--
  2153. return 1;
  2154. }
  2155. RPC_STATUS
  2156. OSF_SCALL::SendNextFragment (
  2157. void
  2158. )
  2159. /*++
  2160. Function Name:SendNextFragment
  2161. Description:
  2162. Send the next response fragment
  2163. Returns:
  2164. --*/
  2165. {
  2166. RPC_STATUS Status;
  2167. RPC_STATUS RpcStatus2;
  2168. rpcconn_common * pFragment;
  2169. BOOL LastFragmentFlag;
  2170. ULONG PacketLength;
  2171. ULONG MaxDataLength = MaximumFragmentLength
  2172. - sizeof(rpcconn_response) - MaxSecuritySize;
  2173. unsigned char *ReservedForSecurity = (unsigned char *) CurrentBuffer
  2174. + CurrentOffset + CurrentBufferLength
  2175. + Connection->AdditionalSpaceForSecurity;
  2176. pFragment = (rpcconn_common *)
  2177. ((char *) CurrentBuffer+CurrentOffset-sizeof(rpcconn_response));
  2178. if (CurrentBuffer == LastBuffer
  2179. && CurrentBufferLength <= MaxDataLength)
  2180. {
  2181. LastFragmentFlag = 1;
  2182. PacketLength = CurrentBufferLength;
  2183. }
  2184. else
  2185. {
  2186. //
  2187. // Each outstanding send needs to hold a reference
  2188. // on the call. Since the call holds a reference
  2189. // on the connection. The connection will also be alive
  2190. //
  2191. AddReference(); // CALL++
  2192. LastFragmentFlag = 0;
  2193. PacketLength = MaxDataLength;
  2194. }
  2195. ConstructPacket(pFragment, rpc_response,
  2196. PacketLength+sizeof(rpcconn_response)+MaxSecuritySize);
  2197. if (FirstSend)
  2198. {
  2199. FirstSend = 0;
  2200. pFragment->pfc_flags |= PFC_FIRST_FRAG;
  2201. }
  2202. ((rpcconn_response *) pFragment)->alloc_hint = CurrentBufferLength;
  2203. ((rpcconn_response *) pFragment)->p_cont_id = (unsigned char) CurrentBinding->GetPresentationContext();
  2204. ((rpcconn_response *) pFragment)->alert_count = (unsigned char) 0;
  2205. ((rpcconn_response *) pFragment)->reserved = 0;
  2206. pFragment->call_id = CallId;
  2207. LogEvent(SU_SCALL, EV_BUFFER_OUT, this, pFragment, LastFragmentFlag, 1);
  2208. if (LastFragmentFlag)
  2209. {
  2210. char *BufferToFree = (char *) CurrentBuffer-sizeof(rpcconn_response);
  2211. int MyMaxFrag = MaximumFragmentLength;
  2212. int MyMaxSec = MaxSecuritySize;
  2213. CurrentBufferLength = 0;
  2214. CleanupCall();
  2215. if (Connection->IsHttpTransport())
  2216. {
  2217. RpcStatus2 = Connection->SetLastBufferToFree (BufferToFree);
  2218. VALIDATE(RpcStatus2)
  2219. {
  2220. RPC_S_OK,
  2221. RPC_S_CANNOT_SUPPORT
  2222. } END_VALIDATE;
  2223. // if the transport does not support SetLastBufferToFree, it will
  2224. // return RPC_S_CANNOT_SUPPORT. In this case we retain ownership of
  2225. // the buffer.
  2226. }
  2227. //
  2228. // The call should still be alive at this point because the caller
  2229. // of this function has not release the send reference
  2230. //
  2231. Status = Connection->SendFragment(
  2232. pFragment,
  2233. LastFragmentFlag,
  2234. sizeof(rpcconn_response),
  2235. MyMaxSec,
  2236. PacketLength,
  2237. MyMaxFrag,
  2238. ReservedForSecurity);
  2239. //
  2240. // Last send always succeeds
  2241. //
  2242. Status = RPC_S_OK;
  2243. if ((Connection->IsHttpTransport() == FALSE) || (RpcStatus2 != RPC_S_OK))
  2244. Connection->TransFreeBuffer(BufferToFree);
  2245. }
  2246. else
  2247. {
  2248. Status = Connection->SendFragment(
  2249. pFragment,
  2250. LastFragmentFlag,
  2251. sizeof(rpcconn_response),
  2252. MaxSecuritySize,
  2253. PacketLength,
  2254. MaximumFragmentLength,
  2255. ReservedForSecurity,
  2256. TRUE,
  2257. SendContext) ;
  2258. if (Status != RPC_S_OK)
  2259. {
  2260. CurrentBufferLength = 0;
  2261. //
  2262. // Remove the reference for the outstanding send
  2263. //
  2264. OSF_SCALL::RemoveReference(); // CALL--
  2265. }
  2266. }
  2267. return Status;
  2268. }
  2269. RPC_STATUS
  2270. OSF_SCALL::Send (
  2271. IN OUT PRPC_MESSAGE Message
  2272. )
  2273. /*++
  2274. Routine Description:
  2275. Arguments:
  2276. Message - Supplies the buffer containing the response to be sent
  2277. --*/
  2278. {
  2279. void *NewBuffer;
  2280. int RemainingLength = 0;
  2281. RPC_STATUS Status = RPC_S_OK;
  2282. RPC_STATUS StatusToReturn = RPC_S_OK;
  2283. ULONG MaxDataLength = MaximumFragmentLength
  2284. - sizeof(rpcconn_response) - MaxSecuritySize;
  2285. BOOL fOutstandingSend = 0;
  2286. BOOL fBufferSent = 0;
  2287. ASSERT(LastBuffer == 0);
  2288. if (PARTIAL(Message))
  2289. {
  2290. if (Message->BufferLength < MaxDataLength)
  2291. {
  2292. return RPC_S_SEND_INCOMPLETE;
  2293. }
  2294. RemainingLength = Message->BufferLength % MaxDataLength;
  2295. if (RemainingLength)
  2296. {
  2297. Status = GetBufferDo(&NewBuffer, RemainingLength);
  2298. if (Status != RPC_S_OK)
  2299. {
  2300. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  2301. FreeBufferDo(Message->Buffer);
  2302. return Status;
  2303. }
  2304. Message->BufferLength -= RemainingLength;
  2305. RpcpMemoryCopy(NewBuffer,
  2306. (char *) Message->Buffer+Message->BufferLength,
  2307. RemainingLength);
  2308. }
  2309. }
  2310. else
  2311. {
  2312. LastBuffer = Message->Buffer;
  2313. }
  2314. while (1)
  2315. {
  2316. CallMutex.Request();
  2317. if (CurrentBuffer == 0)
  2318. {
  2319. //
  2320. // If CurrentBuffer == 0, it means that the call is idle
  2321. //
  2322. CurrentOffset = 0;
  2323. CurrentBuffer = Message->Buffer;
  2324. CurrentBufferLength = Message->BufferLength;
  2325. fBufferSent = TRUE;
  2326. if ((CurrentBuffer != LastBuffer)
  2327. || (CurrentBufferLength > MaxDataLength))
  2328. {
  2329. UpdateBuffersAfterNonLastSend(
  2330. NewBuffer,
  2331. RemainingLength,
  2332. Message);
  2333. fOutstandingSend = TRUE;
  2334. }
  2335. CallMutex.Clear();
  2336. Status = SendNextFragment();
  2337. if (Status && fOutstandingSend)
  2338. {
  2339. // if we failed on a non last send, there will be
  2340. // nobody else to drive the call - we need to
  2341. // return the unsent buffer to Message->Buffer,
  2342. // so that it can be freed below.
  2343. Message->Buffer = CurrentBuffer;
  2344. CleanupCall();
  2345. }
  2346. // N.B. Do not touch any call members after
  2347. // this point if the call succeeded - you may affect
  2348. // the next call.
  2349. // This is because once we send, we may get swapped out
  2350. // and other threads could drive the call to
  2351. // completion (i.e. send all fragments and cleanup
  2352. // the call on the last fragment). From then on,
  2353. // it may be another call we're writing on.
  2354. if (fOutstandingSend && RemainingLength && (Status == RPC_S_OK))
  2355. StatusToReturn = RPC_S_SEND_INCOMPLETE;
  2356. }
  2357. else
  2358. {
  2359. if ((AsyncStatus == RPC_S_OK) && (pAsync == 0) && (BufferQueue.Size() >= 4))
  2360. {
  2361. fChoked = 1;
  2362. CallMutex.Clear();
  2363. SyncEvent.Wait();
  2364. // if the call already failed, bail out
  2365. if (AsyncStatus != RPC_S_OK)
  2366. {
  2367. Status = AsyncStatus;
  2368. fOutstandingSend = TRUE;
  2369. break;
  2370. }
  2371. continue;
  2372. }
  2373. else if (AsyncStatus != RPC_S_OK)
  2374. {
  2375. CallMutex.Clear();
  2376. Status = AsyncStatus;
  2377. fOutstandingSend = TRUE;
  2378. break;
  2379. }
  2380. //
  2381. // Since CurrentBuffer != 0, the call is busy sending the reply
  2382. //
  2383. if (BufferQueue.PutOnQueue(Message->Buffer, Message->BufferLength))
  2384. {
  2385. Status = RPC_S_OUT_OF_MEMORY;
  2386. }
  2387. else
  2388. {
  2389. UpdateBuffersAfterNonLastSend(
  2390. NewBuffer,
  2391. RemainingLength,
  2392. Message);
  2393. if (RemainingLength)
  2394. StatusToReturn = RPC_S_SEND_INCOMPLETE;
  2395. }
  2396. CallMutex.Clear();
  2397. }
  2398. break;
  2399. }
  2400. if (Status)
  2401. {
  2402. if (RemainingLength)
  2403. {
  2404. FreeBufferDo(NewBuffer);
  2405. }
  2406. if (fOutstandingSend)
  2407. {
  2408. FreeBufferDo(Message->Buffer);
  2409. }
  2410. }
  2411. else
  2412. {
  2413. if (StatusToReturn != RPC_S_OK)
  2414. Status = StatusToReturn;
  2415. }
  2416. if (fBufferSent)
  2417. {
  2418. //
  2419. // Remove the reference for the call (if failure)
  2420. // or for the outstanding send (if success)
  2421. //
  2422. RemoveReference(); // CALL--
  2423. }
  2424. return Status;
  2425. }
  2426. RPC_STATUS
  2427. OSF_SCALL::AsyncSend (
  2428. IN OUT PRPC_MESSAGE Message
  2429. )
  2430. /*++
  2431. Function Name:AsyncSend
  2432. Parameters:
  2433. Message - Supplies the buffer containing the response to be sent
  2434. Description:
  2435. It isn't neccassary for us to send the reply using async IO. For the first
  2436. cut, we will send the request synchronously. This will save us a whole lot
  2437. of headache.
  2438. Returns:
  2439. --*/
  2440. {
  2441. RPC_STATUS Status;
  2442. ULONG OldBufferLength = Message->BufferLength;
  2443. ASSERT(FirstSend == 0 || BufferQueue.IsQueueEmpty());
  2444. if (AsyncStatus != RPC_S_OK)
  2445. {
  2446. Status = AsyncStatus;
  2447. CleanupCall();
  2448. //
  2449. // Remove the reply reference
  2450. //
  2451. RemoveReference(); // CALL--
  2452. return Status;
  2453. }
  2454. Status = Send(Message);
  2455. if (Status == RPC_S_SEND_INCOMPLETE)
  2456. {
  2457. if (Message->BufferLength == OldBufferLength
  2458. && (pAsync->Flags & RPC_C_NOTIFY_ON_SEND_COMPLETE))
  2459. {
  2460. CallMutex.Request() ;
  2461. if (!IssueNotification(RpcSendComplete))
  2462. {
  2463. Status = RPC_S_OUT_OF_MEMORY ;
  2464. }
  2465. CallMutex.Clear() ;
  2466. }
  2467. }
  2468. //
  2469. // In the failure case, the reference has already been removed
  2470. // by the server
  2471. //
  2472. return Status;
  2473. }
  2474. RPC_STATUS
  2475. OSF_SCALL::SendRequestOrResponse (
  2476. IN OUT PRPC_MESSAGE Message,
  2477. IN unsigned char PacketType
  2478. )
  2479. /*++
  2480. Routine Description:
  2481. This routine is used to send to synchoronous sends, as in callbacks
  2482. and callback response.
  2483. Arguments:
  2484. Message - Supplies the buffer containing the request or response to be
  2485. sent, and returns the first fragment received from the server.
  2486. PacketType - Supplies the packet type; this must be rpc_request or
  2487. rpc_response.
  2488. Return Value:
  2489. RPC_S_OK - We successfully sent the request and received a fragment from
  2490. the server.
  2491. RPC_S_CALL_FAILED_DNE - The connection failed part way through sending
  2492. the request or response.
  2493. RPC_S_CALL_FAILED - The connection failed after sending the request or
  2494. response, and the receive failed.
  2495. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to perform the
  2496. operation.
  2497. RPC_S_OUT_OF_RESOURCES - Insufficient resources are available to perform
  2498. the operation.
  2499. --*/
  2500. {
  2501. RPC_STATUS Status;
  2502. RPC_MESSAGE SendBuffer;
  2503. rpcconn_common * pFragment;
  2504. ULONG LastFragmentFlag = 0;
  2505. ULONG LengthLeft = Message->BufferLength;
  2506. ULONG HeaderSize = sizeof(rpcconn_request);
  2507. ULONG MaxDataLength = MaximumFragmentLength - HeaderSize - MaxSecuritySize;
  2508. unsigned char *ReservedForSecurity = (unsigned char *) Message->Buffer
  2509. + Message->BufferLength + Connection->AdditionalSpaceForSecurity;
  2510. ASSERT(!PARTIAL(Message));
  2511. ASSERT( sizeof(rpcconn_response) == sizeof(rpcconn_request));
  2512. VALIDATE(PacketType)
  2513. {
  2514. rpc_request,
  2515. rpc_response
  2516. } END_VALIDATE;
  2517. SendBuffer.Buffer = Message->Buffer;
  2518. pFragment = (rpcconn_common *) ((char *) Message->Buffer - HeaderSize);
  2519. for (;;)
  2520. {
  2521. //
  2522. // Check to see if the remaining data will fit into a single
  2523. // fragment; if so, set the last fragment flag.
  2524. //
  2525. if ( LengthLeft <= MaxDataLength )
  2526. {
  2527. LastFragmentFlag = 1;
  2528. }
  2529. ConstructPacket(pFragment, PacketType, (LastFragmentFlag != 0 ?
  2530. LengthLeft+HeaderSize+MaxSecuritySize : MaximumFragmentLength));
  2531. if ((LengthLeft == Message->BufferLength))
  2532. {
  2533. if (FirstFrag)
  2534. {
  2535. FirstFrag = 0;
  2536. pFragment->pfc_flags |= PFC_FIRST_FRAG;
  2537. if (TestCancel())
  2538. {
  2539. pFragment->pfc_flags |= PFC_PENDING_CANCEL;
  2540. }
  2541. }
  2542. }
  2543. if (PacketType == rpc_request)
  2544. {
  2545. ((rpcconn_request *) pFragment)->alloc_hint = LengthLeft;
  2546. ((rpcconn_request *) pFragment)->p_cont_id = (unsigned short) CurrentBinding->GetPresentationContext();
  2547. ((rpcconn_request *) pFragment)->opnum = (unsigned short) Message->ProcNum;
  2548. }
  2549. else
  2550. {
  2551. ((rpcconn_response *) pFragment)->alloc_hint = LengthLeft;
  2552. ((rpcconn_response *) pFragment)->p_cont_id = (unsigned short) CurrentBinding->GetPresentationContext();
  2553. ((rpcconn_response *) pFragment)->alert_count = (unsigned char) 0;
  2554. ((rpcconn_response *) pFragment)->reserved = 0;
  2555. }
  2556. pFragment->call_id = CallId;
  2557. Status = Connection->SendFragment(
  2558. pFragment,
  2559. LastFragmentFlag,
  2560. HeaderSize,
  2561. MaxSecuritySize,
  2562. LengthLeft,
  2563. MaximumFragmentLength,
  2564. ReservedForSecurity) ;
  2565. if (Status != RPC_S_OK || LastFragmentFlag)
  2566. {
  2567. FreeBuffer(&SendBuffer);
  2568. return (Status) ;
  2569. }
  2570. pFragment = (rpcconn_common *)
  2571. (((unsigned char *) pFragment) + MaxDataLength);
  2572. LengthLeft -= MaxDataLength;
  2573. }
  2574. ASSERT(0);
  2575. }
  2576. void
  2577. OSF_SCALL::ProcessSendComplete (
  2578. IN RPC_STATUS EventStatus,
  2579. IN BUFFER Buffer
  2580. )
  2581. /*++
  2582. Function Name:ProcessSendComplete
  2583. Parameters:
  2584. Description:
  2585. Returns:
  2586. --*/
  2587. {
  2588. RPC_STATUS Status;
  2589. int MaxDataLength = MaximumFragmentLength
  2590. - sizeof(rpcconn_response) - MaxSecuritySize;
  2591. unsigned int MyCurrentBufferLength;
  2592. LogEvent(SU_SCALL, EV_NOTIFY, this, Buffer, EventStatus, 1);
  2593. ASSERT(Buffer);
  2594. ASSERT((char *) Buffer-CurrentOffset
  2595. +sizeof(rpcconn_request) == CurrentBuffer);
  2596. ASSERT((((rpcconn_common *) Buffer)->pfc_flags & PFC_LAST_FRAG) == 0);
  2597. if (EventStatus != RPC_S_OK)
  2598. {
  2599. Status = RPC_S_CALL_FAILED;
  2600. goto Abort;
  2601. }
  2602. MyCurrentBufferLength = CurrentBufferLength - MaxDataLength;
  2603. CurrentOffset += MaxDataLength;
  2604. CallMutex.Request();
  2605. if (MyCurrentBufferLength == 0)
  2606. {
  2607. Connection->TransFreeBuffer(
  2608. (char *) CurrentBuffer-sizeof(rpcconn_response));
  2609. CurrentBuffer = BufferQueue.TakeOffQueue(&MyCurrentBufferLength);
  2610. if (CurrentBuffer == 0)
  2611. {
  2612. if (pAsync && (pAsync->Flags & RPC_C_NOTIFY_ON_SEND_COMPLETE))
  2613. {
  2614. if (!IssueNotification(RpcSendComplete))
  2615. {
  2616. AsyncStatus = RPC_S_OUT_OF_MEMORY;
  2617. }
  2618. }
  2619. CurrentBufferLength = 0;
  2620. CallMutex.Clear();
  2621. return;
  2622. }
  2623. CurrentOffset = 0;
  2624. if (fChoked == 1 && pAsync == 0 && BufferQueue.Size() <=1)
  2625. {
  2626. fChoked = 0;
  2627. SyncEvent.Raise();
  2628. }
  2629. }
  2630. else
  2631. {
  2632. //
  2633. // We know that there is more to send in the current buffer
  2634. // We need to restore the part of the buffer which we overwrote
  2635. // with authentication information.
  2636. //
  2637. ASSERT(CurrentBuffer);
  2638. unsigned char *ReservedForSecurity = (unsigned char *) CurrentBuffer
  2639. + CurrentOffset + MyCurrentBufferLength
  2640. + Connection->AdditionalSpaceForSecurity;
  2641. if ((Connection->AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  2642. && (MaxSecuritySize != 0))
  2643. {
  2644. RpcpMemoryCopy((char *) Buffer+MaximumFragmentLength-MaxSecuritySize,
  2645. ReservedForSecurity, MaxSecuritySize);
  2646. }
  2647. }
  2648. ASSERT(MyCurrentBufferLength);
  2649. CurrentBufferLength = MyCurrentBufferLength;
  2650. CallMutex.Clear();
  2651. ASSERT(CurrentBuffer);
  2652. Status = SendNextFragment();
  2653. if (Status != RPC_S_OK)
  2654. {
  2655. goto Abort;
  2656. }
  2657. //
  2658. // Remove reference held by the outstanding send
  2659. // or the call reference in the case of the last call
  2660. //
  2661. RemoveReference(); // CALL--
  2662. return;
  2663. Abort:
  2664. ASSERT(CurrentBuffer);
  2665. ASSERT(Status != RPC_S_OK);
  2666. Connection->TransFreeBuffer(
  2667. (char *) CurrentBuffer-sizeof(rpcconn_response));
  2668. //
  2669. // We cannot remove the reference here, if we do
  2670. // we'll cause the other thread to puke
  2671. //
  2672. AsyncStatus = Status;
  2673. BUFFER MyBuffer;
  2674. unsigned int ignore;
  2675. CallMutex.Request();
  2676. while (MyBuffer = BufferQueue.TakeOffQueue(&ignore))
  2677. {
  2678. Connection->TransFreeBuffer((char *) MyBuffer-sizeof(rpcconn_response));
  2679. }
  2680. // wake up the thread that was flow controlled, if any
  2681. if (fChoked == 1 && pAsync == 0)
  2682. {
  2683. fChoked = 0;
  2684. SyncEvent.Raise();
  2685. }
  2686. CallMutex.Clear();
  2687. CurrentBufferLength = 0;
  2688. //
  2689. // Remove the reply reference
  2690. //
  2691. RemoveReference(); // CALL--
  2692. }
  2693. RPC_STATUS
  2694. OSF_SCALL::ImpersonateClient (
  2695. )
  2696. /*++
  2697. Function Name:ImpersonateClient
  2698. Parameters:
  2699. Description:
  2700. This is relatively easy: we check to see if there is RPC protocol level
  2701. security, if there is not, we let the transport try and impersonate
  2702. the client, and if there is, we let the GSSAPI deal with it.
  2703. Returns:
  2704. --*/
  2705. {
  2706. return Connection->ImpersonateClient();
  2707. }
  2708. RPC_STATUS
  2709. OSF_SCALL::RevertToSelf (
  2710. )
  2711. /*++
  2712. Function Name:RevertToSelf
  2713. Parameters:
  2714. Description:
  2715. As with ImpersonateClient, this is relatively easy. We just check
  2716. to see if we should let the RPC protocol level security deal with
  2717. it or the transport.
  2718. Returns:
  2719. --*/
  2720. {
  2721. return Connection->RevertToSelf();
  2722. }
  2723. RPC_STATUS
  2724. OSF_SCALL::GetAuthorizationContext (
  2725. IN BOOL ImpersonateOnReturn,
  2726. IN AUTHZ_RESOURCE_MANAGER_HANDLE AuthzResourceManager,
  2727. IN PLARGE_INTEGER pExpirationTime OPTIONAL,
  2728. IN LUID Identifier,
  2729. IN DWORD Flags,
  2730. IN PVOID DynamicGroupArgs OPTIONAL,
  2731. OUT PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContext
  2732. )
  2733. /*++
  2734. Routine Description:
  2735. Gets an authorization context for the client that can be used
  2736. with Authz functions. The resulting context is owned by the caller
  2737. and must be freed by it.
  2738. Arguments:
  2739. ImpersonateOnReturn - if TRUE, when we return, we should be impersonating.
  2740. AuthzResourceManager - the resource manager to use (passed to Authz)
  2741. pExpirationTime - the expiration time to use (passed to Authz)
  2742. Identifier - the LUID (passed to Authz)
  2743. Flags - Flags (passed to Authz)
  2744. DynamicGroupArgs - parameter required by Authz (passed to Authz)
  2745. pAuthzClientContext - the authorization context, returned on success.
  2746. Undefined on failure.
  2747. --*/
  2748. {
  2749. RPC_STATUS Status = RPC_S_OK;
  2750. RPC_STATUS RevertStatus;
  2751. HANDLE ImpersonationToken;
  2752. BOOL Result;
  2753. PAUTHZ_CLIENT_CONTEXT_HANDLE pAuthzClientContextPlaceholder;
  2754. SECURITY_CONTEXT *SecurityContext = Connection->CurrentSecurityContext;
  2755. SECURITY_STATUS SecurityStatus;
  2756. BOOL fNeedToCloseToken;
  2757. AUTHZ_CLIENT_CONTEXT_HANDLE AuthzContext;
  2758. ASSERT (AuthzResourceManager != NULL);
  2759. if (!SecurityContext)
  2760. {
  2761. return RPC_S_NO_CONTEXT_AVAILABLE;
  2762. }
  2763. AuthzContext = SecurityContext->GetAuthzContext();
  2764. if (ImpersonateOnReturn)
  2765. {
  2766. Status = OSF_SCALL::ImpersonateClient();
  2767. if (Status != RPC_S_OK)
  2768. {
  2769. RpcpErrorAddRecord(EEInfoGCRuntime,
  2770. Status,
  2771. EEInfoDLOSF_SCALL__GetAuthorizationContext10,
  2772. (ULONGLONG)this,
  2773. (ULONGLONG)0);
  2774. return Status;
  2775. }
  2776. }
  2777. if (AuthzContext)
  2778. {
  2779. Status = DuplicateAuthzContext(AuthzContext,
  2780. pExpirationTime,
  2781. Identifier,
  2782. Flags,
  2783. DynamicGroupArgs,
  2784. pAuthzClientContext);
  2785. if ((Status != RPC_S_OK) && ImpersonateOnReturn)
  2786. {
  2787. RevertStatus = OSF_SCALL::RevertToSelf();
  2788. ASSERT(RevertStatus == RPC_S_OK);
  2789. }
  2790. // EEInfo, if any, has already been added
  2791. return Status;
  2792. }
  2793. // if there was Authz context created, we would have
  2794. // returned by now. If we are here, this means there
  2795. // is none. Create it.
  2796. Status = SecurityContext->GetAccessToken(&ImpersonationToken,
  2797. &fNeedToCloseToken);
  2798. if (Status)
  2799. {
  2800. if (ImpersonateOnReturn)
  2801. {
  2802. RevertStatus = OSF_SCALL::RevertToSelf();
  2803. ASSERT(RevertStatus == RPC_S_OK);
  2804. }
  2805. return Status;
  2806. }
  2807. Status = CreateAndSaveAuthzContextFromToken(SecurityContext->GetAuthzContextAddress(),
  2808. ImpersonationToken,
  2809. AuthzResourceManager,
  2810. pExpirationTime,
  2811. Identifier,
  2812. Flags,
  2813. DynamicGroupArgs,
  2814. pAuthzClientContext);
  2815. if (fNeedToCloseToken)
  2816. {
  2817. CloseHandle(ImpersonationToken);
  2818. }
  2819. if (Status)
  2820. {
  2821. if (ImpersonateOnReturn)
  2822. {
  2823. RevertStatus = OSF_SCALL::RevertToSelf();
  2824. ASSERT(RevertStatus == RPC_S_OK);
  2825. }
  2826. return Status;
  2827. }
  2828. return RPC_S_OK;
  2829. }
  2830. RPC_STATUS
  2831. OSF_SCALL::GetAssociationContextCollection (
  2832. OUT ContextCollection **CtxCollection
  2833. )
  2834. /*++
  2835. Function Name: GetAssociationContextCollection
  2836. Parameters:
  2837. CtxCollection - a placeholder where to put the pointer to
  2838. the context collection.
  2839. Description:
  2840. The context handle code will call the SCALL to get the collection
  2841. of context handles for this association. The SCALL method will
  2842. simply delegate to the association.
  2843. Returns:
  2844. RPC_S_OK for success or RPC_S_* for error.
  2845. --*/
  2846. {
  2847. return Connection->GetAssociationContextCollection(CtxCollection);
  2848. }
  2849. void
  2850. OSF_SCALL::CleanupCallAndSendFault (
  2851. IN RPC_STATUS Status,
  2852. IN int DidNotExecute
  2853. )
  2854. /*++
  2855. Function Name:CleanupCallAndSendFault
  2856. Parameters: Status - the error code for the fault
  2857. Description:
  2858. A syntactic sugar function that saves all relevant call members in a local
  2859. variable, cleans up the call, and then sends the fault directly on the
  2860. connection. Designed to prevent the case where we send the fault to the client
  2861. and the next request comes in before we have made this call available - this
  2862. confuses the server.
  2863. Returns:
  2864. --*/
  2865. {
  2866. p_context_id_t p_cont = 0;
  2867. OSF_SCONNECTION *pLocalConnection;
  2868. unsigned long LocalCallId = CallId;
  2869. if (CurrentBinding)
  2870. p_cont = (p_context_id_t)CurrentBinding->GetPresentationContext();
  2871. pLocalConnection = Connection;
  2872. // make the call available before we send the fault
  2873. CleanupCall();
  2874. pLocalConnection->SendFault(Status, DidNotExecute, LocalCallId, p_cont);
  2875. }
  2876. RPC_STATUS
  2877. OSF_SCALL::ConvertToServerBinding (
  2878. OUT RPC_BINDING_HANDLE __RPC_FAR * ServerBinding
  2879. )
  2880. /*++
  2881. Routine Description:
  2882. If possible, convert this connection into a server binding, meaning a
  2883. binding handle pointing back to the client.
  2884. Arguments:
  2885. ServerBinding - Returns the server binding.
  2886. Return Value:
  2887. RPC_S_OK - The server binding has successfully been created.
  2888. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate
  2889. a new binding handle.
  2890. RPC_S_CANNOT_SUPPORT - This will be returned if the transport does
  2891. not support query the network address of the client.
  2892. --*/
  2893. {
  2894. RPC_CHAR * NetworkAddress;
  2895. RPC_STATUS Status;
  2896. RPC_CHAR * StringBinding;
  2897. Status = Connection->TransQueryClientNetworkAddress(
  2898. &NetworkAddress);
  2899. if ( Status != RPC_S_OK )
  2900. {
  2901. return(Status);
  2902. }
  2903. Status = RpcStringBindingCompose(0,
  2904. Address->InqRpcProtocolSequence(),
  2905. NetworkAddress,
  2906. 0,
  2907. 0,
  2908. &StringBinding);
  2909. delete NetworkAddress;
  2910. if ( Status != RPC_S_OK )
  2911. {
  2912. return(Status);
  2913. }
  2914. Status = RpcBindingFromStringBinding(StringBinding, ServerBinding);
  2915. if ( ObjectUuidSpecified != 0 && RPC_S_OK == Status)
  2916. {
  2917. Status = RpcBindingSetObject(*ServerBinding, (UUID *) &ObjectUuid);
  2918. }
  2919. RpcStringFree(&StringBinding);
  2920. return(Status);
  2921. }
  2922. OSF_SCONNECTION::OSF_SCONNECTION (
  2923. IN OSF_ADDRESS * TheAddress,
  2924. IN RPC_CONNECTION_TRANSPORT * ServerInfo,
  2925. IN OUT RPC_STATUS * Status
  2926. ) : ConnMutex(Status)
  2927. {
  2928. ObjectType = OSF_SCONNECTION_TYPE;
  2929. MaxFrag = 512;
  2930. Association = 0;
  2931. AuthContextId = 0;
  2932. SavedHeader = 0;
  2933. SavedHeaderSize = 0;
  2934. CurrentSecurityContext = 0;
  2935. RpcSecurityBeingUsed = 0;
  2936. SecurityContextAltered = 0;
  2937. AdditionalSpaceForSecurity = 0;
  2938. DceSecurityInfo.SendSequenceNumber = 0;
  2939. DceSecurityInfo.ReceiveSequenceNumber = 0;
  2940. AuthContinueNeeded = 0;
  2941. CurrentCallId=-1;
  2942. CachedSCallAvailable = 1;
  2943. this->ServerInfo = ServerInfo;
  2944. ConnectionClosedFlag = 0;
  2945. Address = TheAddress;
  2946. TransConnection = (char *) this+sizeof(OSF_SCONNECTION);
  2947. if (IsServerSideDebugInfoEnabled())
  2948. {
  2949. // zero out the CachedSCall - this is a signal that
  2950. // the OSF_SCALL constructor will use to tell
  2951. // it is the cached call
  2952. CachedSCall = NULL;
  2953. DebugCell = (DebugConnectionInfo *) AllocateCell(&DebugCellTag);
  2954. if (DebugCell != 0)
  2955. {
  2956. memset(DebugCell, 0, sizeof(*DebugCell));
  2957. DebugCell->Type = dctConnectionInfo;
  2958. TheAddress->GetDebugCellIDForThisObject(&DebugCell->Endpoint);
  2959. }
  2960. else
  2961. *Status = RPC_S_OUT_OF_MEMORY;
  2962. }
  2963. else
  2964. DebugCell = NULL;
  2965. CachedSCall = new (ServerInfo->SendContextSize)
  2966. OSF_SCALL(this, Status);
  2967. if (CachedSCall == 0)
  2968. {
  2969. *Status = RPC_S_OUT_OF_MEMORY;
  2970. }
  2971. fExclusive = 0;
  2972. fDontFlush = 0;
  2973. fFirstCall = 0;
  2974. fCurrentlyDispatched = 0;
  2975. }
  2976. OSF_SCONNECTION::~OSF_SCONNECTION (
  2977. )
  2978. {
  2979. OSF_SBINDING * SBinding;
  2980. SECURITY_CONTEXT * SecurityContext;
  2981. DictionaryCursor cursor;
  2982. if (CachedSCall)
  2983. {
  2984. delete CachedSCall;
  2985. }
  2986. ASSERT( AuthInfo.PacHandle == 0 );
  2987. if ( CurrentSecurityContext && AuthInfo.PacHandle )
  2988. {
  2989. CurrentSecurityContext->DeletePac( AuthInfo.PacHandle );
  2990. }
  2991. SecurityContextDict.Reset(cursor);
  2992. while ( (SecurityContext = SecurityContextDict.Next(cursor)) != 0 )
  2993. delete SecurityContext;
  2994. Bindings.Reset(cursor);
  2995. while (SBinding = Bindings.Next(cursor))
  2996. delete SBinding;
  2997. if (Association)
  2998. Association->RemoveConnection();
  2999. if (SavedHeader)
  3000. {
  3001. RpcpFarFree(SavedHeader);
  3002. }
  3003. if (ServerInfo)
  3004. {
  3005. //
  3006. // ServerInfo will be set to 0 when create on the SCONNECTION fails
  3007. // look at NewConnection
  3008. //
  3009. ServerInfo->Close(TransConnection, fDontFlush);
  3010. }
  3011. if (DebugCell)
  3012. {
  3013. FreeCell(DebugCell, &DebugCellTag);
  3014. }
  3015. }
  3016. RPC_STATUS
  3017. OSF_SCONNECTION::TransSend (
  3018. IN void * Buffer,
  3019. IN unsigned int BufferLength
  3020. )
  3021. /*++
  3022. --*/
  3023. {
  3024. RPC_STATUS Status;
  3025. {
  3026. rpcconn_common * pkt = (rpcconn_common *) Buffer;
  3027. LogEvent(SU_SCONN, EV_PKT_OUT, this, 0, (pkt->PTYPE << 16) | pkt->frag_length);
  3028. }
  3029. if (ConnectionClosedFlag != 0)
  3030. return(RPC_P_CONNECTION_CLOSED);
  3031. if (DebugCell)
  3032. {
  3033. DebugCell->LastSendTime = NtGetTickCount();
  3034. DebugCell->LastTransmitFragmentSize = (USHORT) BufferLength;
  3035. }
  3036. DceSecurityInfo.SendSequenceNumber += 1;
  3037. Status = ServerInfo->SyncSend(
  3038. TransConnection,
  3039. BufferLength,
  3040. Buffer,
  3041. TRUE,
  3042. TRUE,
  3043. INFINITE); // Timeout
  3044. VALIDATE(Status)
  3045. {
  3046. RPC_S_OK,
  3047. RPC_S_OUT_OF_MEMORY,
  3048. RPC_S_OUT_OF_RESOURCES,
  3049. RPC_P_SEND_FAILED
  3050. } END_VALIDATE;
  3051. if ( Status == RPC_S_OK )
  3052. {
  3053. GlobalRpcServer->PacketSent();
  3054. }
  3055. if ( Status == RPC_P_SEND_FAILED )
  3056. {
  3057. ConnectionClosedFlag = 1;
  3058. }
  3059. return(Status);
  3060. }
  3061. RPC_STATUS
  3062. OSF_SCONNECTION::TransAsyncSend (
  3063. IN void * Buffer,
  3064. IN unsigned int BufferLength,
  3065. IN void *SendContext
  3066. )
  3067. /*++
  3068. Function Name:TransAsyncSend
  3069. Parameters:
  3070. Description:
  3071. Returns:
  3072. --*/
  3073. {
  3074. RPC_STATUS Status;
  3075. {
  3076. rpcconn_common * pkt = (rpcconn_common *) Buffer;
  3077. LogEvent(SU_SCONN, EV_PKT_OUT, this, 0, (pkt->PTYPE << 16) | pkt->frag_length);
  3078. }
  3079. if ( ConnectionClosedFlag != 0 )
  3080. {
  3081. return(RPC_P_CONNECTION_CLOSED);
  3082. }
  3083. if (DebugCell)
  3084. {
  3085. DebugCell->LastSendTime = NtGetTickCount();
  3086. DebugCell->LastTransmitFragmentSize = (USHORT) BufferLength;
  3087. }
  3088. DceSecurityInfo.SendSequenceNumber += 1;
  3089. Status = ServerInfo->Send(TransConnection,
  3090. BufferLength,
  3091. (BUFFER) Buffer,
  3092. SendContext);
  3093. if (Status == RPC_S_OK)
  3094. {
  3095. GlobalRpcServer->PacketSent();
  3096. }
  3097. if ( Status == RPC_P_SEND_FAILED )
  3098. {
  3099. ConnectionClosedFlag = 1;
  3100. }
  3101. VALIDATE(Status)
  3102. {
  3103. RPC_S_OK,
  3104. RPC_S_OUT_OF_MEMORY,
  3105. RPC_S_OUT_OF_RESOURCES,
  3106. RPC_P_SEND_FAILED
  3107. } END_VALIDATE;
  3108. return(Status);
  3109. }
  3110. RPC_STATUS
  3111. OSF_SCONNECTION::TransAsyncReceive (
  3112. )
  3113. /*++
  3114. Function Name:TransAsyncReceive
  3115. Parameters:
  3116. Description:
  3117. Returns:
  3118. --*/
  3119. {
  3120. RPC_STATUS Status;
  3121. //
  3122. // Each outstanding receive will hold a reference
  3123. // on the connection
  3124. //
  3125. AddReference(); // CONN++
  3126. if (ConnectionClosedFlag != 0)
  3127. {
  3128. AbortConnection();
  3129. return(RPC_P_CONNECTION_CLOSED);
  3130. }
  3131. Status = ServerInfo->Recv(TransConnection);
  3132. if (Status != RPC_S_OK)
  3133. {
  3134. VALIDATE(Status)
  3135. {
  3136. RPC_P_RECEIVE_FAILED,
  3137. RPC_P_CONNECTION_SHUTDOWN,
  3138. RPC_P_CONNECTION_CLOSED
  3139. } END_VALIDATE;
  3140. if (fExclusive && !CachedSCallAvailable)
  3141. CachedSCall->WakeUpPipeThreadIfNecessary(RPC_S_CALL_FAILED);
  3142. ConnectionClosedFlag = 1;
  3143. AbortConnection();
  3144. }
  3145. return Status;
  3146. }
  3147. unsigned int
  3148. OSF_SCONNECTION::TransMaximumSend (
  3149. )
  3150. /*++
  3151. --*/
  3152. {
  3153. return(ServerInfo->MaximumFragmentSize);
  3154. }
  3155. RPC_STATUS
  3156. OSF_SCONNECTION::TransImpersonateClient (
  3157. )
  3158. /*++
  3159. Function Name:TransImpersonateClient
  3160. Parameters:
  3161. Description:
  3162. If the transport module supports impersonation it will provide the
  3163. sImpersonateClient entry point, in which case we call it. If an
  3164. error occurs (indicated by sImpersonateClient returning non-zero),
  3165. then no context is available. NOTE: this is the correct error code
  3166. for NT; it may not be the right one (or only one) for other transports
  3167. which support impersonation.
  3168. Returns:
  3169. --*/
  3170. {
  3171. RPC_STATUS Status;
  3172. if ( ServerInfo->ImpersonateClient == 0 )
  3173. {
  3174. return(RPC_S_CANNOT_SUPPORT);
  3175. }
  3176. Status = ServerInfo->ImpersonateClient(TransConnection);
  3177. VALIDATE(Status)
  3178. {
  3179. RPC_S_OK,
  3180. RPC_S_NO_CONTEXT_AVAILABLE
  3181. } END_VALIDATE;
  3182. return(Status);
  3183. }
  3184. void
  3185. OSF_SCONNECTION::TransRevertToSelf (
  3186. )
  3187. /*++
  3188. --*/
  3189. // As with TransImpersonateClient, if the transport module supports
  3190. // impersonation, then sRevertToSelf will be non-zero. We do not have
  3191. // to worry about errors.
  3192. //
  3193. // For revert to self to work in NT, the transport module needs to know
  3194. // the handle of the calling thread when it was originally created. None
  3195. // of the other operating systems we support at this point have
  3196. // impersonation built into the transports.
  3197. {
  3198. RPC_STATUS Status;
  3199. if ( ServerInfo->RevertToSelf != 0 )
  3200. {
  3201. Status = ServerInfo->RevertToSelf(TransConnection);
  3202. ASSERT( Status == RPC_S_OK );
  3203. }
  3204. }
  3205. void
  3206. OSF_SCONNECTION::TransQueryClientProcess (
  3207. OUT RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess
  3208. )
  3209. /*++
  3210. Routine Description:
  3211. We need to obtain the client process identifier for the client process
  3212. at the other end of this connection. This is necessary so that we can
  3213. determine whether or not a connection should belong to a given
  3214. association. We need to do this so that context handles (which hang off
  3215. of associations) are secure.
  3216. Arguments:
  3217. ClientProcess - Returns the client process identifier for the client
  3218. process at the other end of this connection.
  3219. --*/
  3220. {
  3221. RPC_STATUS Status;
  3222. if ( ServerInfo->QueryClientId == 0 )
  3223. {
  3224. ClientProcess->ZeroOut();
  3225. }
  3226. else
  3227. {
  3228. Status = ServerInfo->QueryClientId(TransConnection,
  3229. ClientProcess);
  3230. ASSERT( Status == RPC_S_OK );
  3231. }
  3232. }
  3233. RPC_STATUS
  3234. OSF_SCONNECTION::TransQueryClientNetworkAddress (
  3235. OUT RPC_CHAR ** NetworkAddress
  3236. )
  3237. /*++
  3238. Routine Description:
  3239. This routine is used to query the network address of the client at the
  3240. other end of this connection.
  3241. Arguments:
  3242. NetworkAddress - Returns the client's network address.
  3243. Return Value:
  3244. RPC_S_OK - The client's network address has successfully been obtained.
  3245. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  3246. operation.
  3247. RPC_S_CANNOT_SUPPORT - This particular transport implementation does
  3248. not support this operation.
  3249. --*/
  3250. {
  3251. RPC_STATUS Status;
  3252. if ( ( ServerInfo->TransInterfaceVersion < 2 )
  3253. || ( ServerInfo->QueryClientAddress == 0 ) )
  3254. {
  3255. return(RPC_S_CANNOT_SUPPORT);
  3256. }
  3257. Status = ServerInfo->QueryClientAddress(TransConnection,
  3258. NetworkAddress);
  3259. return(Status);
  3260. }
  3261. void
  3262. OSF_SCONNECTION::AbortConnection (
  3263. )
  3264. /*++
  3265. Routine Description:
  3266. --*/
  3267. {
  3268. DictionaryCursor cursor;
  3269. //
  3270. // When AbortConnection is called,
  3271. // there should be no pending IO
  3272. //
  3273. //
  3274. // Delete the object, ie: remove the object reference
  3275. //
  3276. Delete();
  3277. //
  3278. // If there are calls stuck in callbacks, wake them up
  3279. //
  3280. if (fExclusive)
  3281. {
  3282. ConnMutex.Request();
  3283. if (CachedSCallAvailable == 0)
  3284. {
  3285. CachedSCall->DeactivateCall();
  3286. CachedSCallAvailable = 1;
  3287. ConnMutex.Clear();
  3288. CachedSCall->AbortCall();
  3289. }
  3290. else
  3291. {
  3292. ConnMutex.Clear();
  3293. }
  3294. }
  3295. else
  3296. {
  3297. ConnMutex.Request();
  3298. OSF_SCALL *NextCall;
  3299. CallDict.Reset(cursor);
  3300. while ((NextCall = CallDict.Next(cursor)) != 0)
  3301. {
  3302. NextCall->AbortCall();
  3303. }
  3304. ConnMutex.Clear();
  3305. }
  3306. //
  3307. // Remove the reference held by the pending receive
  3308. //
  3309. RemoveReference(); // CONN--
  3310. }
  3311. void
  3312. OSF_SCONNECTION::FreeObject (
  3313. )
  3314. {
  3315. RemoveFromAssociation();
  3316. delete this;
  3317. }
  3318. void
  3319. OSF_SCONNECTION::FreeSCall (
  3320. IN OSF_SCALL *SCall,
  3321. IN BOOL fRemove
  3322. )
  3323. /*++
  3324. Function Name:FreeSCall
  3325. Parameters:
  3326. Description:
  3327. Returns:
  3328. --*/
  3329. {
  3330. ASSERT(SCall->BufferQueue.IsQueueEmpty());
  3331. if (fExclusive == 0)
  3332. {
  3333. if (fRemove)
  3334. {
  3335. OSF_SCALL *Call;
  3336. ConnMutex.Request();
  3337. Call = CallDict.Delete(ULongToPtr(SCall->CallId));
  3338. ConnMutex.Clear();
  3339. ASSERT(Call == 0 || Call == SCall);
  3340. }
  3341. // CurrentBinding is initialized in OSF_SCALL::BeginRpcCall
  3342. // by a call to OSF_CCONNECTION::LookupBinding. That call may
  3343. // not succeed if we do not find the binding in the dictionary,
  3344. // or we may fail before initialization.
  3345. if (SCall->CurrentBinding != NULL)
  3346. {
  3347. RPC_INTERFACE *CallInterface;
  3348. CallInterface = SCall->CurrentBinding->GetInterface();
  3349. if (SCall->pAsync)
  3350. {
  3351. CallInterface->EndCall(0, 1);
  3352. }
  3353. if (CallInterface->IsAutoListenInterface())
  3354. {
  3355. CallInterface->EndAutoListenCall();
  3356. }
  3357. }
  3358. SCall->DeactivateCall();
  3359. if (SCall == CachedSCall)
  3360. {
  3361. CachedSCallAvailable = 1;
  3362. }
  3363. else
  3364. {
  3365. delete SCall;
  3366. }
  3367. }
  3368. //
  3369. // Remove the reference held by the call
  3370. //
  3371. RemoveReference(); // CONN--
  3372. }
  3373. RPC_STATUS
  3374. OSF_SCONNECTION::TransGetBuffer (
  3375. OUT void * * Buffer,
  3376. IN unsigned int BufferLength
  3377. )
  3378. {
  3379. int * Memory;
  3380. //
  3381. // Our memory allocator returns memory which is aligned by at least
  3382. // 8, so we dont need to worry about aligning it.
  3383. //
  3384. Memory = (int *) CoAllocateBuffer(BufferLength);
  3385. if ( Memory == 0 )
  3386. {
  3387. return(RPC_S_OUT_OF_MEMORY);
  3388. }
  3389. ASSERT( IsBufferAligned(Memory) );
  3390. *Buffer = Memory;
  3391. return(RPC_S_OK);
  3392. }
  3393. void
  3394. OSF_SCONNECTION::TransFreeBuffer ( // Free a buffer.
  3395. IN void * Buffer
  3396. )
  3397. {
  3398. CoFreeBuffer(Buffer);
  3399. }
  3400. void
  3401. OSF_SCONNECTION::ProcessReceiveComplete (
  3402. IN RPC_STATUS EventStatus,
  3403. IN BUFFER Buffer,
  3404. IN UINT BufferLength
  3405. )
  3406. /*++
  3407. Function Name:ProcessReceiveComplete
  3408. Parameters:
  3409. Description:
  3410. Returns:
  3411. --*/
  3412. {
  3413. rpcconn_common *Packet = (rpcconn_common *) Buffer;
  3414. rpcconn_auth3 * AuthThirdLegPacket;
  3415. sec_trailer * NewSecurityTrailer;
  3416. OSF_SCALL *SCall = 0;
  3417. RPC_STATUS Status;
  3418. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  3419. SECURITY_BUFFER InputBuffers[4];
  3420. BOOL fReceivePosted = 0;
  3421. BOOL fDNE = 0;
  3422. if (EventStatus)
  3423. {
  3424. LogEvent(SU_SCONN, EV_PKT_IN, this, LongToPtr(EventStatus));
  3425. }
  3426. else
  3427. {
  3428. if (Packet->PTYPE == rpc_request)
  3429. {
  3430. LogEvent(SU_SCONN, EV_PKT_IN, this, 0,
  3431. (((rpcconn_request *)Packet)->opnum << 24) | (Packet->PTYPE << 16) | Packet->frag_length);
  3432. }
  3433. else
  3434. {
  3435. LogEvent(SU_SCONN, EV_PKT_IN, this, 0, (Packet->PTYPE << 16) | Packet->frag_length);
  3436. }
  3437. }
  3438. if (DebugCell)
  3439. {
  3440. DebugCell->LastReceiveTime = NtGetTickCount();
  3441. DebugCell->LastTransmitFragmentSize = (USHORT)BufferLength;
  3442. }
  3443. if (EventStatus != RPC_S_OK)
  3444. {
  3445. VALIDATE(EventStatus)
  3446. {
  3447. RPC_P_CONNECTION_CLOSED,
  3448. RPC_P_RECEIVE_FAILED,
  3449. RPC_P_CONNECTION_SHUTDOWN
  3450. } END_VALIDATE;
  3451. ConnectionClosedFlag = 1;
  3452. if (fExclusive && !CachedSCallAvailable)
  3453. CachedSCall->WakeUpPipeThreadIfNecessary(RPC_S_CALL_FAILED);
  3454. TransFreeBuffer(Buffer);
  3455. AbortConnection();
  3456. return;
  3457. }
  3458. ASSERT(EventStatus == 0);
  3459. ASSERT(Buffer);
  3460. GlobalRpcServer->PacketReceived();
  3461. //
  3462. // Check and make sure that if this is the first packet on this
  3463. // connection that it is a bind packet.
  3464. //
  3465. if ((Association == 0) && (Packet->PTYPE != rpc_bind))
  3466. {
  3467. SendBindNak(protocol_version_not_supported, Packet->call_id);
  3468. TransFreeBuffer(Packet);
  3469. AbortConnection();
  3470. return;
  3471. }
  3472. switch (Packet->PTYPE)
  3473. {
  3474. case rpc_request:
  3475. if (fExclusive)
  3476. {
  3477. if (Packet->pfc_flags & PFC_FIRST_FRAG
  3478. && CachedSCallAvailable)
  3479. {
  3480. //
  3481. // New call is about to be started
  3482. // Add a reference on the connection
  3483. //
  3484. AddReference(); // CONN++
  3485. CachedSCallAvailable = 0;
  3486. fReceivePosted = CachedSCall->BeginRpcCall(Packet, BufferLength);
  3487. }
  3488. else
  3489. {
  3490. fReceivePosted = CachedSCall->ProcessReceivedPDU(Packet, BufferLength);
  3491. }
  3492. }
  3493. else
  3494. {
  3495. if ((long) Packet->call_id <= (long) CurrentCallId)
  3496. {
  3497. //
  3498. // If it is a non-first fragment, or if it is a callback
  3499. //
  3500. SCall = FindCall(Packet->call_id);
  3501. if (SCall == 0)
  3502. {
  3503. if ((long) Packet->call_id < (long) CurrentCallId
  3504. || (Packet->pfc_flags & PFC_FIRST_FRAG) == 0)
  3505. {
  3506. //
  3507. // Can't find the call. This could be because the pipe call
  3508. // raised an exception and the call is now complete.
  3509. //
  3510. TransFreeBuffer(Packet);
  3511. fReceivePosted = 0;
  3512. goto End;
  3513. }
  3514. //
  3515. // If the client is Win95, it will use the same call_id
  3516. // for subsequent calls on the same connection
  3517. //
  3518. }
  3519. }
  3520. if (SCall == 0)
  3521. {
  3522. CurrentCallId = Packet->call_id;
  3523. //
  3524. // A new call is about to be started, create one
  3525. //
  3526. if (InterlockedCompareExchange(
  3527. (LPLONG) &CachedSCallAvailable, 0, 1))
  3528. {
  3529. SCall = CachedSCall;
  3530. }
  3531. else
  3532. {
  3533. Status = RPC_S_OK;
  3534. SCall = new (ServerInfo->SendContextSize)
  3535. OSF_SCALL(this, &Status);
  3536. if (SCall == 0 || Status != RPC_S_OK)
  3537. {
  3538. SendFault(RPC_S_OUT_OF_MEMORY, 1, Packet->call_id);
  3539. if (SCall != 0)
  3540. {
  3541. delete SCall;
  3542. }
  3543. TransFreeBuffer(Packet);
  3544. break;
  3545. }
  3546. }
  3547. //
  3548. // New call is about to be started
  3549. // Add a reference on the connection
  3550. //
  3551. AddReference(); // CONN++
  3552. int DictKey;
  3553. ASSERT(SCall);
  3554. ConnMutex.Request();
  3555. DictKey = CallDict.Insert(ULongToPtr(Packet->call_id), SCall);
  3556. ConnMutex.Clear();
  3557. if (DictKey == -1)
  3558. {
  3559. SendFault(RPC_S_OUT_OF_MEMORY, 1, Packet->call_id);
  3560. FreeSCall(SCall);
  3561. TransFreeBuffer(Packet);
  3562. break;
  3563. }
  3564. ASSERT(SCall);
  3565. //
  3566. // We need this reference to prevent the call from going
  3567. // away from under us when the client goes away
  3568. //
  3569. SCall->AddReference(); // CALL++
  3570. fReceivePosted = SCall->BeginRpcCall(Packet, BufferLength);
  3571. SCall->OSF_SCALL::RemoveReference(); // CALL--
  3572. }
  3573. else
  3574. {
  3575. ASSERT(SCall);
  3576. //
  3577. // The packet will be freed by the callee
  3578. //
  3579. fReceivePosted = SCall->ProcessReceivedPDU(Packet, BufferLength);
  3580. //
  3581. // Remove the reference added by the lookup
  3582. //
  3583. SCall->OSF_SCALL::RemoveReference(); // CALL--
  3584. }
  3585. }
  3586. break;
  3587. case rpc_bind:
  3588. case rpc_alter_context:
  3589. //
  3590. // Save the unbyteswapped header for the security related stuff
  3591. // Especially if SECURITY is on.
  3592. // For Bind and AlterContext we save entire packet [we can do better though]
  3593. //
  3594. if (Packet->auth_length != 0)
  3595. {
  3596. if (SavedHeaderSize < BufferLength)
  3597. {
  3598. if (SavedHeader != 0)
  3599. {
  3600. ASSERT(SavedHeaderSize != 0);
  3601. RpcpFarFree(SavedHeader);
  3602. }
  3603. SavedHeader = RpcpFarAllocate(BufferLength);
  3604. if (SavedHeader == 0)
  3605. {
  3606. if ( Association == 0 )
  3607. {
  3608. SendBindNak(
  3609. protocol_version_not_supported,
  3610. Packet->call_id);
  3611. TransFreeBuffer(Packet);
  3612. AbortConnection();
  3613. return;
  3614. }
  3615. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3616. }
  3617. SavedHeaderSize = BufferLength;
  3618. RpcpMemoryCopy(SavedHeader, Packet, BufferLength);
  3619. }
  3620. else
  3621. {
  3622. RpcpMemoryCopy(SavedHeader, Packet, BufferLength);
  3623. }
  3624. }
  3625. //
  3626. // These things can take quite a while and could cause deadlocks
  3627. // if we dont have any listening threads
  3628. //
  3629. Address->CreateThread();
  3630. Status = ValidatePacket(Packet, BufferLength);
  3631. if (Status != RPC_S_OK)
  3632. {
  3633. ASSERT( Status == RPC_S_PROTOCOL_ERROR );
  3634. //
  3635. // If this the first packet on the connection, it should be an
  3636. // rpc_bind packet, and we want to send a rpc_bind_nak packet
  3637. // rather than a fault. We can tell that this is the first packet
  3638. // because the association is zero.
  3639. //
  3640. if ( Association == 0 )
  3641. {
  3642. SendBindNak(protocol_version_not_supported,
  3643. Packet->call_id);
  3644. TransFreeBuffer(Packet);
  3645. AbortConnection();
  3646. return;
  3647. }
  3648. //
  3649. // It is not the first packet, so we need to send a fault instead,
  3650. // and then we will blow the connection away.
  3651. //
  3652. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 1);
  3653. }
  3654. if (Packet->PTYPE == rpc_bind)
  3655. {
  3656. if (Association != 0)
  3657. {
  3658. SendBindNak(reason_not_specified_reject,
  3659. Packet->call_id);
  3660. AbortConnection();
  3661. return;
  3662. }
  3663. //
  3664. // The packet will be freed by the callee
  3665. //
  3666. if (AssociationRequested(
  3667. (rpcconn_bind *) Packet, BufferLength) != 0)
  3668. {
  3669. AbortConnection();
  3670. return;
  3671. }
  3672. }
  3673. else
  3674. {
  3675. if (Association == 0)
  3676. {
  3677. SendFault(RPC_S_PROTOCOL_ERROR, 1, Packet->call_id);
  3678. }
  3679. //
  3680. // The packet will be freed by the callee
  3681. //
  3682. if (AlterContextRequested(
  3683. (rpcconn_alter_context *) Packet,
  3684. BufferLength) != 0 )
  3685. {
  3686. AbortConnection();
  3687. return;
  3688. }
  3689. }
  3690. break;
  3691. case rpc_auth_3:
  3692. //
  3693. // This means that the client sent us back a third leg
  3694. // AuthInfo.Authentication packet.
  3695. //
  3696. ASSERT(AuthContinueNeeded != 0);
  3697. // Save the unbyteswapped header
  3698. ASSERT(AuthInfo.AuthenticationLevel
  3699. != RPC_C_AUTHN_LEVEL_NONE);
  3700. AuthThirdLegPacket = (rpcconn_auth3 *) Buffer;
  3701. if (AuthContinueNeeded == 0)
  3702. {
  3703. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 1);
  3704. }
  3705. if (SavedHeaderSize < BufferLength)
  3706. {
  3707. if (SavedHeader != 0)
  3708. {
  3709. ASSERT(SavedHeaderSize != 0);
  3710. RpcpFarFree(SavedHeader);
  3711. }
  3712. SavedHeader = RpcpFarAllocate(BufferLength);
  3713. if (SavedHeader == 0)
  3714. {
  3715. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3716. }
  3717. SavedHeaderSize = BufferLength;
  3718. RpcpMemoryCopy(SavedHeader, AuthThirdLegPacket,
  3719. BufferLength);
  3720. }
  3721. else
  3722. {
  3723. RpcpMemoryCopy(SavedHeader, AuthThirdLegPacket,
  3724. BufferLength);
  3725. }
  3726. //
  3727. // These things can take quite a while and could cause deadlocks
  3728. // if we dont have any listening threads
  3729. //
  3730. Address->CreateThread();
  3731. Status = ValidatePacket(
  3732. (rpcconn_common *) AuthThirdLegPacket,
  3733. BufferLength);
  3734. if ( Status != RPC_S_OK )
  3735. {
  3736. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3737. }
  3738. if ( AuthThirdLegPacket->common.PTYPE != rpc_auth_3 )
  3739. {
  3740. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3741. }
  3742. NewSecurityTrailer = (sec_trailer *)
  3743. (((unsigned char *) AuthThirdLegPacket)
  3744. + AuthThirdLegPacket->common.frag_length - sizeof(sec_trailer)
  3745. - AuthThirdLegPacket->common.auth_length);
  3746. if ( (NewSecurityTrailer->auth_type != AuthInfo.AuthenticationService)
  3747. || (NewSecurityTrailer->auth_level != AuthInfo.AuthenticationLevel) )
  3748. {
  3749. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3750. }
  3751. InputBufferDescriptor.ulVersion = 0;
  3752. InputBufferDescriptor.cBuffers = 4;
  3753. InputBufferDescriptor.pBuffers = InputBuffers;
  3754. InputBuffers[0].cbBuffer = sizeof(rpcconn_auth3);
  3755. InputBuffers[0].BufferType =
  3756. SECBUFFER_DATA | SECBUFFER_READONLY;
  3757. InputBuffers[0].pvBuffer = SavedHeader;
  3758. InputBuffers[1].cbBuffer =
  3759. AuthThirdLegPacket->common.frag_length
  3760. - sizeof(rpcconn_auth3)
  3761. - AuthThirdLegPacket->common.auth_length;
  3762. InputBuffers[1].BufferType =
  3763. SECBUFFER_DATA | SECBUFFER_READONLY;
  3764. InputBuffers[1].pvBuffer =
  3765. (char *) SavedHeader + sizeof(rpcconn_auth3);
  3766. InputBuffers[2].cbBuffer = AuthThirdLegPacket->common.auth_length;
  3767. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  3768. InputBuffers[2].pvBuffer = NewSecurityTrailer + 1;
  3769. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  3770. InputBuffers[3].BufferType =
  3771. SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  3772. InputBuffers[3].pvBuffer = &InitSecurityInfo;
  3773. Status = CurrentSecurityContext->AcceptThirdLeg(
  3774. *((unsigned long *)
  3775. AuthThirdLegPacket->common.drep),
  3776. &InputBufferDescriptor, 0);
  3777. LogEvent(SU_SCONN, EV_SEC_ACCEPT3, this, LongToPtr(Status), 0);
  3778. if ( Status != RPC_S_OK )
  3779. {
  3780. SC_CLEANUP(RPC_S_OUT_OF_MEMORY, 1);
  3781. }
  3782. TransFreeBuffer(AuthThirdLegPacket);
  3783. DceSecurityInfo.ReceiveSequenceNumber += 1;
  3784. //
  3785. // We need to figure out how much space to reserve for security
  3786. // information at the end of request and response packets.
  3787. // In addition to saving space for the signature or header,
  3788. // we need space to pad the packet to a multiple of the maximum
  3789. // security block size as well as for the security trailer.
  3790. //
  3791. if ((AuthInfo.AuthenticationLevel
  3792. == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  3793. || (AuthInfo.AuthenticationLevel
  3794. == RPC_C_AUTHN_LEVEL_PKT)
  3795. || (AuthInfo.AuthenticationLevel
  3796. == RPC_C_AUTHN_LEVEL_CONNECT) )
  3797. {
  3798. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE
  3799. + CurrentSecurityContext->MaximumSignatureLength()
  3800. + sizeof(sec_trailer);
  3801. }
  3802. else if ( AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY )
  3803. {
  3804. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE
  3805. + CurrentSecurityContext->MaximumHeaderLength()
  3806. + sizeof(sec_trailer);
  3807. }
  3808. break;
  3809. case rpc_cancel :
  3810. case rpc_orphaned :
  3811. case rpc_fault :
  3812. case rpc_response:
  3813. if (fExclusive)
  3814. {
  3815. if (!CachedSCallAvailable)
  3816. {
  3817. //
  3818. // The packet will be freed by the callee
  3819. //
  3820. fReceivePosted = CachedSCall->ProcessReceivedPDU(
  3821. Packet, BufferLength);
  3822. }
  3823. else
  3824. {
  3825. TransFreeBuffer(Packet);
  3826. fReceivePosted = 0;
  3827. goto End;
  3828. }
  3829. }
  3830. else
  3831. {
  3832. SCall = FindCall(Packet->call_id);
  3833. if (SCall == 0)
  3834. {
  3835. if (Packet->PTYPE == rpc_cancel
  3836. || Packet->PTYPE == rpc_orphaned)
  3837. {
  3838. //
  3839. // Too late, looks like the call is complete
  3840. //
  3841. TransFreeBuffer(Packet);
  3842. }
  3843. else
  3844. {
  3845. #if DBG
  3846. PrintToDebugger(
  3847. "RPC: Conn: 0x%lXNo SCall corresponding to the CallId: %d\n",
  3848. this, Packet->call_id);
  3849. ASSERT(0);
  3850. #endif
  3851. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  3852. }
  3853. break;
  3854. }
  3855. //
  3856. // The packet will be freed by the callee
  3857. //
  3858. fReceivePosted = SCall->ProcessReceivedPDU(Packet, BufferLength);
  3859. //
  3860. // Remove the reference added by the lookup
  3861. //
  3862. SCall->OSF_SCALL::RemoveReference(); // CALL--
  3863. }
  3864. break;
  3865. default:
  3866. SC_CLEANUP(RPC_S_PROTOCOL_ERROR, 0);
  3867. }
  3868. End:
  3869. //
  3870. // Submit the receive for the next packet
  3871. //
  3872. if (!fReceivePosted)
  3873. {
  3874. TransAsyncReceive();
  3875. }
  3876. //
  3877. // Remove the reference held by the pending receive
  3878. //
  3879. OSF_SCONNECTION::RemoveReference(); // CONN--
  3880. return;
  3881. Cleanup:
  3882. SendFault(Status, fDNE, Packet->call_id);
  3883. TransFreeBuffer(Packet);
  3884. AbortConnection();
  3885. }
  3886. RPC_STATUS
  3887. OSF_SCONNECTION::ImpersonateClient (
  3888. )
  3889. /*++
  3890. Function Name:ImpersonateClient
  3891. Parameters:
  3892. Description:
  3893. Returns:
  3894. --*/
  3895. {
  3896. RPC_STATUS Status;
  3897. if ( !RpcSecurityBeingUsed )
  3898. {
  3899. Status = SetThreadSecurityContext(
  3900. (SECURITY_CONTEXT *) MAXUINT_PTR);
  3901. if (RPC_S_OK != Status)
  3902. {
  3903. return Status;
  3904. }
  3905. return TransImpersonateClient();
  3906. }
  3907. SECURITY_CONTEXT * SecurityContext = CurrentSecurityContext;
  3908. if (!SecurityContext)
  3909. {
  3910. ASSERT(SecurityContextAltered);
  3911. return RPC_S_NO_CONTEXT_AVAILABLE;
  3912. }
  3913. Status = SetThreadSecurityContext(
  3914. SecurityContext);
  3915. if (RPC_S_OK != Status)
  3916. {
  3917. return Status;
  3918. }
  3919. Status = SecurityContext->ImpersonateClient();
  3920. if (RPC_S_OK != Status)
  3921. {
  3922. ClearThreadSecurityContext();
  3923. }
  3924. return Status;
  3925. }
  3926. RPC_STATUS
  3927. OSF_SCONNECTION::RevertToSelf (
  3928. )
  3929. /*++
  3930. Function Name:RevertToSelf
  3931. Parameters:
  3932. Description:
  3933. Returns:
  3934. --*/
  3935. {
  3936. SECURITY_CONTEXT * SecurityContext =
  3937. ClearThreadSecurityContext();
  3938. if (!RpcSecurityBeingUsed)
  3939. {
  3940. if (SecurityContext)
  3941. {
  3942. ASSERT(SecurityContext == (SECURITY_CONTEXT *) MAXUINT_PTR);
  3943. TransRevertToSelf();
  3944. }
  3945. return RPC_S_OK;
  3946. }
  3947. if (SecurityContext)
  3948. {
  3949. SecurityContext->RevertToSelf();
  3950. }
  3951. return(RPC_S_OK);
  3952. }
  3953. void
  3954. OSF_SCONNECTION::SendFault (
  3955. IN RPC_STATUS Status,
  3956. IN int DidNotExecute,
  3957. IN unsigned long CallId,
  3958. IN p_context_id_t p_cont_id
  3959. )
  3960. /*++
  3961. Function Name:SendFault
  3962. Parameters:
  3963. Description:
  3964. Returns:
  3965. --*/
  3966. {
  3967. rpcconn_fault *Fault;
  3968. size_t FaultSize;
  3969. BOOL fEEInfoPresent = FALSE;
  3970. if (g_fSendEEInfo)
  3971. {
  3972. fEEInfoPresent = PickleEEInfoIntoPacket(FaultSizeWithoutEEInfo,
  3973. (PVOID *)&Fault,
  3974. &FaultSize);
  3975. }
  3976. if (fEEInfoPresent)
  3977. {
  3978. Fault->reserved = FaultEEInfoPresent;
  3979. Fault->alloc_hint = FaultSize;
  3980. }
  3981. else
  3982. {
  3983. FaultSize = FaultSizeWithoutEEInfo;
  3984. Fault = (rpcconn_fault *)_alloca(FaultSize);
  3985. RpcpMemorySet(Fault, 0, FaultSize);
  3986. }
  3987. ConstructPacket((rpcconn_common *)Fault, rpc_fault, FaultSize);
  3988. if (DidNotExecute != 0)
  3989. {
  3990. DidNotExecute = PFC_DID_NOT_EXECUTE;
  3991. }
  3992. if (Status == ERROR_SHUTDOWN_IN_PROGRESS)
  3993. {
  3994. if (DidNotExecute)
  3995. {
  3996. Status = RPC_S_SERVER_UNAVAILABLE;
  3997. }
  3998. else
  3999. {
  4000. Status = ERROR_SERVER_SHUTDOWN_IN_PROGRESS;
  4001. }
  4002. }
  4003. Fault->common.pfc_flags |= PFC_FIRST_FRAG | PFC_LAST_FRAG | DidNotExecute;
  4004. Fault->status = MapToNcaStatusCode(Status);
  4005. Fault->common.call_id = CallId;
  4006. Fault->p_cont_id = p_cont_id;
  4007. TransSend(Fault, FaultSize);
  4008. if (fEEInfoPresent)
  4009. delete Fault;
  4010. }
  4011. BOOL
  4012. OSF_SCONNECTION::PickleEEInfoIntoPacket (
  4013. IN size_t PickleStartOffset,
  4014. OUT PVOID *Packet,
  4015. OUT size_t *PacketSize)
  4016. /*++
  4017. Function Name: PickeEEInfoIntoPacket
  4018. Parameters:
  4019. PickleStartOffset - the offset in bytes where the pickling starts
  4020. Packet - the allocated packet will be placed here on success.
  4021. PacketSize - the size of the packet if success is returned. If
  4022. failure is returned, this parameter is undefined
  4023. Description:
  4024. Checks for EEInfo on the thread, trims the EEInfo to MaxFrag,
  4025. allocates the packet, zeroes it out, and pickles the EEInfo
  4026. starting from PickleStartOffset.
  4027. Returns:
  4028. TRUE if EEInfo was pickled. FALSE if not.
  4029. --*/
  4030. {
  4031. unsigned char *CurrentPacket;
  4032. BOOL fEEInfoPresent = FALSE;
  4033. ExtendedErrorInfo *EEInfo;
  4034. RPC_STATUS RpcStatus;
  4035. size_t CurrentPacketSize;
  4036. EEInfo = RpcpGetEEInfo();
  4037. if (EEInfo)
  4038. {
  4039. ASSERT(MaxFrag > 0);
  4040. AddComputerNameToChain(EEInfo);
  4041. TrimEEInfoToLength (MaxFrag, &CurrentPacketSize);
  4042. if (CurrentPacketSize != 0)
  4043. {
  4044. CurrentPacketSize += PickleStartOffset;
  4045. CurrentPacket = new unsigned char[CurrentPacketSize];
  4046. if (CurrentPacket)
  4047. {
  4048. ASSERT(IsBufferAligned(CurrentPacket + PickleStartOffset));
  4049. RpcpMemorySet(CurrentPacket, 0, CurrentPacketSize);
  4050. RpcStatus = PickleEEInfo(EEInfo,
  4051. CurrentPacket + PickleStartOffset,
  4052. CurrentPacketSize - PickleStartOffset);
  4053. if (RpcStatus == RPC_S_OK)
  4054. {
  4055. fEEInfoPresent = TRUE;
  4056. *Packet = CurrentPacket;
  4057. *PacketSize = CurrentPacketSize;
  4058. }
  4059. else
  4060. {
  4061. delete CurrentPacket;
  4062. }
  4063. }
  4064. }
  4065. }
  4066. return fEEInfoPresent;
  4067. }
  4068. RPC_STATUS
  4069. OSF_SCONNECTION::SendFragment(
  4070. IN OUT rpcconn_common *pFragment,
  4071. IN unsigned int LastFragmentFlag,
  4072. IN unsigned int HeaderSize,
  4073. IN unsigned int MaxSecuritySize,
  4074. IN unsigned int DataLength,
  4075. IN unsigned int MaximumFragmentLength,
  4076. IN unsigned char *MyReservedForSec,
  4077. IN BOOL fAsync,
  4078. IN void *SendContext
  4079. )
  4080. /*++
  4081. Function Name:SendFragment
  4082. Parameters:
  4083. Description:
  4084. Returns:
  4085. --*/
  4086. {
  4087. sec_trailer * SecurityTrailer;
  4088. unsigned int SecurityLength;
  4089. unsigned int AuthPadLength;
  4090. SECURITY_BUFFER_DESCRIPTOR BufferDescriptor;
  4091. SECURITY_BUFFER SecurityBuffers[5];
  4092. DCE_MSG_SECURITY_INFO MsgSecurityInfo;
  4093. RPC_STATUS Status;
  4094. unsigned long AuthLevel;
  4095. AuthLevel = AuthInfo.AuthenticationLevel;
  4096. if ( ((AuthLevel != RPC_C_AUTHN_LEVEL_NONE)
  4097. && (AuthLevel != RPC_C_AUTHN_LEVEL_CONNECT))
  4098. || ((AuthLevel == RPC_C_AUTHN_LEVEL_CONNECT)
  4099. &&(MaxSecuritySize != 0)) )
  4100. {
  4101. if ( LastFragmentFlag == 0 )
  4102. {
  4103. SecurityTrailer = (sec_trailer *)
  4104. (((unsigned char *) pFragment)
  4105. + MaximumFragmentLength - MaxSecuritySize);
  4106. // It is not the last fragment, so we need to save away the
  4107. // part of the buffer which could get overwritten with
  4108. // authentication information. We can not use memcpy,
  4109. // because the source and destination regions may overlap.
  4110. RpcpMemoryMove(MyReservedForSec, SecurityTrailer,
  4111. MaxSecuritySize);
  4112. AuthPadLength = 0;
  4113. }
  4114. else
  4115. {
  4116. ASSERT( MAXIMUM_SECURITY_BLOCK_SIZE == 16 );
  4117. AuthPadLength = Pad16(HeaderSize+DataLength+sizeof(sec_trailer));
  4118. DataLength += AuthPadLength;
  4119. ASSERT( ((DataLength + HeaderSize+sizeof(sec_trailer))
  4120. % MAXIMUM_SECURITY_BLOCK_SIZE) == 0 );
  4121. SecurityTrailer = (sec_trailer *)
  4122. (((unsigned char *) pFragment) + DataLength
  4123. + HeaderSize);
  4124. pFragment->pfc_flags |= PFC_LAST_FRAG;
  4125. }
  4126. SecurityTrailer->auth_type = (unsigned char) AuthInfo.AuthenticationService;
  4127. SecurityTrailer->auth_level = (unsigned char) AuthLevel;
  4128. SecurityTrailer->auth_pad_length = (unsigned char) AuthPadLength;
  4129. SecurityTrailer->auth_reserved = 0;
  4130. SecurityTrailer->auth_context_id = AuthContextId;
  4131. BufferDescriptor.ulVersion = 0;
  4132. BufferDescriptor.cBuffers = 5;
  4133. BufferDescriptor.pBuffers = SecurityBuffers;
  4134. SecurityBuffers[0].cbBuffer = HeaderSize;
  4135. SecurityBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  4136. SecurityBuffers[0].pvBuffer = ((unsigned char *) pFragment);
  4137. SecurityBuffers[1].cbBuffer = (LastFragmentFlag != 0 ?
  4138. DataLength
  4139. : (MaximumFragmentLength - HeaderSize
  4140. - MaxSecuritySize ));
  4141. SecurityBuffers[1].BufferType = SECBUFFER_DATA;
  4142. SecurityBuffers[1].pvBuffer = ((unsigned char *) pFragment)
  4143. + HeaderSize;
  4144. SecurityBuffers[2].cbBuffer = sizeof(sec_trailer);
  4145. SecurityBuffers[2].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  4146. SecurityBuffers[2].pvBuffer = SecurityTrailer;
  4147. SecurityBuffers[3].cbBuffer = MaxSecuritySize - sizeof(sec_trailer);
  4148. SecurityBuffers[3].BufferType = SECBUFFER_TOKEN;
  4149. SecurityBuffers[3].pvBuffer = SecurityTrailer + 1;
  4150. SecurityBuffers[4].cbBuffer = sizeof(DCE_MSG_SECURITY_INFO);
  4151. SecurityBuffers[4].BufferType = SECBUFFER_PKG_PARAMS
  4152. | SECBUFFER_READONLY;
  4153. SecurityBuffers[4].pvBuffer = &MsgSecurityInfo;
  4154. MsgSecurityInfo.SendSequenceNumber =
  4155. DceSecurityInfo.SendSequenceNumber;
  4156. MsgSecurityInfo.ReceiveSequenceNumber =
  4157. DceSecurityInfo.ReceiveSequenceNumber;
  4158. MsgSecurityInfo.PacketType = pFragment->PTYPE;
  4159. pFragment->auth_length = (unsigned short) SecurityBuffers[3].cbBuffer;
  4160. SecurityLength = MaxSecuritySize;
  4161. if ( LastFragmentFlag != 0 )
  4162. {
  4163. pFragment->frag_length = HeaderSize + DataLength + SecurityLength;
  4164. }
  4165. else
  4166. {
  4167. pFragment->frag_length += SecurityLength - MaxSecuritySize;
  4168. }
  4169. Status = CurrentSecurityContext->SignOrSeal(
  4170. MsgSecurityInfo.SendSequenceNumber,
  4171. AuthLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  4172. &BufferDescriptor);
  4173. //
  4174. // If the package computes a checksum of the read-only buffers,
  4175. // then it should not change SecurityBuffers[3].cbBuffer.
  4176. //
  4177. // removed ASSERT( pFragment->auth_length == SecurityBuffers[3].cbBuffer);
  4178. {
  4179. //
  4180. // The package might have updated SecurityBuffers[3].cbBuffer.
  4181. // update the header appropriately
  4182. //
  4183. unsigned short AuthLengthChange = pFragment->auth_length - (unsigned short) SecurityBuffers[3].cbBuffer;
  4184. SecurityLength -= AuthLengthChange;
  4185. pFragment->auth_length -= AuthLengthChange;
  4186. pFragment->frag_length -= AuthLengthChange;
  4187. }
  4188. if (Status != RPC_S_OK)
  4189. {
  4190. if ( LastFragmentFlag == 0 )
  4191. {
  4192. RpcpMemoryCopy(SecurityTrailer, MyReservedForSec,
  4193. MaxSecuritySize);
  4194. }
  4195. if (Status == ERROR_SHUTDOWN_IN_PROGRESS)
  4196. {
  4197. return Status;
  4198. }
  4199. if ( (Status == SEC_E_CONTEXT_EXPIRED)
  4200. || (Status == SEC_E_QOP_NOT_SUPPORTED) )
  4201. {
  4202. return (RPC_S_SEC_PKG_ERROR);
  4203. }
  4204. return (RPC_S_ACCESS_DENIED);
  4205. }
  4206. }
  4207. else
  4208. {
  4209. SecurityLength = 0;
  4210. }
  4211. if ( LastFragmentFlag != 0 )
  4212. {
  4213. pFragment->pfc_flags |= PFC_LAST_FRAG;
  4214. ASSERT(pFragment->frag_length == DataLength+HeaderSize+SecurityLength);
  4215. if (fAsync)
  4216. {
  4217. Status = TransAsyncSend(
  4218. pFragment,
  4219. pFragment->frag_length,
  4220. SendContext);
  4221. }
  4222. else
  4223. {
  4224. Status = TransSend(
  4225. pFragment,
  4226. pFragment->frag_length);
  4227. }
  4228. if (Status != RPC_S_OK)
  4229. {
  4230. if ((Status == RPC_P_CONNECTION_CLOSED)
  4231. || (Status == RPC_P_SEND_FAILED))
  4232. {
  4233. return(RPC_S_CALL_FAILED_DNE);
  4234. }
  4235. if ( Status == RPC_P_RECEIVE_FAILED)
  4236. {
  4237. return(RPC_S_CALL_FAILED);
  4238. }
  4239. VALIDATE(Status)
  4240. {
  4241. RPC_S_OUT_OF_MEMORY,
  4242. RPC_S_OUT_OF_RESOURCES
  4243. } END_VALIDATE;
  4244. return(Status);
  4245. }
  4246. return(RPC_S_OK);
  4247. }
  4248. ASSERT(pFragment->frag_length == MaximumFragmentLength
  4249. - MaxSecuritySize + SecurityLength);
  4250. if (fAsync)
  4251. {
  4252. Status = TransAsyncSend (
  4253. pFragment,
  4254. pFragment->frag_length,
  4255. SendContext);
  4256. }
  4257. else
  4258. {
  4259. Status = TransSend(
  4260. pFragment,
  4261. pFragment->frag_length);
  4262. //
  4263. // We need to restore the part of the buffer which we overwrote
  4264. // with authentication information.
  4265. //
  4266. if ((AuthLevel != RPC_C_AUTHN_LEVEL_NONE)
  4267. &&(MaxSecuritySize != 0))
  4268. {
  4269. RpcpMemoryCopy(SecurityTrailer,
  4270. MyReservedForSec, MaxSecuritySize);
  4271. }
  4272. }
  4273. if ( Status != RPC_S_OK )
  4274. {
  4275. if ( (Status == RPC_P_CONNECTION_CLOSED)
  4276. || (Status == RPC_P_SEND_FAILED))
  4277. {
  4278. return(RPC_S_CALL_FAILED_DNE);
  4279. }
  4280. VALIDATE(Status)
  4281. {
  4282. RPC_S_OUT_OF_MEMORY,
  4283. RPC_S_OUT_OF_RESOURCES
  4284. } END_VALIDATE;
  4285. return(Status);
  4286. }
  4287. return Status ;
  4288. }
  4289. RPC_STATUS
  4290. OSF_SCONNECTION::GetServerPrincipalName (
  4291. IN unsigned long Flags,
  4292. OUT RPC_CHAR **ServerPrincipalName OPTIONAL
  4293. )
  4294. /*++
  4295. Routine Description:
  4296. Obtains the server principal name.
  4297. Arguments:
  4298. ServerPrincipalName - Returns the server principal name which the client
  4299. specified.
  4300. Return Value:
  4301. RPC_S_OK or RPC_S_* / Win32 error
  4302. --*/
  4303. {
  4304. RPC_STATUS Status;
  4305. SECURITY_CONTEXT * SecurityContext;
  4306. SecurityContext = CurrentSecurityContext;
  4307. if ( ARGUMENT_PRESENT(ServerPrincipalName) )
  4308. {
  4309. if (AuthInfo.AuthenticationService == RPC_C_AUTHN_GSS_SCHANNEL)
  4310. {
  4311. if (AuthInfo.PacHandle == 0)
  4312. {
  4313. Status = SecurityContext->GetDceInfo(
  4314. &AuthInfo.PacHandle,
  4315. &AuthInfo.AuthorizationService
  4316. );
  4317. if (Status)
  4318. {
  4319. return Status;
  4320. }
  4321. }
  4322. Status = RpcCertGeneratePrincipalName( (PCCERT_CONTEXT) AuthInfo.PacHandle,
  4323. Flags,
  4324. ServerPrincipalName
  4325. );
  4326. return Status;
  4327. }
  4328. else
  4329. {
  4330. Status = Address->Server->InquirePrincipalName(
  4331. SecurityContext->AuthenticationService, ServerPrincipalName);
  4332. VALIDATE(Status)
  4333. {
  4334. RPC_S_OK,
  4335. RPC_S_OUT_OF_MEMORY
  4336. } END_VALIDATE;
  4337. return(Status);
  4338. }
  4339. }
  4340. return RPC_S_OK;
  4341. }
  4342. RPC_STATUS
  4343. OSF_SCONNECTION::InquireAuthClient (
  4344. OUT RPC_AUTHZ_HANDLE * Privileges,
  4345. OUT RPC_CHAR * * ServerPrincipalName, OPTIONAL
  4346. OUT unsigned long * AuthenticationLevel,
  4347. OUT unsigned long * AuthenticationService,
  4348. OUT unsigned long * AuthorizationService,
  4349. IN unsigned long Flags
  4350. )
  4351. /*++
  4352. Routine Description:
  4353. Each protocol module must define this routine: it is used to obtain
  4354. the authentication and authorization information about a client making
  4355. the remote procedure call represented by this.
  4356. Arguments:
  4357. Privileges - Returns a the privileges of the client.
  4358. ServerPrincipalName - Returns the server principal name which the client
  4359. specified.
  4360. AuthenticationLevel - Returns the authentication level requested by
  4361. the client.
  4362. AuthenticationService - Returns the authentication service requested by
  4363. the client.
  4364. AuthorizationService - Returns the authorization service requested by
  4365. the client.
  4366. Return Value:
  4367. RPC_S_OK - The operation completed successfully.
  4368. RPC_S_BINDING_HAS_NO_AUTH - The remote procedure call represented by
  4369. this binding is not authenticated.
  4370. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to inquire the
  4371. server principal name.
  4372. --*/
  4373. {
  4374. RPC_STATUS Status;
  4375. SECURITY_CONTEXT * SecurityContext;
  4376. SecurityContext = CurrentSecurityContext;
  4377. if ( !SecurityContext )
  4378. {
  4379. return(RPC_S_BINDING_HAS_NO_AUTH);
  4380. }
  4381. if (AuthenticationLevel)
  4382. {
  4383. *AuthenticationLevel = SecurityContext->AuthenticationLevel;
  4384. }
  4385. if (AuthenticationService)
  4386. {
  4387. *AuthenticationService = SecurityContext->AuthenticationService;
  4388. }
  4389. if (Privileges || AuthorizationService)
  4390. {
  4391. if (AuthInfo.PacHandle == 0)
  4392. {
  4393. SecurityContext->GetDceInfo(
  4394. &AuthInfo.PacHandle,
  4395. &AuthInfo.AuthorizationService
  4396. );
  4397. }
  4398. if ( Privileges )
  4399. {
  4400. *Privileges = AuthInfo.PacHandle;
  4401. }
  4402. if ( AuthorizationService )
  4403. {
  4404. *AuthorizationService = AuthInfo.AuthorizationService;
  4405. }
  4406. }
  4407. Status = GetServerPrincipalName(Flags, ServerPrincipalName);
  4408. return(Status);
  4409. }
  4410. RPC_STATUS
  4411. OSF_SCONNECTION::InquireCallAttributes (
  4412. IN OUT void *RpcCallAttributes
  4413. )
  4414. /*++
  4415. Routine Description:
  4416. Inquire the security context attributes for the OSF client
  4417. Arguments:
  4418. RpcCallAttributes - a pointer to
  4419. RPC_CALL_ATTRIBUTES_V1_W structure. The Version
  4420. member must be initialized.
  4421. Return Value:
  4422. RPC_S_OK or RPC_S_* / Win32 error. EEInfo will be returned.
  4423. --*/
  4424. {
  4425. RPC_CALL_ATTRIBUTES_V1 *CallAttributes;
  4426. RPC_STATUS Status;
  4427. SECURITY_CONTEXT * SecurityContext;
  4428. RPC_CHAR *ServerPrincipalName = NULL;
  4429. ULONG ServerPrincipalNameLength; // in bytes, including terminating NULL
  4430. SecurityContext = CurrentSecurityContext;
  4431. if ( !SecurityContext )
  4432. {
  4433. return(RPC_S_BINDING_HAS_NO_AUTH);
  4434. }
  4435. CallAttributes =
  4436. (RPC_CALL_ATTRIBUTES_V1 *)RpcCallAttributes;
  4437. CallAttributes->AuthenticationLevel = SecurityContext->AuthenticationLevel;
  4438. CallAttributes->AuthenticationService = SecurityContext->AuthenticationService;
  4439. CallAttributes->NullSession = SecurityContext->ContextAttributes & ASC_RET_NULL_SESSION;
  4440. if (CallAttributes->Flags & RPC_QUERY_CLIENT_PRINCIPAL_NAME)
  4441. {
  4442. CallAttributes->ClientPrincipalNameBufferLength = 0;
  4443. }
  4444. if (CallAttributes->Flags & RPC_QUERY_SERVER_PRINCIPAL_NAME)
  4445. {
  4446. Status = GetServerPrincipalName(CallAttributes->Flags,
  4447. &ServerPrincipalName);
  4448. if (Status != RPC_S_OK)
  4449. return Status;
  4450. if (ServerPrincipalName)
  4451. {
  4452. ServerPrincipalNameLength = (RpcpStringLength(ServerPrincipalName) + 1) * sizeof(RPC_CHAR);
  4453. // now, see whether the user supplied memory is big enough
  4454. if (CallAttributes->ServerPrincipalNameBufferLength < ServerPrincipalNameLength)
  4455. {
  4456. Status = ERROR_MORE_DATA;
  4457. }
  4458. else
  4459. {
  4460. // a buffer is specified, and it is large enough
  4461. RpcpMemoryCopy(CallAttributes->ServerPrincipalName,
  4462. ServerPrincipalName,
  4463. ServerPrincipalNameLength);
  4464. Status = RPC_S_OK;
  4465. }
  4466. // in both cases store the resulting length
  4467. CallAttributes->ServerPrincipalNameBufferLength = ServerPrincipalNameLength;
  4468. RpcStringFree(&ServerPrincipalName);
  4469. }
  4470. else
  4471. {
  4472. CallAttributes->ServerPrincipalNameBufferLength = 0;
  4473. }
  4474. return Status;
  4475. }
  4476. else
  4477. {
  4478. return RPC_S_OK;
  4479. }
  4480. }
  4481. OSF_SBINDING *
  4482. OSF_SCONNECTION::LookupBinding (
  4483. IN p_context_id_t PresentContextId
  4484. )
  4485. /*++
  4486. Function Name:LookupBinding
  4487. Parameters:
  4488. Description:
  4489. Returns:
  4490. --*/
  4491. {
  4492. OSF_SBINDING *CurBinding;
  4493. DictionaryCursor cursor;
  4494. Bindings.Reset(cursor);
  4495. while ((CurBinding = Bindings.Next(cursor)))
  4496. {
  4497. if (CurBinding->GetPresentationContext() == PresentContextId)
  4498. {
  4499. return CurBinding;
  4500. }
  4501. }
  4502. return NULL;
  4503. }
  4504. RPC_STATUS
  4505. OSF_SCONNECTION::GetAssociationContextCollection (
  4506. OUT ContextCollection **CtxCollection
  4507. )
  4508. {
  4509. return Association->GetAssociationContextCollection(CtxCollection);
  4510. }
  4511. RPC_STATUS
  4512. OSF_SCONNECTION::IsClientLocal (
  4513. OUT unsigned int * ClientLocalFlag
  4514. )
  4515. /*++
  4516. Routine Description:
  4517. We just need to inquire the client process identifier for this
  4518. connection; if the first part is zero, then the client is local.
  4519. Arguments:
  4520. ClientLocalFlag - Returns an indication of whether or not the client is
  4521. local (ie. on the same machine as the server). This field will be
  4522. set to a non-zero value to indicate that the client is local;
  4523. otherwise, the client is remote.
  4524. Return Value:
  4525. RPC_S_OK - This will always be used.
  4526. --*/
  4527. {
  4528. RPC_CLIENT_PROCESS_IDENTIFIER ClientProcess;
  4529. int i;
  4530. TransQueryClientProcess(&ClientProcess);
  4531. if ( ClientProcess.IsLocal() == FALSE )
  4532. {
  4533. if (ClientProcess.IsNull())
  4534. return RPC_S_CANNOT_SUPPORT;
  4535. *ClientLocalFlag = 0;
  4536. }
  4537. else
  4538. {
  4539. *ClientLocalFlag = 1;
  4540. }
  4541. return(RPC_S_OK);
  4542. }
  4543. int
  4544. OSF_SCONNECTION::SendBindNak (
  4545. IN p_reject_reason_t reject_reason,
  4546. IN unsigned long CallId
  4547. )
  4548. {
  4549. rpcconn_bind_nak *BindNak;
  4550. size_t BindNakSize;
  4551. BOOL fEEInfoPresent = FALSE;
  4552. int RetVal;
  4553. if (g_fSendEEInfo)
  4554. {
  4555. fEEInfoPresent = PickleEEInfoIntoPacket(BindNakSizeWithoutEEInfo,
  4556. (PVOID *) &BindNak,
  4557. &BindNakSize);
  4558. }
  4559. if (fEEInfoPresent == FALSE)
  4560. {
  4561. BindNakSize = BindNakSizeWithoutEEInfoAndSignature;
  4562. BindNak = (rpcconn_bind_nak *)_alloca(BindNakSize);
  4563. RpcpMemorySet(BindNak, 0, BindNakSize);
  4564. }
  4565. else
  4566. {
  4567. RpcpMemoryCopy (&BindNak->Signature,
  4568. BindNakEEInfoSignature,
  4569. sizeof (UUID));
  4570. }
  4571. ConstructPacket((rpcconn_common *) BindNak, rpc_bind_nak, BindNakSize);
  4572. BindNak->provider_reject_reason = reject_reason;
  4573. BindNak->versions.n_protocols = 1;
  4574. BindNak->versions.p_protocols[0].major = OSF_RPC_V20_VERS;
  4575. BindNak->versions.p_protocols[0].minor = 0;
  4576. BindNak->common.call_id = CallId;
  4577. BindNak->common.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG ;
  4578. if (TransSend(BindNak,BindNakSize))
  4579. {
  4580. RetVal = -1;
  4581. }
  4582. else
  4583. {
  4584. RetVal = 0;
  4585. }
  4586. if (fEEInfoPresent)
  4587. {
  4588. delete BindNak;
  4589. }
  4590. return RetVal;
  4591. }
  4592. typedef struct tagSelectedInterfaceAndTransferSyntaxInfo
  4593. {
  4594. RPC_INTERFACE *Interface;
  4595. int SelectedAvailableTransferSyntaxIndex;
  4596. } SelectedInterfaceAndTransferSyntaxInfo;
  4597. int
  4598. OSF_SCONNECTION::ProcessPContextList (
  4599. IN OSF_ADDRESS * Address,
  4600. IN p_cont_list_t *PContextList,
  4601. IN OUT unsigned int * PContextListLength,
  4602. OUT p_result_list_t *ResultList
  4603. )
  4604. /*++
  4605. Routine Description:
  4606. Arguments:
  4607. Address - Supplies the address which owns this connection. We need
  4608. this information so that we can try to find the interface (and
  4609. transfer syntax) the client requested.
  4610. PContextList - Supplies a pointer to the presentation context list
  4611. which the client passed in the rpc_bind packet. It has not yet
  4612. had data conversion performed on it.
  4613. PContextListLength - Supplies the maximum possible length of the
  4614. presentation context list, and returns its actual length. The
  4615. lengths are in bytes as usual.
  4616. ResultList - Returns the result list corresponding to the presentation
  4617. context list.
  4618. Return Value:
  4619. A non-zero value will be returned if we are unable to process the
  4620. presentation context list. The caller should send an rpc_bind_nak
  4621. packet to the client, and then close the connection.
  4622. --*/
  4623. {
  4624. p_cont_elem_t *PContextElem;
  4625. unsigned int PContextListIndex;
  4626. unsigned int TransferSyntaxIndex;
  4627. SelectedInterfaceAndTransferSyntaxInfo *SelectionInfo;
  4628. OSF_SBINDING * SBinding;
  4629. RPC_STATUS Status;
  4630. BOOL fInterfaceTransferIsPreferred;
  4631. p_result_t *PResultElem;
  4632. int PreferredPContextIndex;
  4633. BOOL fRejectCurrentContext;
  4634. BOOL fPContextAlreadyAccepted;
  4635. unsigned int NumberOfPContextElements;
  4636. int fIgnored;
  4637. if (*PContextListLength < sizeof(p_cont_list_t))
  4638. {
  4639. return(1);
  4640. }
  4641. NumberOfPContextElements = (unsigned int) PContextList->n_context_elem;
  4642. // make sure the client doesn't offer a gaziliion pcontexts
  4643. if (NumberOfPContextElements > 20)
  4644. {
  4645. return 1;
  4646. }
  4647. SelectionInfo = (SelectedInterfaceAndTransferSyntaxInfo *)
  4648. _alloca(sizeof(SelectedInterfaceAndTransferSyntaxInfo) * NumberOfPContextElements);
  4649. *PContextListLength -= (sizeof(p_cont_list_t) - sizeof(p_cont_elem_t));
  4650. ResultList->n_results = PContextList->n_context_elem;
  4651. ResultList->reserved = 0;
  4652. ResultList->reserved2 = 0;
  4653. PreferredPContextIndex = -1;
  4654. for (PContextListIndex = 0, PContextElem = PContextList->p_cont_elem;
  4655. PContextListIndex < NumberOfPContextElements;
  4656. PContextListIndex ++)
  4657. {
  4658. if (*PContextListLength < sizeof(p_cont_elem_t))
  4659. {
  4660. return(1);
  4661. }
  4662. if (*PContextListLength < (sizeof(p_cont_elem_t) + sizeof(p_syntax_id_t)
  4663. * (PContextElem->n_transfer_syn - 1)))
  4664. {
  4665. return(1);
  4666. }
  4667. *PContextListLength -= (sizeof(p_cont_elem_t) + sizeof(p_syntax_id_t)
  4668. * (PContextElem->n_transfer_syn - 1));
  4669. if ( DataConvertEndian(((unsigned char *) &DataRep)) != 0 )
  4670. {
  4671. PContextElem->p_cont_id = RpcpByteSwapShort(PContextElem->p_cont_id);
  4672. ByteSwapSyntaxId(&PContextElem->abstract_syntax);
  4673. for ( TransferSyntaxIndex = 0;
  4674. TransferSyntaxIndex < PContextElem->n_transfer_syn;
  4675. TransferSyntaxIndex++ )
  4676. {
  4677. ByteSwapSyntaxId(&(PContextElem->transfer_syntaxes[
  4678. TransferSyntaxIndex]));
  4679. }
  4680. }
  4681. Status = Address->FindInterfaceTransfer(
  4682. (PRPC_SYNTAX_IDENTIFIER)
  4683. &PContextElem->abstract_syntax.if_uuid,
  4684. (PRPC_SYNTAX_IDENTIFIER) PContextElem->transfer_syntaxes,
  4685. PContextElem->n_transfer_syn,
  4686. (PRPC_SYNTAX_IDENTIFIER)
  4687. &(ResultList->p_results[PContextListIndex].transfer_syntax),
  4688. &SelectionInfo[PContextListIndex].Interface,
  4689. &fInterfaceTransferIsPreferred,
  4690. &fIgnored,
  4691. &SelectionInfo[PContextListIndex].SelectedAvailableTransferSyntaxIndex);
  4692. if (Status == RPC_S_OK)
  4693. {
  4694. ResultList->p_results[PContextListIndex].result = acceptance;
  4695. ResultList->p_results[PContextListIndex].reason = 0;
  4696. if (fInterfaceTransferIsPreferred)
  4697. {
  4698. // only one pcontext can be preferred. If not, there is
  4699. // error in the stubs
  4700. ASSERT(PreferredPContextIndex == -1);
  4701. PreferredPContextIndex = PContextListIndex;
  4702. }
  4703. // for all accepted we will make a second pass once we know
  4704. // which transfer syntax will be selected
  4705. }
  4706. else
  4707. {
  4708. ResultList->p_results[PContextListIndex].result =
  4709. provider_rejection;
  4710. if (Status == RPC_S_UNSUPPORTED_TRANS_SYN)
  4711. {
  4712. ResultList->p_results[PContextListIndex].reason =
  4713. proposed_transfer_syntaxes_not_supported;
  4714. }
  4715. else
  4716. {
  4717. ASSERT(Status == RPC_S_UNKNOWN_IF);
  4718. ResultList->p_results[PContextListIndex].reason =
  4719. abstract_syntax_not_supported;
  4720. }
  4721. memset(&(ResultList->p_results[PContextListIndex].
  4722. transfer_syntax.if_uuid.Data1),0,sizeof(GUID));
  4723. ResultList->p_results[PContextListIndex].
  4724. transfer_syntax.if_version = 0;
  4725. }
  4726. PContextElem = (p_cont_elem_t *) ((unsigned char *)PContextElem + sizeof(p_cont_elem_t)
  4727. + sizeof(p_syntax_id_t) * (PContextElem->n_transfer_syn - 1));
  4728. }
  4729. fPContextAlreadyAccepted = FALSE;
  4730. for (PContextListIndex = 0, PResultElem = ResultList->p_results,
  4731. PContextElem = PContextList->p_cont_elem;
  4732. PContextListIndex < NumberOfPContextElements;
  4733. PContextListIndex ++, PResultElem = &(ResultList->p_results[PContextListIndex]))
  4734. {
  4735. fRejectCurrentContext = TRUE;
  4736. // if there is a preferred context ...
  4737. if (PreferredPContextIndex >= 0)
  4738. {
  4739. // ... and this is the one, don't reject it
  4740. if ((unsigned int)PreferredPContextIndex == PContextListIndex)
  4741. {
  4742. ASSERT(PResultElem->result == acceptance);
  4743. fRejectCurrentContext = FALSE;
  4744. }
  4745. else
  4746. {
  4747. // else nothing - this is not the preferred one, and the
  4748. // default action is reject it
  4749. }
  4750. }
  4751. else if (PResultElem->result == acceptance)
  4752. {
  4753. // if we haven't already accepted one, accept the current
  4754. if (!fPContextAlreadyAccepted)
  4755. {
  4756. fRejectCurrentContext = FALSE;
  4757. fPContextAlreadyAccepted = TRUE;
  4758. }
  4759. else
  4760. {
  4761. // else nothing - we have already accepted one and
  4762. // we will reject this one
  4763. }
  4764. }
  4765. if (!fRejectCurrentContext)
  4766. {
  4767. SBinding = new OSF_SBINDING(SelectionInfo[PContextListIndex].Interface,
  4768. PContextElem->p_cont_id,
  4769. SelectionInfo[PContextListIndex].SelectedAvailableTransferSyntaxIndex);
  4770. if ( (SBinding == 0)
  4771. || (Bindings.Insert(SBinding) == -1))
  4772. {
  4773. PResultElem->result = provider_rejection;
  4774. PResultElem->reason = local_limit_exceeded;
  4775. memset(&(PResultElem->transfer_syntax.if_uuid.Data1), 0, sizeof(p_syntax_id_t));
  4776. }
  4777. }
  4778. else if (PResultElem->result == acceptance)
  4779. {
  4780. // apparently we have already accepted somebody, and this is not the
  4781. // lucky one
  4782. PResultElem->result = provider_rejection;
  4783. PResultElem->reason = proposed_transfer_syntaxes_not_supported;
  4784. memset(&(PResultElem->transfer_syntax.if_uuid.Data1), 0, sizeof(p_syntax_id_t));
  4785. }
  4786. else
  4787. {
  4788. // nothing - we have to reject the current one, and it has already
  4789. // been rejected
  4790. }
  4791. PContextElem = (p_cont_elem_t *) ((unsigned char *)PContextElem + sizeof(p_cont_elem_t)
  4792. + sizeof(p_syntax_id_t) * (PContextElem->n_transfer_syn - 1));
  4793. }
  4794. return(0);
  4795. }
  4796. unsigned short // Return the minimum of the three arguments.
  4797. MinOf (
  4798. IN unsigned short Arg1,
  4799. IN unsigned short Arg2,
  4800. IN unsigned short Arg3
  4801. )
  4802. {
  4803. unsigned short Min = 0xFFFF;
  4804. if (Arg1 < Min)
  4805. Min = Arg1;
  4806. if (Arg2 < Min)
  4807. Min = Arg2;
  4808. if (Arg3 < Min)
  4809. Min = Arg3;
  4810. return(Min);
  4811. }
  4812. int
  4813. OSF_SCONNECTION::AssociationRequested (
  4814. IN rpcconn_bind * BindPacket,
  4815. IN unsigned int BindPacketLength
  4816. )
  4817. /*++
  4818. Routine Description:
  4819. Arguments:
  4820. Address - Supplies the address which owns this connection.
  4821. BindPacket - Supplies the buffer containing the rpc_bind packet
  4822. received from the client.
  4823. BindPacketLength - Supplies the length of the buffer in bytes.
  4824. Return Value:
  4825. A non-zero return value indicates that the connection needs to
  4826. be deleted by the caller.
  4827. --*/
  4828. {
  4829. p_cont_list_t * PContextList;
  4830. unsigned int SecondaryAddressLength;
  4831. unsigned int BindAckLength, TokenLength = 0, AuthPadLength;
  4832. rpcconn_bind_ack * BindAck;
  4833. RPC_STATUS Status;
  4834. sec_trailer * SecurityTrailer, * NewSecurityTrailer;
  4835. SECURITY_CREDENTIALS * SecurityCredentials = 0;
  4836. RPC_CLIENT_PROCESS_IDENTIFIER ClientProcess;
  4837. unsigned int CompleteNeeded = 0;
  4838. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  4839. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  4840. SECURITY_BUFFER InputBuffers[4];
  4841. SECURITY_BUFFER OutputBuffers[4];
  4842. unsigned long CallId = BindPacket->common.call_id;
  4843. ULONG CalculatedSize;
  4844. PContextList = (p_cont_list_t *) (BindPacket + 1);
  4845. CalculatedSize = sizeof(rpcconn_bind)+sizeof(p_cont_list_t)
  4846. + (PContextList->n_context_elem-1)*sizeof(p_cont_elem_t);
  4847. DataRep = * (unsigned long *) BindPacket->common.drep;
  4848. if ( BindPacketLength < CalculatedSize )
  4849. {
  4850. TransFreeBuffer(BindPacket);
  4851. SendBindNak(reason_not_specified_reject, CallId);
  4852. return(1);
  4853. }
  4854. if ( DataConvertEndian(BindPacket->common.drep) != 0 )
  4855. {
  4856. BindPacket->max_xmit_frag = RpcpByteSwapShort(BindPacket->max_xmit_frag);
  4857. BindPacket->max_recv_frag = RpcpByteSwapShort(BindPacket->max_recv_frag);
  4858. BindPacket->assoc_group_id = RpcpByteSwapLong(BindPacket->assoc_group_id);
  4859. }
  4860. ASSERT(TransMaximumSend() % 8 == 0);
  4861. MaxFrag = MinOf(BindPacket->max_xmit_frag,
  4862. BindPacket->max_recv_frag,
  4863. (unsigned short) TransMaximumSend()) & 0xFFFFFFF8;
  4864. if ( MaxFrag < MUST_RECV_FRAG_SIZE )
  4865. MaxFrag = MUST_RECV_FRAG_SIZE;
  4866. ASSERT(MaxFrag % 8 == 0);
  4867. // Now we need to check to see if we should be performing authentication
  4868. // at the rpc protocol level. This will be the case if there is
  4869. // authentication information in the packet.
  4870. if ( BindPacket->common.auth_length != 0 )
  4871. {
  4872. // Ok, we have got authentication information in the packet. We
  4873. // will save away the information, and then check it.
  4874. SecurityTrailer = (sec_trailer *)
  4875. (((unsigned char *) BindPacket) + BindPacketLength
  4876. - BindPacket->common.auth_length - sizeof(sec_trailer));
  4877. AuthInfo.AuthenticationLevel = SecurityTrailer->auth_level;
  4878. //Hack for OSF Clients
  4879. //If Level is CALL .. bump it ip to CONNECT
  4880. if (AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_CALL)
  4881. {
  4882. AuthInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT;
  4883. }
  4884. if ( (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_CONNECT)
  4885. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT)
  4886. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  4887. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) )
  4888. {
  4889. TransFreeBuffer(BindPacket);
  4890. SendBindNak(reason_not_specified_reject, CallId);
  4891. return(1);
  4892. }
  4893. AuthInfo.AuthenticationService = SecurityTrailer->auth_type;
  4894. AuthContextId = SecurityTrailer->auth_context_id;
  4895. if ( DataConvertEndian(BindPacket->common.drep) != 0 )
  4896. {
  4897. AuthContextId = RpcpByteSwapLong(AuthContextId);
  4898. }
  4899. RPC_STATUS Status = RPC_S_OK;
  4900. CurrentSecurityContext = new SECURITY_CONTEXT(
  4901. &AuthInfo,
  4902. AuthContextId,
  4903. FALSE,
  4904. &Status
  4905. );
  4906. if ( (CurrentSecurityContext == 0)
  4907. || RPC_S_OK != Status
  4908. ||(SecurityContextDict.Insert(CurrentSecurityContext) == -1) )
  4909. {
  4910. TransFreeBuffer(BindPacket);
  4911. SendBindNak(local_limit_exceeded_reject, CallId);
  4912. return(1);
  4913. }
  4914. CallTestHook( TH_RPC_SECURITY_SERVER_CONTEXT_CREATED, CurrentSecurityContext, this );
  4915. RpcSecurityBeingUsed = 1;
  4916. Status = Address->Server->AcquireCredentials(
  4917. AuthInfo.AuthenticationService, AuthInfo.AuthenticationLevel,
  4918. &SecurityCredentials);
  4919. if ( Status == RPC_S_OUT_OF_MEMORY )
  4920. {
  4921. TransFreeBuffer(BindPacket);
  4922. SendBindNak(local_limit_exceeded_reject, CallId);
  4923. return(1);
  4924. }
  4925. if ( Status != RPC_S_OK )
  4926. {
  4927. TransFreeBuffer(BindPacket);
  4928. RpcpErrorAddRecord(EEInfoGCRuntime,
  4929. Status,
  4930. EEInfoDLAssociationRequested30,
  4931. AuthInfo.AuthenticationService,
  4932. AuthInfo.AuthenticationLevel);
  4933. SendBindNak(authentication_type_not_recognized, CallId);
  4934. return(1);
  4935. }
  4936. ASSERT( SecurityCredentials != 0 );
  4937. }
  4938. // Calculate the size of the rpc_bind_ack packet.
  4939. SecondaryAddressLength = Address->TransSecondarySize();
  4940. BindAckLength = sizeof(rpcconn_bind_ack) + SecondaryAddressLength
  4941. + Pad4(SecondaryAddressLength + 2) + sizeof(p_result_list_t)
  4942. + sizeof(p_result_t) * (PContextList->n_context_elem - 1);
  4943. // Ok, we need to save some space for authentication information if
  4944. // necessary. This includes space for the token, the security trailer,
  4945. // and alignment if necessary.
  4946. if ( SecurityCredentials != 0 )
  4947. {
  4948. AuthPadLength = Pad4(BindAckLength);
  4949. BindAckLength += SecurityCredentials->MaximumTokenLength()
  4950. + sizeof(sec_trailer) + AuthPadLength;
  4951. }
  4952. // Allocate the rpc_bind_ack packet. If that fails, send a rpc_bind_nak
  4953. // to the client indicating that the server is out of resources;
  4954. // whoever called AssociationRequested will take care of cleaning up
  4955. // the connection.
  4956. Status = TransGetBuffer((void **) &BindAck, BindAckLength);
  4957. if ( Status != RPC_S_OK )
  4958. {
  4959. ASSERT( Status == RPC_S_OUT_OF_MEMORY );
  4960. if ( SecurityCredentials != 0 )
  4961. {
  4962. SecurityCredentials->DereferenceCredentials();
  4963. }
  4964. TransFreeBuffer(BindPacket);
  4965. SendBindNak(local_limit_exceeded_reject, CallId);
  4966. return(1);
  4967. }
  4968. // Finally we get to do something about that authentication that the
  4969. // client sent us.
  4970. if ( SecurityCredentials != 0 )
  4971. {
  4972. NewSecurityTrailer = (sec_trailer *)
  4973. (((unsigned char *) BindAck) + BindAckLength
  4974. - SecurityCredentials->MaximumTokenLength()
  4975. - sizeof(sec_trailer));
  4976. InitSecurityInfo.DceSecurityInfo = DceSecurityInfo;
  4977. InitSecurityInfo.PacketType = BindPacket->common.PTYPE;
  4978. InputBufferDescriptor.ulVersion = 0;
  4979. InputBufferDescriptor.cBuffers = 4;
  4980. InputBufferDescriptor.pBuffers = InputBuffers;
  4981. InputBuffers[0].cbBuffer = sizeof(rpcconn_bind);
  4982. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  4983. InputBuffers[0].pvBuffer = SavedHeader;
  4984. InputBuffers[1].cbBuffer = BindPacket->common.frag_length
  4985. - sizeof(rpcconn_bind) - BindPacket->common.auth_length;
  4986. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  4987. InputBuffers[1].pvBuffer = (char *) SavedHeader +
  4988. sizeof(rpcconn_bind);
  4989. InputBuffers[2].cbBuffer = BindPacket->common.auth_length;
  4990. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  4991. InputBuffers[2].pvBuffer = SecurityTrailer + 1;
  4992. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  4993. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  4994. InputBuffers[3].pvBuffer = &InitSecurityInfo;
  4995. OutputBufferDescriptor.ulVersion = 0;
  4996. OutputBufferDescriptor.cBuffers = 4;
  4997. OutputBufferDescriptor.pBuffers = OutputBuffers;
  4998. OutputBuffers[0].cbBuffer = sizeof(rpcconn_bind_ack)
  4999. - sizeof(unsigned short);
  5000. OutputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5001. OutputBuffers[0].pvBuffer = BindAck;
  5002. OutputBuffers[1].cbBuffer = BindAckLength
  5003. - SecurityCredentials->MaximumTokenLength()
  5004. - (sizeof(rpcconn_bind_ack) - sizeof(unsigned short));
  5005. OutputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5006. OutputBuffers[1].pvBuffer = ((unsigned char *) BindAck)
  5007. + sizeof(rpcconn_bind_ack) - sizeof(unsigned short);
  5008. OutputBuffers[2].cbBuffer = SecurityCredentials->MaximumTokenLength();
  5009. OutputBuffers[2].BufferType = SECBUFFER_TOKEN;
  5010. OutputBuffers[2].pvBuffer = NewSecurityTrailer + 1;
  5011. OutputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  5012. OutputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  5013. OutputBuffers[3].pvBuffer = &InitSecurityInfo;
  5014. Status = CurrentSecurityContext->AcceptFirstTime(
  5015. SecurityCredentials,
  5016. &InputBufferDescriptor,
  5017. &OutputBufferDescriptor,
  5018. SecurityTrailer->auth_level,
  5019. *((unsigned long *) BindPacket->common.drep),
  5020. 0);
  5021. LogEvent(SU_SCONN, EV_SEC_ACCEPT1, this, LongToPtr(Status), OutputBuffers[2].cbBuffer);
  5022. #if 0
  5023. if (Status == SEC_E_BUFFER_TOO_SMALL)
  5024. {
  5025. unsigned long NewTokenLength = OutputBuffers[2].cbBuffer;
  5026. TransFreeBuffer( BindAck );
  5027. BindAckLength = sizeof(rpcconn_bind_ack) + SecondaryAddressLength
  5028. + Pad4(SecondaryAddressLength + 2) + sizeof(p_result_list_t)
  5029. + sizeof(p_result_t) * (PContextList->n_context_elem - 1);
  5030. AuthPadLength = Pad4(BindAckLength);
  5031. BindAckLength += NewTokenLength
  5032. + sizeof(sec_trailer) + AuthPadLength;
  5033. Status = TransGetBuffer((void **) &BindAck, BindAckLength);
  5034. if ( Status != RPC_S_OK )
  5035. {
  5036. ASSERT( Status == RPC_S_OUT_OF_MEMORY );
  5037. SecurityCredentials->DereferenceCredentials();
  5038. TransFreeBuffer(BindPacket);
  5039. SendBindNak(local_limit_exceeded_reject, CallId);
  5040. return(1);
  5041. }
  5042. NewSecurityTrailer = (sec_trailer *)
  5043. (((unsigned char *) BindAck) + BindAckLength
  5044. - NewTokenLength
  5045. - sizeof(sec_trailer));
  5046. OutputBufferDescriptor.ulVersion = 0;
  5047. OutputBufferDescriptor.cBuffers = 4;
  5048. OutputBufferDescriptor.pBuffers = OutputBuffers;
  5049. OutputBuffers[0].cbBuffer = sizeof(rpcconn_bind_ack)
  5050. - sizeof(unsigned short);
  5051. OutputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5052. OutputBuffers[0].pvBuffer = BindAck;
  5053. OutputBuffers[1].cbBuffer = BindAckLength
  5054. - NewTokenLength
  5055. - (sizeof(rpcconn_bind_ack) - sizeof(unsigned short));
  5056. OutputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5057. OutputBuffers[1].pvBuffer = ((unsigned char *) BindAck)
  5058. + sizeof(rpcconn_bind_ack) - sizeof(unsigned short);
  5059. OutputBuffers[2].cbBuffer = NewTokenLength;
  5060. OutputBuffers[2].BufferType = SECBUFFER_TOKEN;
  5061. OutputBuffers[2].pvBuffer = NewSecurityTrailer + 1;
  5062. OutputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  5063. OutputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  5064. OutputBuffers[3].pvBuffer = &InitSecurityInfo;
  5065. Status = CurrentSecurityContext->AcceptFirstTime(
  5066. SecurityCredentials,
  5067. &InputBufferDescriptor,
  5068. &OutputBufferDescriptor,
  5069. SecurityTrailer->auth_level,
  5070. *((unsigned long *) BindPacket->common.drep),
  5071. 0);
  5072. LogEvent(SU_SCONN, EV_SEC_ACCEPT1, this, (void *) Status, OutputBuffers[2].cbBuffer);
  5073. }
  5074. #endif
  5075. TokenLength = (unsigned int) OutputBuffers[2].cbBuffer;
  5076. if ( ( Status == RPC_P_CONTINUE_NEEDED )
  5077. || ( Status == RPC_S_OK )
  5078. || ( Status == RPC_P_COMPLETE_NEEDED )
  5079. || ( Status == RPC_P_COMPLETE_AND_CONTINUE ) )
  5080. {
  5081. if ( Status == RPC_P_CONTINUE_NEEDED )
  5082. {
  5083. AuthContinueNeeded = 1;
  5084. }
  5085. else if ( Status == RPC_P_COMPLETE_AND_CONTINUE )
  5086. {
  5087. AuthContinueNeeded = 1;
  5088. CompleteNeeded = 1;
  5089. }
  5090. else if ( Status == RPC_P_COMPLETE_NEEDED )
  5091. {
  5092. CompleteNeeded = 1;
  5093. }
  5094. BindAckLength = BindAckLength + TokenLength
  5095. - SecurityCredentials->MaximumTokenLength();
  5096. NewSecurityTrailer->auth_type = SecurityTrailer->auth_type;
  5097. NewSecurityTrailer->auth_level = SecurityTrailer->auth_level;
  5098. NewSecurityTrailer->auth_pad_length = (unsigned char) AuthPadLength;
  5099. NewSecurityTrailer->auth_reserved = 0;
  5100. NewSecurityTrailer->auth_context_id = AuthContextId;
  5101. SecurityCredentials->DereferenceCredentials();
  5102. }
  5103. else
  5104. {
  5105. VALIDATE(Status)
  5106. {
  5107. RPC_S_OUT_OF_MEMORY,
  5108. RPC_S_ACCESS_DENIED,
  5109. ERROR_SHUTDOWN_IN_PROGRESS,
  5110. RPC_S_UNKNOWN_AUTHN_SERVICE
  5111. } END_VALIDATE;
  5112. TransFreeBuffer(BindPacket);
  5113. TransFreeBuffer(BindAck);
  5114. SecurityCredentials->DereferenceCredentials();
  5115. if (Status == RPC_S_OUT_OF_MEMORY)
  5116. {
  5117. SendBindNak(local_limit_exceeded_reject, CallId);
  5118. }
  5119. else
  5120. if (Status == RPC_S_UNKNOWN_AUTHN_SERVICE ||
  5121. Status == ERROR_SHUTDOWN_IN_PROGRESS )
  5122. {
  5123. SendBindNak(authentication_type_not_recognized, CallId);
  5124. }
  5125. else
  5126. {
  5127. SendBindNak(invalid_checksum, CallId);
  5128. }
  5129. return(1);
  5130. }
  5131. }
  5132. TransQueryClientProcess(&ClientProcess);
  5133. if ( BindPacket->assoc_group_id != 0 )
  5134. {
  5135. // This means this is a connection on an existing association.
  5136. Association = Address->FindAssociation(
  5137. (int) BindPacket->assoc_group_id, &ClientProcess);
  5138. if ( Association == 0 )
  5139. {
  5140. RpcpErrorAddRecord (EEInfoGCRuntime,
  5141. RPC_S_ENTRY_NOT_FOUND,
  5142. EEInfoDLAssociationRequested10,
  5143. BindPacket->assoc_group_id,
  5144. ClientProcess.GetDebugULongLong1(),
  5145. ClientProcess.GetDebugULongLong2());
  5146. TransFreeBuffer(BindPacket);
  5147. TransFreeBuffer(BindAck);
  5148. SendBindNak(reason_not_specified_reject, CallId);
  5149. return(1);
  5150. }
  5151. }
  5152. if ( Association == 0 )
  5153. {
  5154. Association = new OSF_ASSOCIATION(Address, &ClientProcess, &Status);
  5155. if ( (Association == 0) || (Status != RPC_S_OK) )
  5156. {
  5157. if (Association != 0)
  5158. {
  5159. delete Association;
  5160. Association = NULL;
  5161. }
  5162. TransFreeBuffer(BindPacket);
  5163. TransFreeBuffer(BindAck);
  5164. RpcpErrorAddRecord (EEInfoGCRuntime,
  5165. Status,
  5166. EEInfoDLAssociationRequested20,
  5167. sizeof(OSF_ASSOCIATION));
  5168. SendBindNak(local_limit_exceeded_reject, CallId);
  5169. return(1);
  5170. }
  5171. }
  5172. BindPacketLength -= sizeof(rpcconn_bind);
  5173. if ( ProcessPContextList(Address, PContextList, &BindPacketLength,
  5174. (p_result_list_t *) (((unsigned char *) BindAck) + sizeof(rpcconn_bind_ack)
  5175. + SecondaryAddressLength + Pad4(SecondaryAddressLength + 2))) != 0 )
  5176. {
  5177. TransFreeBuffer(BindPacket);
  5178. TransFreeBuffer(BindAck);
  5179. SendBindNak(reason_not_specified_reject, CallId);
  5180. return(1);
  5181. }
  5182. // Fill in the header of the rpc_bind_ack packet.
  5183. ConstructPacket((rpcconn_common *) BindAck, rpc_bind_ack, BindAckLength);
  5184. BindAck->max_xmit_frag = BindAck->max_recv_frag = MaxFrag;
  5185. BindAck->assoc_group_id = Association->AssocGroupId();
  5186. BindAck->sec_addr_length = (unsigned short) SecondaryAddressLength;
  5187. BindAck->common.call_id = CallId;
  5188. if (PFC_CONC_MPX & BindPacket->common.pfc_flags)
  5189. {
  5190. ((rpcconn_common *) BindAck)->pfc_flags |=
  5191. (PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX) ;
  5192. }
  5193. else
  5194. {
  5195. fExclusive = 1;
  5196. ((rpcconn_common *) BindAck)->pfc_flags |=
  5197. (PFC_FIRST_FRAG | PFC_LAST_FRAG) ;
  5198. }
  5199. DceSecurityInfo.ReceiveSequenceNumber += 1;
  5200. if ( SecondaryAddressLength != 0 )
  5201. {
  5202. Status = Address->TransSecondary((unsigned char *) (BindAck + 1),
  5203. SecondaryAddressLength);
  5204. if (Status != RPC_S_OK)
  5205. {
  5206. ASSERT(Status == RPC_S_OUT_OF_MEMORY);
  5207. TransFreeBuffer(BindPacket);
  5208. TransFreeBuffer(BindAck);
  5209. SendBindNak(reason_not_specified_reject, CallId);
  5210. return(1);
  5211. }
  5212. }
  5213. // The result list has already been filled in by ProcessPContextList.
  5214. // All that is left to do, is fill in the authentication information.
  5215. BindAck->common.auth_length = (unsigned short) TokenLength;
  5216. // Send the rpc_bind_ack packet back to the client.
  5217. TransFreeBuffer(BindPacket);
  5218. if ( CompleteNeeded != 0 )
  5219. {
  5220. Status = CurrentSecurityContext->CompleteSecurityToken(
  5221. &OutputBufferDescriptor);
  5222. if (Status != RPC_S_OK)
  5223. {
  5224. TransFreeBuffer(BindAck);
  5225. SendBindNak(invalid_checksum, CallId);
  5226. return(1);
  5227. }
  5228. }
  5229. //
  5230. // We may need to do third leg AuthInfo.Authentication.
  5231. // we will do that when we receive the third leg packet
  5232. //
  5233. if ( AuthContinueNeeded == 0 )
  5234. {
  5235. //
  5236. // We need to figure out how much space to reserve for security
  5237. // information at the end of request and response packets.
  5238. // In addition to saving space for the signature or header,
  5239. // we need space to pad the packet to a multiple of the maximum
  5240. // security block size as well as for the security trailer.
  5241. //
  5242. //
  5243. // In the case where we need a third leg, this information will be obtained
  5244. // after we process the third leg packet.
  5245. //
  5246. if ((AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  5247. ||(AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT)
  5248. ||(AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_CONNECT) )
  5249. {
  5250. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE
  5251. + CurrentSecurityContext->MaximumSignatureLength()
  5252. + sizeof(sec_trailer);
  5253. }
  5254. else if (AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
  5255. {
  5256. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE
  5257. + CurrentSecurityContext->MaximumHeaderLength()
  5258. + sizeof(sec_trailer);
  5259. }
  5260. }
  5261. //
  5262. // Sending the bind ack should be the last thing we do
  5263. // in this function. The action will continue in the processing
  5264. // of the third leg.
  5265. //
  5266. Status = TransSend(BindAck, BindAckLength);
  5267. TransFreeBuffer(BindAck);
  5268. if ( Status != RPC_S_OK )
  5269. {
  5270. return(1);
  5271. }
  5272. if (DebugCell)
  5273. {
  5274. DWORD LocalFlags = 0;
  5275. if (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_NONE)
  5276. {
  5277. LocalFlags = AuthInfo.AuthenticationLevel << 1;
  5278. switch (AuthInfo.AuthenticationService)
  5279. {
  5280. case RPC_C_AUTHN_WINNT:
  5281. LocalFlags |= DBGCELL_AUTH_SVC_NTLM;
  5282. break;
  5283. case RPC_C_AUTHN_GSS_KERBEROS:
  5284. case RPC_C_AUTHN_GSS_NEGOTIATE:
  5285. LocalFlags |= DBGCELL_AUTH_SVC_KERB;
  5286. break;
  5287. default:
  5288. ASSERT(AuthInfo.AuthenticationService);
  5289. LocalFlags |= DBGCELL_AUTH_SVC_OTHER;
  5290. }
  5291. }
  5292. if (fExclusive)
  5293. LocalFlags |= 1;
  5294. DebugCell->ConnectionID[0] = ULongToPtr(ClientProcess.GetDebugULong1());
  5295. DebugCell->ConnectionID[1] = ULongToPtr(ClientProcess.GetDebugULong2());
  5296. DebugCell->Flags = (unsigned char)LocalFlags;
  5297. }
  5298. return(0);
  5299. }
  5300. int
  5301. OSF_SCONNECTION::AlterContextRequested (
  5302. IN rpcconn_alter_context * AlterContext,
  5303. IN unsigned int AlterContextLength
  5304. )
  5305. /*++
  5306. Routine Description:
  5307. Arguments:
  5308. AlterContext - Supplies the buffer containing the rpc_alter_context
  5309. packet received from the client.
  5310. AlterContextLength - Supplies the length of the buffer in bytes.
  5311. Address - Supplies the address which owns this connection.
  5312. Return Value:
  5313. A non-zero return value indicates that the connection needs to
  5314. be deleted by the caller.
  5315. --*/
  5316. {
  5317. p_cont_list_t *PContextList;
  5318. rpcconn_alter_context_resp * AlterContextResp = 0;
  5319. unsigned int AlterContextRespLength = 0;
  5320. unsigned int TokenLength = 0;
  5321. unsigned int CompleteNeeded = 0;
  5322. RPC_STATUS Status;
  5323. sec_trailer * SecurityTrailer, * NewSecurityTrailer;
  5324. SECURITY_BUFFER_DESCRIPTOR InputBufferDescriptor;
  5325. SECURITY_BUFFER_DESCRIPTOR OutputBufferDescriptor;
  5326. SECURITY_BUFFER InputBuffers[4];
  5327. SECURITY_BUFFER OutputBuffers[4];
  5328. DCE_INIT_SECURITY_INFO InitSecurityInfo;
  5329. SECURITY_CREDENTIALS * SecurityCredentials = 0;
  5330. unsigned long SecureAlterContext = 0;
  5331. unsigned int AuthPadLength;
  5332. unsigned long NewContextRequired = 0;
  5333. CLIENT_AUTH_INFO NewClientInfo;
  5334. unsigned NewId;
  5335. SECURITY_CONTEXT * SecId;
  5336. unsigned long CallId = AlterContext->common.call_id;
  5337. ULONG CalculatedSize;
  5338. //
  5339. // The packet has already been validate by whoever called this method.
  5340. // Data conversion of the common part of the header was performed at
  5341. // that time as well. We do not use the max_xmit_frag, max_recv_frag,
  5342. // or assoc_group_id fields of the packet, so we will not bother to
  5343. // data convert them.
  5344. //
  5345. // make sure PContextList is there
  5346. if ( AlterContextLength <
  5347. sizeof(rpcconn_alter_context) + sizeof(p_cont_list_t))
  5348. {
  5349. SendFault(RPC_S_ACCESS_DENIED, 1, CallId);
  5350. TransFreeBuffer(AlterContext);
  5351. return(1);
  5352. }
  5353. PContextList = (p_cont_list_t *) (AlterContext + 1);
  5354. CalculatedSize = sizeof(rpcconn_alter_context)+sizeof(p_cont_list_t)
  5355. + (PContextList->n_context_elem-1)*sizeof(p_cont_elem_t);
  5356. DataRep = * (unsigned long *) AlterContext->common.drep;
  5357. if ( AlterContextLength < CalculatedSize)
  5358. {
  5359. SendFault(RPC_S_ACCESS_DENIED, 1, CallId);
  5360. TransFreeBuffer(AlterContext);
  5361. return(1);
  5362. }
  5363. if ( AlterContext->common.auth_length != 0 )
  5364. {
  5365. //
  5366. // We are dealing with a secure alter context
  5367. // it may be adding a presentation context
  5368. // or a new security context
  5369. //
  5370. SecureAlterContext = 1;
  5371. SecurityTrailer = (sec_trailer *)
  5372. (((unsigned char *) AlterContext) + AlterContextLength -
  5373. AlterContext->common.auth_length - sizeof(sec_trailer));
  5374. NewId = SecurityTrailer->auth_context_id;
  5375. NewClientInfo.AuthenticationLevel = SecurityTrailer->auth_level;
  5376. NewClientInfo.AuthenticationService = SecurityTrailer->auth_type;
  5377. if (DataConvertEndian(((unsigned char *)&DataRep)) != 0)
  5378. {
  5379. NewId = RpcpByteSwapLong(NewId);
  5380. }
  5381. if (NewClientInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_CALL)
  5382. {
  5383. NewClientInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_PKT;
  5384. }
  5385. //
  5386. //Check to see if a new context is being added..
  5387. //
  5388. SecId = FindSecurityContext(NewId,
  5389. NewClientInfo.AuthenticationLevel,
  5390. NewClientInfo.AuthenticationService
  5391. );
  5392. if (SecId == 0)
  5393. {
  5394. RPC_STATUS Status = RPC_S_OK;
  5395. SecId = new SECURITY_CONTEXT(&NewClientInfo, NewId, FALSE, &Status);
  5396. if ( (SecId == 0)
  5397. || RPC_S_OK != Status
  5398. ||(SecurityContextDict.Insert(SecId) == -1) )
  5399. {
  5400. SendFault(RPC_S_OUT_OF_MEMORY, 1, CallId);
  5401. TransFreeBuffer(AlterContext);
  5402. return (1);
  5403. }
  5404. NewContextRequired = 1;
  5405. //
  5406. // If previously no secure rpc had taken place
  5407. // set original sec. context
  5408. // else, mark this connection to indicate
  5409. // security context is altered ..
  5410. //
  5411. if (RpcSecurityBeingUsed)
  5412. {
  5413. SecurityContextAltered = 1;
  5414. }
  5415. }
  5416. AuthInfo = NewClientInfo;
  5417. AuthInfo.ReferenceCredentials();
  5418. AuthContextId = NewId;
  5419. CurrentSecurityContext = SecId;
  5420. RpcSecurityBeingUsed = 1;
  5421. if ( (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_CONNECT)
  5422. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT)
  5423. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)
  5424. && (AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY) )
  5425. {
  5426. SendFault(RPC_S_ACCESS_DENIED, 1, CallId);
  5427. TransFreeBuffer(AlterContext);
  5428. return(1);
  5429. }
  5430. Status = Address->Server->AcquireCredentials(
  5431. AuthInfo.AuthenticationService,
  5432. AuthInfo.AuthenticationLevel,
  5433. &SecurityCredentials
  5434. );
  5435. if ( Status == RPC_S_OUT_OF_MEMORY ||
  5436. Status == ERROR_SHUTDOWN_IN_PROGRESS)
  5437. {
  5438. SendFault(Status, 1, CallId);
  5439. TransFreeBuffer(AlterContext);
  5440. return(1);
  5441. }
  5442. if ( Status != RPC_S_OK )
  5443. {
  5444. if (SecurityCredentials != 0)
  5445. {
  5446. SecurityCredentials->DereferenceCredentials();
  5447. }
  5448. SendFault(RPC_S_ACCESS_DENIED, 1, CallId);
  5449. TransFreeBuffer(AlterContext);
  5450. return(1);
  5451. }
  5452. ASSERT( SecurityCredentials != 0 );
  5453. } //if secure alter context
  5454. AlterContextRespLength =
  5455. sizeof(rpcconn_alter_context_resp) + sizeof(p_result_list_t)
  5456. + sizeof(p_result_t) * (PContextList->n_context_elem - 1);
  5457. if (SecureAlterContext != 0)
  5458. {
  5459. ASSERT(SecurityCredentials != 0);
  5460. AuthPadLength = Pad4(AlterContextRespLength);
  5461. AlterContextRespLength += AuthPadLength +
  5462. SecurityCredentials->MaximumTokenLength() +
  5463. sizeof(sec_trailer);
  5464. }
  5465. Status = TransGetBuffer((void **) &AlterContextResp,
  5466. AlterContextRespLength);
  5467. if ( Status != RPC_S_OK )
  5468. {
  5469. ASSERT( Status == RPC_S_OUT_OF_MEMORY );
  5470. if (SecurityCredentials != 0)
  5471. {
  5472. SecurityCredentials->DereferenceCredentials();
  5473. }
  5474. SendFault(RPC_S_OUT_OF_MEMORY, 1, CallId);
  5475. TransFreeBuffer(AlterContext);
  5476. return(1);
  5477. }
  5478. AlterContextLength -= sizeof(rpcconn_alter_context);
  5479. if ( ProcessPContextList(Address, PContextList, &AlterContextLength,
  5480. (p_result_list_t *) (AlterContextResp + 1)) != 0 )
  5481. {
  5482. TransFreeBuffer(AlterContext);
  5483. TransFreeBuffer(AlterContextResp);
  5484. if (SecurityCredentials != 0)
  5485. {
  5486. SecurityCredentials->DereferenceCredentials();
  5487. }
  5488. SendFault(RPC_S_PROTOCOL_ERROR, 1, CallId);
  5489. return(1);
  5490. }
  5491. if ( SecureAlterContext != 0 )
  5492. {
  5493. ASSERT(SecurityCredentials != 0);
  5494. NewSecurityTrailer = (sec_trailer *)
  5495. (((unsigned char *) AlterContextResp) +
  5496. AlterContextRespLength -
  5497. SecurityCredentials->MaximumTokenLength() -
  5498. sizeof(sec_trailer));
  5499. InitSecurityInfo.DceSecurityInfo = DceSecurityInfo;
  5500. InitSecurityInfo.PacketType = AlterContext->common.PTYPE;
  5501. InputBufferDescriptor.ulVersion = 0;
  5502. InputBufferDescriptor.cBuffers = 4;
  5503. InputBufferDescriptor.pBuffers = InputBuffers;
  5504. InputBuffers[0].cbBuffer = sizeof(rpcconn_alter_context);
  5505. InputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5506. InputBuffers[0].pvBuffer = SavedHeader;
  5507. InputBuffers[1].cbBuffer = AlterContext->common.frag_length -
  5508. sizeof(rpcconn_alter_context) -
  5509. AlterContext->common.auth_length;
  5510. InputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5511. InputBuffers[1].pvBuffer = (char *) SavedHeader +
  5512. sizeof(rpcconn_alter_context);
  5513. InputBuffers[2].cbBuffer = AlterContext->common.auth_length;
  5514. InputBuffers[2].BufferType = SECBUFFER_TOKEN;
  5515. InputBuffers[2].pvBuffer = SecurityTrailer + 1;
  5516. InputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  5517. InputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  5518. InputBuffers[3].pvBuffer = &InitSecurityInfo;
  5519. OutputBufferDescriptor.ulVersion = 0;
  5520. OutputBufferDescriptor.cBuffers = 4;
  5521. OutputBufferDescriptor.pBuffers = OutputBuffers;
  5522. OutputBuffers[0].cbBuffer = sizeof(rpcconn_alter_context_resp);
  5523. OutputBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5524. OutputBuffers[0].pvBuffer = AlterContextResp;
  5525. OutputBuffers[1].cbBuffer = AlterContextRespLength
  5526. - SecurityCredentials->MaximumTokenLength()
  5527. - sizeof(rpcconn_alter_context_resp);
  5528. OutputBuffers[1].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5529. OutputBuffers[1].pvBuffer = ((unsigned char *) AlterContextResp)
  5530. + sizeof(rpcconn_alter_context_resp);
  5531. OutputBuffers[2].cbBuffer = SecurityCredentials->MaximumTokenLength();
  5532. OutputBuffers[2].BufferType = SECBUFFER_TOKEN;
  5533. OutputBuffers[2].pvBuffer = NewSecurityTrailer + 1;
  5534. OutputBuffers[3].cbBuffer = sizeof(DCE_INIT_SECURITY_INFO);
  5535. OutputBuffers[3].BufferType = SECBUFFER_PKG_PARAMS | SECBUFFER_READONLY;
  5536. OutputBuffers[3].pvBuffer = &InitSecurityInfo;
  5537. if ( NewContextRequired != 0 )
  5538. {
  5539. Status = CurrentSecurityContext->AcceptFirstTime(
  5540. SecurityCredentials,
  5541. &InputBufferDescriptor,
  5542. &OutputBufferDescriptor,
  5543. SecurityTrailer->auth_level,
  5544. *((unsigned long *) AlterContext->common.drep),
  5545. NewContextRequired
  5546. );
  5547. LogEvent(SU_SCONN, EV_SEC_ACCEPT1, this, LongToPtr(Status), OutputBuffers[2].cbBuffer);
  5548. //
  5549. // Since we have (potentially) a new security context we
  5550. // need to figure out
  5551. // additional security related information at this stage..
  5552. //
  5553. switch (SecurityTrailer->auth_level)
  5554. {
  5555. case RPC_C_AUTHN_LEVEL_CONNECT:
  5556. case RPC_C_AUTHN_LEVEL_CALL: //OSF Hack..
  5557. case RPC_C_AUTHN_LEVEL_PKT:
  5558. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  5559. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5560. CurrentSecurityContext->MaximumSignatureLength() +
  5561. sizeof (sec_trailer);
  5562. break;
  5563. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  5564. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5565. CurrentSecurityContext->MaximumHeaderLength() +
  5566. sizeof (sec_trailer);
  5567. break;
  5568. default:
  5569. ASSERT(!"Unknown Security Level\n");
  5570. }
  5571. }
  5572. else
  5573. {
  5574. Status = CurrentSecurityContext->AcceptThirdLeg(
  5575. *((unsigned long *) AlterContext->common.drep),
  5576. &InputBufferDescriptor,
  5577. &OutputBufferDescriptor
  5578. );
  5579. LogEvent(SU_SCONN, EV_SEC_ACCEPT3, this, LongToPtr(Status), OutputBuffers[2].cbBuffer);
  5580. }
  5581. TokenLength = (unsigned int) OutputBuffers[2].cbBuffer;
  5582. if ( Status == RPC_S_OK ||
  5583. Status == RPC_P_COMPLETE_NEEDED ||
  5584. Status == RPC_P_CONTINUE_NEEDED ||
  5585. Status == RPC_P_COMPLETE_AND_CONTINUE )
  5586. {
  5587. if ( Status == RPC_P_COMPLETE_NEEDED ||
  5588. Status == RPC_P_COMPLETE_AND_CONTINUE )
  5589. {
  5590. CompleteNeeded = 1;
  5591. }
  5592. if ( Status == RPC_S_OK ||
  5593. Status == RPC_P_COMPLETE_NEEDED )
  5594. {
  5595. switch (SecurityTrailer->auth_level)
  5596. {
  5597. case RPC_C_AUTHN_LEVEL_CONNECT:
  5598. case RPC_C_AUTHN_LEVEL_CALL: //OSF Hack..
  5599. case RPC_C_AUTHN_LEVEL_PKT:
  5600. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  5601. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5602. CurrentSecurityContext->MaximumSignatureLength() +
  5603. sizeof (sec_trailer);
  5604. break;
  5605. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  5606. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5607. CurrentSecurityContext->MaximumHeaderLength() +
  5608. sizeof (sec_trailer);
  5609. break;
  5610. default:
  5611. ASSERT(!"Unknown Security Level\n");
  5612. }
  5613. }
  5614. AlterContextRespLength = AlterContextRespLength +
  5615. TokenLength -
  5616. SecurityCredentials->MaximumTokenLength();
  5617. NewSecurityTrailer->auth_type = SecurityTrailer->auth_type;
  5618. NewSecurityTrailer->auth_level = SecurityTrailer->auth_level;
  5619. NewSecurityTrailer->auth_pad_length = (unsigned char) AuthPadLength;
  5620. NewSecurityTrailer->auth_reserved = 0;
  5621. NewSecurityTrailer->auth_context_id = AuthContextId;
  5622. SecurityCredentials->DereferenceCredentials();
  5623. SecurityCredentials = 0;
  5624. Status = RPC_S_OK;
  5625. }
  5626. if (Status)
  5627. {
  5628. TransFreeBuffer(AlterContext);
  5629. TransFreeBuffer(AlterContextResp);
  5630. SecurityCredentials->DereferenceCredentials();
  5631. SendFault(RPC_S_ACCESS_DENIED, 1, CallId);
  5632. return(1);
  5633. }
  5634. }
  5635. DceSecurityInfo.ReceiveSequenceNumber++;
  5636. ConstructPacket((rpcconn_common *) AlterContextResp,
  5637. rpc_alter_context_resp, AlterContextRespLength);
  5638. TransFreeBuffer(AlterContext);
  5639. if ( Association == 0 )
  5640. {
  5641. TransFreeBuffer(AlterContextResp);
  5642. SendFault(RPC_S_PROTOCOL_ERROR, 1, CallId);
  5643. return(1);
  5644. }
  5645. AlterContextResp->assoc_group_id = Association->AssocGroupId();
  5646. AlterContextResp->sec_addr_length = 0;
  5647. AlterContextResp->max_xmit_frag = AlterContextResp->max_recv_frag = MaxFrag;
  5648. AlterContextResp->common.call_id = CallId;
  5649. AlterContextResp->common.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
  5650. AlterContextResp->common.auth_length = (unsigned short) TokenLength;
  5651. if (CompleteNeeded != 0)
  5652. {
  5653. CurrentSecurityContext->CompleteSecurityToken(&OutputBufferDescriptor);
  5654. }
  5655. Status= TransSend(AlterContextResp, AlterContextRespLength);
  5656. TransFreeBuffer(AlterContextResp);
  5657. if ( Status != RPC_S_OK )
  5658. {
  5659. return(1);
  5660. }
  5661. return(0);
  5662. }
  5663. RPC_STATUS
  5664. OSF_SCONNECTION::EatAuthInfoFromPacket (
  5665. IN rpcconn_request * Request,
  5666. IN OUT int * RequestLength,
  5667. IN OUT void * *SavedHeader,
  5668. IN OUT unsigned long *SavedHeaderSize
  5669. )
  5670. /*++
  5671. Routine Description:
  5672. If there is authentication information in the packet, this routine
  5673. will check it, and perform security as necessary. This may include
  5674. calls to the security support package.
  5675. Arguments:
  5676. Request - Supplies the packet which may contain authentication
  5677. information.
  5678. RequestLength - Supplies the length of the packet in bytes, and
  5679. returns the length of the packet without authentication
  5680. information.
  5681. Return Value:
  5682. RPC_S_OK - Everything went just fine.
  5683. RPC_S_ACCESS_DENIED - A security failure of some sort occured.
  5684. RPC_S_PROTOCOL_ERROR - This will occur if no authentication information
  5685. is in the packet, and some was expected, or visa versa.
  5686. --*/
  5687. {
  5688. sec_trailer * SecurityTrailer;
  5689. RPC_STATUS Status;
  5690. SECURITY_BUFFER_DESCRIPTOR BufferDescriptor;
  5691. SECURITY_BUFFER SecurityBuffers[5];
  5692. DCE_MSG_SECURITY_INFO MsgSecurityInfo;
  5693. unsigned long Id, Level, Service;
  5694. SECURITY_CONTEXT * SecId;
  5695. unsigned int HeaderSize = sizeof(rpcconn_request);
  5696. unsigned long DataRep = * (unsigned long *) Request->common.drep;
  5697. #if DBG
  5698. // Check to make sure SavedHeader is OSF_SCALL->SavedHeader.
  5699. // We may need to get to the call object below.
  5700. OSF_SCALL *pSCall = (OSF_SCALL *) ((char *)SavedHeader - FIELD_OFFSET(OSF_SCALL, SavedHeader));
  5701. ASSERT(pSCall->InvalidHandle(OSF_SCALL_TYPE) == 0);
  5702. #endif
  5703. if ( (Request->common.pfc_flags & PFC_OBJECT_UUID) != 0 )
  5704. {
  5705. HeaderSize += sizeof(UUID);
  5706. }
  5707. if ( Request->common.auth_length != 0 )
  5708. {
  5709. SecurityTrailer = (sec_trailer *) (((unsigned char *)
  5710. Request) + Request->common.frag_length
  5711. - Request->common.auth_length - sizeof(sec_trailer));
  5712. if (RpcSecurityBeingUsed == 0)
  5713. {
  5714. return(RPC_S_PROTOCOL_ERROR);
  5715. }
  5716. //
  5717. // Find the appropriate security context..
  5718. //
  5719. Id = SecurityTrailer->auth_context_id;
  5720. Level = SecurityTrailer->auth_level;
  5721. Service = SecurityTrailer->auth_type;
  5722. if (DataConvertEndian(((unsigned char *)&DataRep)) != 0)
  5723. {
  5724. Id = RpcpByteSwapLong(Id);
  5725. }
  5726. //
  5727. // Osf Hack
  5728. //
  5729. if (Level == RPC_C_AUTHN_LEVEL_CALL)
  5730. {
  5731. Level = RPC_C_AUTHN_LEVEL_PKT;
  5732. }
  5733. if ( (CurrentSecurityContext == 0)
  5734. ||(CurrentSecurityContext->AuthContextId != Id)
  5735. ||(CurrentSecurityContext->AuthenticationLevel != Level)
  5736. ||(CurrentSecurityContext->AuthenticationService != Service) )
  5737. {
  5738. SecId = FindSecurityContext(Id, Level, Service);
  5739. if (SecId == 0)
  5740. {
  5741. return (RPC_S_PROTOCOL_ERROR);
  5742. }
  5743. CurrentSecurityContext = SecId;
  5744. AuthInfo.AuthenticationLevel = Level;
  5745. AuthInfo.AuthenticationService = Service;
  5746. AuthContextId = Id;
  5747. switch (Level)
  5748. {
  5749. case RPC_C_AUTHN_LEVEL_CONNECT:
  5750. case RPC_C_AUTHN_LEVEL_CALL: //OSF Hack..
  5751. case RPC_C_AUTHN_LEVEL_PKT:
  5752. case RPC_C_AUTHN_LEVEL_PKT_INTEGRITY:
  5753. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5754. CurrentSecurityContext->MaximumSignatureLength() +
  5755. sizeof (sec_trailer);
  5756. break;
  5757. case RPC_C_AUTHN_LEVEL_PKT_PRIVACY:
  5758. AdditionalSpaceForSecurity = MAXIMUM_SECURITY_BLOCK_SIZE +
  5759. CurrentSecurityContext->MaximumHeaderLength() +
  5760. sizeof (sec_trailer);
  5761. break;
  5762. default:
  5763. ASSERT(!"Unknown Security Level\n");
  5764. }
  5765. }
  5766. *RequestLength -= (Request->common.auth_length
  5767. +HeaderSize + sizeof(sec_trailer) +
  5768. SecurityTrailer->auth_pad_length);
  5769. MsgSecurityInfo.SendSequenceNumber =
  5770. DceSecurityInfo.SendSequenceNumber;
  5771. MsgSecurityInfo.ReceiveSequenceNumber =
  5772. DceSecurityInfo.ReceiveSequenceNumber;
  5773. MsgSecurityInfo.PacketType = Request->common.PTYPE;
  5774. BufferDescriptor.ulVersion = 0;
  5775. BufferDescriptor.cBuffers = 5;
  5776. BufferDescriptor.pBuffers = SecurityBuffers;
  5777. SecurityBuffers[0].cbBuffer = HeaderSize;
  5778. SecurityBuffers[0].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5779. SecurityBuffers[0].pvBuffer = (unsigned char *) *SavedHeader;
  5780. SecurityBuffers[1].cbBuffer = *RequestLength + SecurityTrailer->auth_pad_length;
  5781. SecurityBuffers[1].BufferType = SECBUFFER_DATA;
  5782. SecurityBuffers[1].pvBuffer = ((unsigned char *) Request)
  5783. + HeaderSize;
  5784. SecurityBuffers[2].cbBuffer = sizeof(sec_trailer);
  5785. SecurityBuffers[2].BufferType = SECBUFFER_DATA | SECBUFFER_READONLY;
  5786. SecurityBuffers[2].pvBuffer = SecurityTrailer;
  5787. SecurityBuffers[3].cbBuffer = Request->common.auth_length;
  5788. SecurityBuffers[3].BufferType = SECBUFFER_TOKEN;
  5789. SecurityBuffers[3].pvBuffer = SecurityTrailer + 1;
  5790. SecurityBuffers[4].cbBuffer = sizeof(DCE_MSG_SECURITY_INFO);
  5791. SecurityBuffers[4].BufferType = SECBUFFER_PKG_PARAMS
  5792. | SECBUFFER_READONLY;
  5793. SecurityBuffers[4].pvBuffer = &MsgSecurityInfo;
  5794. Status = CurrentSecurityContext->VerifyOrUnseal(
  5795. MsgSecurityInfo.ReceiveSequenceNumber,
  5796. AuthInfo.AuthenticationLevel != RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  5797. &BufferDescriptor);
  5798. if ( Status != RPC_S_OK )
  5799. {
  5800. ASSERT( Status == RPC_S_ACCESS_DENIED ||
  5801. Status == ERROR_SHUTDOWN_IN_PROGRESS ||
  5802. Status == ERROR_PASSWORD_MUST_CHANGE ||
  5803. Status == ERROR_PASSWORD_EXPIRED ||
  5804. Status == ERROR_ACCOUNT_DISABLED ||
  5805. Status == ERROR_INVALID_LOGON_HOURS);
  5806. return(Status);
  5807. }
  5808. }
  5809. else if (CurrentSecurityContext == 0)
  5810. {
  5811. // This is a non-secure connection. There is nothing to be done.
  5812. ASSERT(AuthInfo.AuthenticationLevel == RPC_C_AUTHN_LEVEL_NONE);
  5813. ASSERT(*SavedHeader == 0);
  5814. *RequestLength -= HeaderSize;
  5815. }
  5816. else
  5817. {
  5818. //
  5819. // We are doing a nonsecure rpc and previously we did a secure rpc.
  5820. //
  5821. // This switch from a secure to a non-secure connection is only
  5822. // allowed to take place in between calls. A given call has to
  5823. // be either entirely secure or entirely non-secure.
  5824. //
  5825. // If this is the first buffer, then we are allowed to switch.
  5826. // We determine whether this is the first buffer by the flag and the
  5827. // current state of the call object. We can get to the call object because
  5828. // this funciton is called with SavedHeader from OSF_SCALL::SavedHeader.
  5829. // We do not explicitly pass in a call address for perf reasons.
  5830. //
  5831. OSF_SCALL *pSCall = (OSF_SCALL *) ((char *)SavedHeader - FIELD_OFFSET(OSF_SCALL, SavedHeader));
  5832. if (Request->common.pfc_flags & PFC_FIRST_FRAG &&
  5833. pSCall->RcvBufferLength == 0)
  5834. {
  5835. ASSERT(pSCall->CurrentState == NewRequest);
  5836. // After we reset the auth level and zero-out the security
  5837. // context the call will not be able to get past security callbacks.
  5838. AuthInfo.AuthenticationLevel = RPC_C_AUTHN_LEVEL_NONE;
  5839. CurrentSecurityContext = 0;
  5840. if (*SavedHeader != 0)
  5841. {
  5842. ASSERT(*SavedHeaderSize != 0);
  5843. RpcpFarFree(*SavedHeader);
  5844. *SavedHeader = 0;
  5845. *SavedHeaderSize = 0;
  5846. }
  5847. *RequestLength -= HeaderSize;
  5848. }
  5849. // Attempt to switch from a secure to a non-secure RPC within a call - fail.
  5850. else
  5851. {
  5852. ASSERT(0 && "Switch from secure to non-secure RPC in the middle of a call.");
  5853. return RPC_S_ACCESS_DENIED;
  5854. }
  5855. }
  5856. DceSecurityInfo.ReceiveSequenceNumber += 1;
  5857. if (*RequestLength < 0)
  5858. {
  5859. return RPC_S_ACCESS_DENIED;
  5860. }
  5861. return(RPC_S_OK);
  5862. }
  5863. BOOL
  5864. OSF_SCONNECTION::MaybeQueueThisCall (
  5865. IN OSF_SCALL *ThisCall
  5866. )
  5867. {
  5868. BOOL fCallQueued = 0;
  5869. ConnMutex.Request();
  5870. if (fCurrentlyDispatched)
  5871. {
  5872. if (CallQueue.PutOnQueue(ThisCall, 0))
  5873. {
  5874. ThisCall->SendFault(RPC_S_OUT_OF_MEMORY, 1);
  5875. //
  5876. // Remove the reply reference
  5877. //
  5878. ThisCall->RemoveReference(); // CALL--
  5879. //
  5880. // Remove the dispatch reference();
  5881. //
  5882. ThisCall->RemoveReference(); // CALL--
  5883. }
  5884. fCallQueued = 1;
  5885. }
  5886. else
  5887. {
  5888. fCurrentlyDispatched = 1;
  5889. }
  5890. ConnMutex.Clear();
  5891. return fCallQueued;
  5892. }
  5893. void
  5894. OSF_SCONNECTION::AbortQueuedCalls (
  5895. )
  5896. {
  5897. OSF_SCALL *NextCall;
  5898. unsigned int ignore;
  5899. while (1)
  5900. {
  5901. ConnMutex.Request();
  5902. NextCall = (OSF_SCALL *) CallQueue.TakeOffQueue(&ignore);
  5903. if (NextCall == 0)
  5904. {
  5905. fCurrentlyDispatched = 0;
  5906. ConnMutex.Clear();
  5907. break;
  5908. }
  5909. ConnMutex.Clear();
  5910. //
  5911. // Remove the reply reference
  5912. //
  5913. NextCall->RemoveReference(); // CALL--
  5914. //
  5915. // Remove the dispatch reference on the call
  5916. //
  5917. NextCall->RemoveReference(); // CALL--
  5918. }
  5919. }
  5920. void
  5921. OSF_SCONNECTION::DispatchQueuedCalls (
  5922. )
  5923. {
  5924. OSF_SCALL *NextCall;
  5925. unsigned int ignore;
  5926. while (1)
  5927. {
  5928. ConnMutex.Request();
  5929. NextCall = (OSF_SCALL *) CallQueue.TakeOffQueue(&ignore);
  5930. if (NextCall == 0)
  5931. {
  5932. fCurrentlyDispatched = 0;
  5933. ConnMutex.Clear();
  5934. break;
  5935. }
  5936. ConnMutex.Clear();
  5937. NextCall->DispatchHelper();
  5938. //
  5939. // Remove the dispatch reference on the call
  5940. //
  5941. NextCall->RemoveReference(); // CALL--
  5942. }
  5943. }
  5944. OSF_ASSOCIATION::OSF_ASSOCIATION (
  5945. IN OSF_ADDRESS *TheAddress,
  5946. IN RPC_CLIENT_PROCESS_IDENTIFIER * ClientProcess,
  5947. OUT RPC_STATUS * Status
  5948. )
  5949. {
  5950. ObjectType = OSF_ASSOCIATION_TYPE;
  5951. *Status = RPC_S_OK;
  5952. ConnectionCount = 1;
  5953. Address = TheAddress;
  5954. this->ClientProcess.Set(ClientProcess);
  5955. AssociationGroupId = InterlockedExchangeAdd(&GroupIdCounter, 1);
  5956. AssociationDictKey = Address->AddAssociation(this);
  5957. if (AssociationDictKey == -1)
  5958. {
  5959. *Status = RPC_S_OUT_OF_MEMORY;
  5960. }
  5961. }
  5962. OSF_ASSOCIATION::~OSF_ASSOCIATION (
  5963. )
  5964. {
  5965. if (AssociationDictKey != -1)
  5966. {
  5967. int HashBucketNumber;
  5968. HashBucketNumber = Address->GetHashBucketForAssociation(AssocGroupId());
  5969. // lock the bucket
  5970. Address->GetAssociationBucketMutex(HashBucketNumber)->Request();
  5971. Address->RemoveAssociation(AssociationDictKey, this);
  5972. // unlock the bucket
  5973. Address->GetAssociationBucketMutex(HashBucketNumber)->Clear();
  5974. }
  5975. }
  5976. BOOL
  5977. OSF_ASSOCIATION::RemoveConnectionUnsafe (
  5978. void
  5979. )
  5980. {
  5981. int HashBucketNumber;
  5982. // get the hashed bucket
  5983. HashBucketNumber = Address->GetHashBucketForAssociation(AssociationGroupId);
  5984. // verify the bucket is locked
  5985. Address->GetAssociationBucketMutex(HashBucketNumber)->VerifyOwned();
  5986. ConnectionCount --;
  5987. if (ConnectionCount == 0)
  5988. {
  5989. Address->RemoveAssociation(AssociationDictKey, this);
  5990. AssociationDictKey = -1;
  5991. return AssociationDictKey; // AssociationDictKey is a quick non-zero value
  5992. }
  5993. else
  5994. return FALSE;
  5995. }
  5996. void
  5997. OSF_ASSOCIATION::RemoveConnection (
  5998. )
  5999. {
  6000. int HashBucketNumber;
  6001. BOOL Res;
  6002. // get the hashed bucket
  6003. HashBucketNumber = Address->GetHashBucketForAssociation(AssociationGroupId);
  6004. // lock the bucket
  6005. Address->GetAssociationBucketMutex(HashBucketNumber)->Request();
  6006. Res = RemoveConnectionUnsafe();
  6007. // unlock the bucket
  6008. Address->GetAssociationBucketMutex(HashBucketNumber)->Clear();
  6009. if (Res)
  6010. delete this;
  6011. }
  6012. RPC_STATUS OSF_ASSOCIATION::CreateThread(void)
  6013. {
  6014. return Address->CreateThread();
  6015. }
  6016. RPC_ADDRESS *
  6017. OsfCreateRpcAddress (
  6018. IN TRANS_INFO *TransportInfo
  6019. )
  6020. /*++
  6021. Routine Description:
  6022. This routine will be called to create an object representing an
  6023. rpc address. That is all it has got to do.
  6024. Arguments:
  6025. A new rpc address will be returned, unless insufficient memory is
  6026. available to create the new rpc address, in which case zero will
  6027. be returned.
  6028. --*/
  6029. {
  6030. RPC_ADDRESS * RpcAddress;
  6031. RPC_STATUS Status = RPC_S_OK;
  6032. RPC_CONNECTION_TRANSPORT *ServerInfo =
  6033. (RPC_CONNECTION_TRANSPORT *) TransportInfo->InqTransInfo();
  6034. RpcAddress = new (ServerInfo->AddressSize)
  6035. OSF_ADDRESS(TransportInfo, &Status);
  6036. if ( Status != RPC_S_OK )
  6037. {
  6038. return(0);
  6039. }
  6040. return(RpcAddress);
  6041. }
  6042. RPC_STATUS
  6043. OSF_SCALL::Cancel(
  6044. void * ThreadHandle
  6045. )
  6046. {
  6047. InterlockedIncrement(&CancelPending);
  6048. return RPC_S_OK;
  6049. }
  6050. unsigned
  6051. OSF_SCALL::TestCancel(
  6052. )
  6053. {
  6054. return InterlockedExchange(&CancelPending, 0);
  6055. }
  6056. RPC_STATUS
  6057. OSF_SCALL::ToStringBinding (
  6058. OUT RPC_CHAR * * StringBinding
  6059. )
  6060. /*++
  6061. Routine Description:
  6062. We need to convert this connection into a string binding. We
  6063. will ask the address for a binding handle which we can then
  6064. convert into a string binding.
  6065. Arguments:
  6066. StringBinding - Returns the string representation of the binding
  6067. handle.
  6068. Return Value:
  6069. RPC_S_OK - The operation completed successfully.
  6070. RPC_S_OUT_OF_MEMORY - We do not have enough memory available to
  6071. allocate space for the string binding.
  6072. --*/
  6073. {
  6074. BINDING_HANDLE * BindingHandle;
  6075. RPC_STATUS Status = RPC_S_OK;
  6076. BindingHandle = Address->InquireBinding();
  6077. if (BindingHandle == 0)
  6078. return(RPC_S_OUT_OF_MEMORY);
  6079. if ( ObjectUuidSpecified != 0)
  6080. {
  6081. Status = RpcBindingSetObject(BindingHandle, (UUID *) &ObjectUuid);
  6082. }
  6083. if (Status == RPC_S_OK)
  6084. {
  6085. Status = BindingHandle->ToStringBinding(StringBinding);
  6086. }
  6087. BindingHandle->BindingFree();
  6088. return(Status);
  6089. }
  6090. #if DBG
  6091. void
  6092. OSF_SCALL::InterfaceForCallDoesNotUseStrict (
  6093. void
  6094. )
  6095. {
  6096. CurrentBinding->InterfaceForCallDoesNotUseStrict();
  6097. }
  6098. #endif
  6099. RPC_STATUS
  6100. OSF_SCALL::InqLocalConnAddress (
  6101. IN OUT void *Buffer,
  6102. IN OUT unsigned long *BufferSize,
  6103. OUT unsigned long *AddressFormat
  6104. )
  6105. /*++
  6106. Routine Description:
  6107. This routine is used by a server application to inquire about the local
  6108. address on which a call is made.
  6109. Arguments:
  6110. Buffer - The buffer that will receive the output address
  6111. BufferSize - the size of the supplied Buffer on input. On output the
  6112. number of bytes written to the buffer. If the buffer is too small
  6113. to receive all the output data, ERROR_MORE_DATA is returned,
  6114. nothing is written to the buffer, and BufferSize is set to
  6115. the size of the buffer needed to return all the data.
  6116. AddressFormat - a constant indicating the format of the returned address.
  6117. Currently supported are RPC_P_ADDR_FORMAT_TCP_IPV4 and
  6118. RPC_P_ADDR_FORMAT_TCP_IPV6.
  6119. Return Values:
  6120. RPC_S_OK - success.
  6121. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete this
  6122. operation.
  6123. RPC_S_INVALID_BINDING - The supplied client binding is invalid.
  6124. RPC_S_CANNOT_SUPPORT - The local address was inquired for a protocol
  6125. sequence that doesn't support this type of functionality. Currently
  6126. only ncacn_ip_tcp supports it.
  6127. RPC_S_* or Win32 error for other errors
  6128. --*/
  6129. {
  6130. return Connection->InqLocalConnAddress(
  6131. Buffer,
  6132. BufferSize,
  6133. AddressFormat);
  6134. }
  6135. void
  6136. OSF_SCALL::WakeUpPipeThreadIfNecessary (
  6137. IN RPC_STATUS Status
  6138. )
  6139. /*++
  6140. Routine Description:
  6141. If a pipe thread is being stuck on wait, it fires the event to wake
  6142. it up.
  6143. Arguments:
  6144. Status - the status with which the call failed.
  6145. Return Values:
  6146. --*/
  6147. {
  6148. if (pAsync == 0)
  6149. {
  6150. if (fPipeCall)
  6151. {
  6152. CallMutex.Request();
  6153. CurrentState = CallAborted;
  6154. AsyncStatus = Status;
  6155. // wake up the thread that was flow controlled, if any
  6156. fChoked = 0;
  6157. CallMutex.Clear();
  6158. LogEvent(SU_SCALL, EV_STATUS, this, SyncEvent.EventHandle, 0, 1, 0);
  6159. SyncEvent.Raise();
  6160. }
  6161. }
  6162. }
  6163. RPC_STATUS RPC_ENTRY
  6164. I_RpcTransServerReallocPacket (
  6165. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  6166. IN OUT void * * Buffer,
  6167. IN unsigned int OldBufferLength,
  6168. IN unsigned int NewBufferLength
  6169. )
  6170. /*++
  6171. Routine Description:
  6172. The server side transport interface modules will use this routine to
  6173. increase the size of a buffer so that the entire packet to be
  6174. received will fit into it, or to allocate a new buffer. If the buffer
  6175. is to be reallocated, the data from the old buffer is copied
  6176. into the beginning of the new buffer. The old buffer will be freed.
  6177. Arguments:
  6178. ThisConnection - Supplies the connection for which we are reallocating
  6179. a transport buffer.
  6180. Buffer - Supplies the buffer which we want to reallocate to
  6181. be larger. If no buffer is supplied, then a new one is allocated
  6182. anyway. The new buffer is returned via this argument.
  6183. OldBufferLength - Supplies the current length of the buffer in bytes.
  6184. This information is necessary so we know how much of the buffer
  6185. needs to be copied into the new buffer.
  6186. NewBufferLength - Supplies the required length of the buffer in bytes.
  6187. Return Value:
  6188. RPC_S_OK - The requested larger buffer has successfully been allocated.
  6189. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate
  6190. the buffer.
  6191. --*/
  6192. {
  6193. ASSERT(0);
  6194. return(RPC_S_INTERNAL_ERROR);
  6195. }
  6196. BUFFER RPC_ENTRY
  6197. I_RpcTransServerAllocatePacket (
  6198. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  6199. IN UINT Size
  6200. )
  6201. /*++
  6202. Routine Description:
  6203. The server side transport interface modules will use this routine to
  6204. increase the size of a buffer so that the entire packet to be
  6205. received will fit into it, or to allocate a new buffer. If the buffer
  6206. is to be reallocated, the data from the old buffer is copied
  6207. into the beginning of the new buffer. The old buffer will be freed.
  6208. Arguments:
  6209. ThisConnection - Supplies the connection for which we are reallocating
  6210. a transport buffer.
  6211. Buffer - Supplies the buffer which we want to reallocate to
  6212. be larger. If no buffer is supplied, then a new one is allocated
  6213. anyway. The new buffer is returned via this argument.
  6214. OldBufferLength - Supplies the current length of the buffer in bytes.
  6215. This information is necessary so we know how much of the buffer
  6216. needs to be copied into the new buffer.
  6217. NewBufferLength - Supplies the required length of the buffer in bytes.
  6218. Return Value:
  6219. RPC_S_OK - The requested larger buffer has successfully been allocated.
  6220. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allocate
  6221. the buffer.
  6222. --*/
  6223. {
  6224. ASSERT(0);
  6225. return(0);
  6226. }
  6227. unsigned short RPC_ENTRY
  6228. I_RpcTransServerMaxFrag (
  6229. IN RPC_TRANSPORT_CONNECTION ThisConnection
  6230. )
  6231. /*++
  6232. Routine Description:
  6233. The server side transport interface modules will use this routine to
  6234. determine the negotiated maximum fragment size.
  6235. Arguments:
  6236. ThisConnection - Supplies the connection for which we are returning
  6237. the maximum fragment size.
  6238. --*/
  6239. {
  6240. ASSERT(0);
  6241. return(0);
  6242. }
  6243. RPC_TRANSPORT_CONNECTION RPC_ENTRY
  6244. I_RpcTransServerNewConnection (
  6245. IN RPC_TRANSPORT_ADDRESS ThisAddress
  6246. )
  6247. {
  6248. OSF_SCONNECTION * SConnection;
  6249. OSF_ADDRESS *Address ;
  6250. Address = InqTransAddress(ThisAddress) ;
  6251. SConnection = Address->NewConnection();
  6252. if ( SConnection == 0 )
  6253. {
  6254. return(0);
  6255. }
  6256. return(SConnection->TransConnection);
  6257. }
  6258. void RPC_ENTRY
  6259. I_RpcTransServerFreePacket (
  6260. IN RPC_TRANSPORT_CONNECTION ThisConnection,
  6261. IN void * Buffer
  6262. )
  6263. /*++
  6264. Routine Description:
  6265. We need to free a transport buffer for a transport connection; this
  6266. will typically occur when the connection is being closed.
  6267. Arguments:
  6268. ThisConnection - Supplies the transport connection which owns the
  6269. buffer.
  6270. Buffer - Supplies the buffer to be freed.
  6271. --*/
  6272. {
  6273. ASSERT(0);
  6274. }
  6275. void * RPC_ENTRY
  6276. I_RpcTransProtectThread (
  6277. void
  6278. )
  6279. /*++
  6280. Routine Description:
  6281. In some cases, if an asyncronous io operation has been started by a
  6282. thread, the thread can not be deleted because the io operation will
  6283. be cancelled. This routine will be called by a transport to indicate
  6284. that the current thread can not be deleted.
  6285. Return Value:
  6286. A pointer to the thread will be returned. This is necessary, so that
  6287. later the thread can be unprotected.
  6288. --*/
  6289. {
  6290. #ifdef RPC_OLD_IO_PROTECTION
  6291. THREAD * Thread = RpcpGetThreadPointer();
  6292. Thread->ProtectThread();
  6293. return((void *) Thread);
  6294. #endif
  6295. return 0;
  6296. }
  6297. void RPC_ENTRY
  6298. I_RpcTransUnprotectThread (
  6299. IN void * Thread
  6300. )
  6301. /*++
  6302. Routine Description:
  6303. When a thread no longer needs to be protected from deletion, this
  6304. routine must be called.
  6305. Arguments:
  6306. Thread - Supplies the thread which no longer needs to be protected
  6307. from deletion.
  6308. --*/
  6309. {
  6310. #ifdef RPC_OLD_IO_PROTECTION
  6311. ((THREAD *) Thread)->UnprotectThread();
  6312. #endif
  6313. }
  6314. void
  6315. I_RpcTransVerifyServerRuntimeCallFromContext(
  6316. void *SendContext
  6317. )
  6318. /*++
  6319. Routine Description:
  6320. Verifies that the supplied context follows a valid
  6321. runtime server call object.
  6322. Arguments:
  6323. SendContext - the context as seen by the transport
  6324. Return Value:
  6325. --*/
  6326. {
  6327. ASSERT(InqTransSCall(SendContext)->InvalidHandle(OSF_SCALL_TYPE) == 0);
  6328. }
  6329. const UUID BindNakEEInfoSignatureData = { /* 90740320-fad0-11d3-82d7-009027b130ab */
  6330. 0x90740320,
  6331. 0xfad0,
  6332. 0x11d3,
  6333. {0x82, 0xd7, 0x00, 0x90, 0x27, 0xb1, 0x30, 0xab}
  6334. };
  6335. const UUID *BindNakEEInfoSignature = &BindNakEEInfoSignatureData;