Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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