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.

963 lines
28 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. epclnt.cxx
  5. Abstract:
  6. This file contains the client runtime entry points into the
  7. endpoint mapper dll.
  8. Author:
  9. Michael Montague (mikemon) 06-Jan-1992
  10. Revision History:
  11. --*/
  12. #include <precomp.hxx>
  13. #include <epmp.h>
  14. #include <epmap.h>
  15. #include <twrproto.h>
  16. #include <CharConv.hxx>
  17. #include <OsfPcket.hxx>
  18. #include <BitSet.hxx>
  19. #include <ProtBind.hxx>
  20. #include <OsfClnt.hxx>
  21. #include <sidcache.hxx>
  22. extern RPC_STATUS __RPC_FAR
  23. MapFromNcaStatusCode (
  24. IN unsigned long NcaStatus
  25. );
  26. const static ProtseqEndpointPair EpMapperTable[] =
  27. {
  28. L"ncacn_np", L"\\pipe\\epmapper", NMP,
  29. L"ncalrpc", L"epmapper", LRPC,
  30. L"ncacn_ip_tcp", L"135", TCP,
  31. L"ncadg_ip_udp", L"135", UDP,
  32. #ifdef NETBIOS_ON
  33. L"ncacn_nb_nb", L"135", NBF,
  34. L"ncacn_nb_tcp", L"135", NBT,
  35. L"ncacn_nb_ipx", L"135", NBI,
  36. #endif
  37. #ifdef SPX_ON
  38. L"ncacn_spx", L"34280", SPX,
  39. #endif
  40. #ifdef IPX_ON
  41. L"ncadg_ipx", L"34280", IPX,
  42. #endif
  43. #ifdef APPLETALK_ON
  44. L"ncacn_at_dsp", L"Endpoint Mapper", DSP,
  45. #endif
  46. #ifdef NCADG_MQ_ON
  47. L"ncadg_mq", L"EpMapper", MSMQ,
  48. #endif
  49. L"ncacn_http", L"593", HTTP
  50. };
  51. const int LrpcEpMapperEntry = 1; // the entry in the table that contains LRPC
  52. unsigned long PartialRetries = 0;
  53. unsigned long ReallyTooBusy = 0;
  54. typedef struct _EP_LOOKUP_DATA
  55. {
  56. unsigned int NumberOfEndpoints;
  57. unsigned int MaximumEndpoints;
  58. unsigned int CurrentEndpoint;
  59. RPC_CHAR * PAPI * Endpoints;
  60. } EP_LOOKUP_DATA;
  61. RPC_STATUS RPC_ENTRY
  62. EpResolveEndpoint (
  63. IN UUID PAPI * ObjectUuid, OPTIONAL
  64. IN RPC_SYNTAX_IDENTIFIER PAPI * IfId,
  65. IN RPC_SYNTAX_IDENTIFIER PAPI * XferId,
  66. IN RPC_CHAR PAPI * RpcProtocolSequence,
  67. IN RPC_CHAR PAPI * NetworkAddress,
  68. IN RPC_CHAR PAPI * Options,
  69. IN OUT void PAPI * PAPI * EpLookupHandle,
  70. IN unsigned ConnTimeout,
  71. IN ULONG CallTimeout,
  72. IN CLIENT_AUTH_INFO *AuthInfo, OPTIONAL
  73. OUT RPC_CHAR * PAPI * Endpoint
  74. )
  75. /*++
  76. Routine Description:
  77. The runtime will call this routine to resolve an endpoint.
  78. Arguments:
  79. ObjectUuid - Optional specifies the object uuid in the binding
  80. for which we are trying to resolve an endpoint.
  81. Ifid - Pointer to the Syntax Identifier for the Interface
  82. Xferid - Pointer to the Syntax Identifier for the Transfer Syntax.
  83. RpcProtocolSequence - Supplies the rpc protocol sequence contained
  84. in the binding.
  85. NetworkAddress - Supplies the network address. This will be used
  86. to contact the endpoint mapper on that machine in order to
  87. resolve the endpoint.
  88. EpLookupHandle - Supplies the current version of the lookup handle
  89. for this iteration through the endpoint mapper. A new value
  90. for the lookup handle will be returned. If RPC_S_NO_ENDPOINT_FOUND
  91. is returned, this parameter will be set to its initial value,
  92. zero.
  93. ConnTimeout - the connection timeout
  94. CallTimeout - the call timeout
  95. AutInfo - any auth info that needs to be used during the resolution process
  96. Endpoint - Returns the endpoint resolved by the endpoint mapper on
  97. the machine specified by the network address argument. The
  98. storage for the endpoint must have been allocated using the
  99. runtime API I_RpcAllocate.
  100. Return Value:
  101. RPC_S_OK - The endpoint was successfully resolved.
  102. EP_S_NOT_REGISTERED - There are no more endpoints to be found
  103. for the specified combination of interface, network address,
  104. and lookup handle.
  105. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to allow
  106. resolution of the endpoint.
  107. EP_S_CANT_PERFORM_OP - The operation failed due to misc. error e.g.
  108. unable to bind to the EpMapper.
  109. --*/
  110. {
  111. RPC_BINDING_HANDLE MapperHandle = 0;
  112. RPC_STATUS RpcStatus;
  113. twr_p_t InputTower = 0;
  114. twr_p_t OutputTower[4];
  115. unsigned long Returned;
  116. error_status ErrorStatus;
  117. ept_lookup_handle_t ContextHandle = 0;
  118. EP_LOOKUP_DATA PAPI * EpLookupData = (EP_LOOKUP_DATA PAPI *)
  119. *EpLookupHandle;
  120. unsigned long RetryCount, i;
  121. unsigned char PAPI * EPoint;
  122. PSID SidToUse;
  123. int NormalizeRetryCount;
  124. BOOL SidFound;
  125. CHeapAnsi AnsiNWAddr, AnsiOptions;
  126. CStackAnsi AnsiProtseq;
  127. CNlUnicode nlEndpoint;
  128. // We have already taken all of the endpoints from the endpoint mapper;
  129. // now we just return them back to the runtime one at a time.
  130. ReturnEndpointFromList:
  131. ASSERT(*Endpoint == 0);
  132. if ( EpLookupData != 0 )
  133. {
  134. // When we reach the end of the list of endpoints, return an error,
  135. // and set things up so that we will start at the beginning again.
  136. if ( EpLookupData->CurrentEndpoint == EpLookupData->NumberOfEndpoints )
  137. {
  138. RpcpErrorAddRecord(EEInfoGCRuntime,
  139. EPT_S_NOT_REGISTERED,
  140. EEInfoDLEpResolveEndpoint10,
  141. RpcProtocolSequence,
  142. NetworkAddress,
  143. IfId->SyntaxGUID.Data1,
  144. (ULONG)((EpLookupData->CurrentEndpoint << 16) | EpLookupData->NumberOfEndpoints));
  145. EpLookupData->CurrentEndpoint = 0;
  146. return(EPT_S_NOT_REGISTERED);
  147. }
  148. *Endpoint = DuplicateString(
  149. EpLookupData->Endpoints[EpLookupData->CurrentEndpoint]);
  150. EpLookupData->CurrentEndpoint += 1;
  151. if ( *Endpoint == 0 )
  152. {
  153. return(RPC_S_OUT_OF_MEMORY);
  154. }
  155. return(RPC_S_OK);
  156. }
  157. // Otherwise, we need to take the list of endpoints from the endpoint
  158. // mapper.
  159. EpLookupData = (EP_LOOKUP_DATA PAPI *) RpcpFarAllocate(
  160. sizeof(EP_LOOKUP_DATA));
  161. if ( EpLookupData == 0 )
  162. {
  163. return(RPC_S_OUT_OF_MEMORY);
  164. }
  165. EpLookupData->MaximumEndpoints = 64;
  166. EpLookupData->Endpoints = (RPC_CHAR * PAPI *) RpcpFarAllocate(
  167. sizeof(RPC_CHAR PAPI *) * EpLookupData->MaximumEndpoints);
  168. if ( EpLookupData->Endpoints == 0 )
  169. {
  170. RpcStatus = RPC_S_OUT_OF_MEMORY;
  171. goto CleanupAndReturn;
  172. }
  173. EpLookupData->NumberOfEndpoints = 0;
  174. EpLookupData->CurrentEndpoint = 0;
  175. RpcStatus = AnsiNWAddr.Attach(NetworkAddress);
  176. if ( RpcStatus != RPC_S_OK )
  177. {
  178. ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
  179. goto CleanupAndReturn;
  180. }
  181. i = 1+RpcpStringLength(RpcProtocolSequence);
  182. *(AnsiProtseq.GetPAnsiString()) = (char *)_alloca(i);
  183. RpcStatus = AnsiProtseq.Attach(RpcProtocolSequence, i, i * 2);
  184. if ( RpcStatus != RPC_S_OK )
  185. {
  186. ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
  187. goto CleanupAndReturn;
  188. }
  189. RpcStatus = AnsiOptions.Attach(Options);
  190. if ( RpcStatus != RPC_S_OK )
  191. {
  192. ASSERT( RpcStatus == RPC_S_OUT_OF_MEMORY );
  193. goto CleanupAndReturn;
  194. }
  195. RpcStatus = BindToEpMapper(&MapperHandle,
  196. NetworkAddress,
  197. RpcProtocolSequence,
  198. Options,
  199. ConnTimeout,
  200. CallTimeout,
  201. AuthInfo
  202. );
  203. if ( RpcStatus != RPC_S_OK )
  204. {
  205. MapperHandle = 0;
  206. goto CleanupAndReturn;
  207. }
  208. RpcStatus = TowerConstruct((RPC_IF_ID PAPI *) IfId,
  209. (RPC_TRANSFER_SYNTAX PAPI *) XferId, (char PAPI *) AnsiProtseq,
  210. NULL, (char PAPI *) AnsiNWAddr, &InputTower);
  211. if ( RpcStatus != RPC_S_OK )
  212. {
  213. goto CleanupAndReturn;
  214. }
  215. NormalizeRetryCount = 0;
  216. SidFound = FALSE;
  217. for (RetryCount = 0;;)
  218. {
  219. OutputTower[0] = 0;
  220. OutputTower[1] = 0;
  221. OutputTower[2] = 0;
  222. OutputTower[3] = 0;
  223. if (AuthInfo && (AuthInfo->Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT) && (SidFound == FALSE))
  224. {
  225. // use ept_map_auth if we have the local hint and the SID.
  226. ASSERT(AuthInfo->ServerSid);
  227. RpcStatus = NormalizeAccountSid(AuthInfo->ServerSid, &SidToUse, &NormalizeRetryCount);
  228. if (RpcStatus != RPC_S_OK)
  229. {
  230. goto CleanupAndReturn;
  231. }
  232. }
  233. else
  234. SidToUse = NULL;
  235. RpcTryExcept
  236. {
  237. if (SidToUse)
  238. {
  239. ept_map_auth (MapperHandle, ObjectUuid, InputTower, (PISID)SidToUse,
  240. &ContextHandle, 4L, &Returned, &OutputTower[0], &ErrorStatus);
  241. }
  242. else
  243. {
  244. ept_map(MapperHandle, ObjectUuid, InputTower, &ContextHandle, 4L,
  245. &Returned, &OutputTower[0], &ErrorStatus);
  246. }
  247. }
  248. RpcExcept(I_RpcExceptionFilter(RpcExceptionCode()))
  249. {
  250. ErrorStatus = RpcExceptionCode();
  251. }
  252. RpcEndExcept
  253. if ((NormalizeRetryCount != 0) && (ErrorStatus == EP_S_NOT_REGISTERED))
  254. {
  255. ASSERT(AuthInfo);
  256. ASSERT(AuthInfo->ServerSid);
  257. ASSERT(AuthInfo->Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT);
  258. continue;
  259. }
  260. if ( ErrorStatus == RPC_S_SERVER_TOO_BUSY)
  261. {
  262. // RPC_S_SERVER_TOO_BUSY can happen only if we successfully
  263. // established connection. This means the SID was good.
  264. SidFound = TRUE;
  265. if (RetryCount < 3)
  266. {
  267. RetryCount ++;
  268. PartialRetries++;
  269. continue;
  270. }
  271. else
  272. {
  273. ReallyTooBusy++;
  274. }
  275. }
  276. if ( ErrorStatus != 0 )
  277. {
  278. // For DCE interop the endpoint mapper returns DCE errors on the
  279. // wire. We need to map some of them to the MS RPC ones.
  280. // Remove this SPN from our cache in case it is no longer valid, to be safe we will
  281. // do this for any error code returned from the ep mapper
  282. if (AuthInfo && (AuthInfo->Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT))
  283. {
  284. (void) RemoveFromSIDCache(AuthInfo->ServerPrincipalName);
  285. }
  286. switch (ErrorStatus)
  287. {
  288. case EP_S_CANT_PERFORM_OP :
  289. RpcStatus = EPT_S_CANT_PERFORM_OP;
  290. break;
  291. case EP_S_NOT_REGISTERED :
  292. RpcpErrorAddRecord(EEInfoGCRuntime,
  293. EPT_S_NOT_REGISTERED,
  294. EEInfoDLEpResolveEndpoint20,
  295. RpcProtocolSequence,
  296. NetworkAddress,
  297. IfId->SyntaxGUID.Data1,
  298. (ULONGLONG)MapperHandle);
  299. RpcStatus = EPT_S_NOT_REGISTERED;
  300. break;
  301. default :
  302. RpcStatus = MapFromNcaStatusCode(ErrorStatus);
  303. break;
  304. }
  305. break;
  306. }
  307. // we completed one call successfully. Remember it so that we don't
  308. // normalize the sid again
  309. SidFound = TRUE;
  310. // If the received buffer is truncated we may receive no output towers with
  311. // a non-NULL ContextHandle. This should not happen without corruption.
  312. CORRUPTION_ASSERT( ((Returned != 0) || (ContextHandle == 0)) && (Returned <= 4) );
  313. for (i = 0; i < Returned; i++)
  314. {
  315. if (OutputTower[i] == 0)
  316. {
  317. ASSERT(!"OutputTower[] contains a NULL element.\n");
  318. RpcStatus = RPC_S_OUT_OF_MEMORY ;
  319. break;
  320. }
  321. RpcStatus = TowerExplode(
  322. OutputTower[i],
  323. NULL,
  324. NULL,
  325. NULL,
  326. (char PAPI * PAPI *) &EPoint,
  327. NULL
  328. );
  329. if ( RpcStatus != RPC_S_OK )
  330. {
  331. break;
  332. }
  333. RpcStatus = nlEndpoint.Attach((char *)EPoint);
  334. *Endpoint = nlEndpoint;
  335. I_RpcFree(EPoint);
  336. if ( *Endpoint == 0 )
  337. {
  338. RpcStatus = RPC_S_OUT_OF_MEMORY;
  339. break;
  340. }
  341. EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints] =
  342. *Endpoint;
  343. // We copied the endpoint into the list. Erase its value so that we do not
  344. // return a bogus string in case we fail later, for example why exploding the
  345. // next tower. The endpoint is a member of DceBinding and should remain NULL
  346. // on failure.
  347. *Endpoint = 0;
  348. EpLookupData->NumberOfEndpoints += 1;
  349. if ( EpLookupData->NumberOfEndpoints ==
  350. EpLookupData->MaximumEndpoints )
  351. {
  352. goto OutsideTheLoop;
  353. }
  354. }//..for Loop over parse all towers/eps in this loop
  355. for (i = 0; i < Returned; i++)
  356. {
  357. MIDL_user_free(OutputTower[i]);
  358. }
  359. if ( (ContextHandle == 0) || (RpcStatus != RPC_S_OK) )
  360. {
  361. break;
  362. }
  363. } //..for loop over get all endpoints
  364. OutsideTheLoop:
  365. ASSERT( InputTower != 0 );
  366. I_RpcFree(InputTower);
  367. CleanupAndReturn:
  368. if ( MapperHandle != 0 )
  369. {
  370. RPC_STATUS Status = RpcBindingFree(&MapperHandle);
  371. ASSERT( Status == RPC_S_OK );
  372. MapperHandle = 0;
  373. }
  374. if ( ContextHandle != 0 )
  375. {
  376. RpcSsDestroyClientContext(&ContextHandle);
  377. ContextHandle = 0;
  378. }
  379. if ( ( RpcStatus == EPT_S_NOT_REGISTERED )
  380. || ( RpcStatus == RPC_S_OK ) )
  381. {
  382. if ( EpLookupData->NumberOfEndpoints != 0 )
  383. {
  384. *EpLookupHandle = EpLookupData;
  385. goto ReturnEndpointFromList;
  386. }
  387. RpcStatus = EPT_S_NOT_REGISTERED;
  388. }
  389. if ( EpLookupData != 0 )
  390. {
  391. if ( EpLookupData->Endpoints != 0 )
  392. {
  393. while ( EpLookupData->NumberOfEndpoints > 0 )
  394. {
  395. EpLookupData->NumberOfEndpoints -= 1;
  396. delete EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints];
  397. }
  398. RpcpFarFree(EpLookupData->Endpoints);
  399. }
  400. RpcpFarFree(EpLookupData);
  401. }
  402. return(RpcStatus);
  403. }
  404. RPC_STATUS RPC_ENTRY
  405. EpGetEpmapperEndpoint(
  406. IN OUT RPC_CHAR * PAPI * Endpoint,
  407. IN RPC_CHAR PAPI * Protseq
  408. )
  409. /*+
  410. Routine Description:
  411. Returns the Endpoint mappers well known endpoint for a given
  412. protocol sequence.
  413. Arguments:
  414. Endpoint - Place to store the epmappers well known endpoint.
  415. Protsq - Protocol sequence the client wishes to use.
  416. Return Value:
  417. RPC_S_OK - Found the protocol sequence in the epmapper table and
  418. am returning the associated well known endpoint.
  419. EPT_S_CANT_PERFORM_OP - Protocol sequence not found.
  420. --*/
  421. {
  422. RPC_STATUS Status = EPT_S_CANT_PERFORM_OP;
  423. RPC_STATUS rc;
  424. unsigned int i, Count;
  425. if (Protseq != NULL)
  426. {
  427. Count = sizeof(EpMapperTable)/sizeof(EpMapperTable[0]);
  428. for (i = 0; i < Count; i++)
  429. {
  430. //Search for the protocol sequence client is using.
  431. if ( RpcpStringCompare(Protseq, EpMapperTable[i].Protseq) )
  432. {
  433. //Not yet found.
  434. continue;
  435. }
  436. else
  437. {
  438. //Found a match. Grab the epmapper known endpoint.
  439. *Endpoint = DuplicateString(EpMapperTable[i].Endpoint);
  440. if (*Endpoint == NULL)
  441. return RPC_S_OUT_OF_MEMORY;
  442. else
  443. {
  444. Status = RPC_S_OK;
  445. break;
  446. }
  447. }
  448. } //for
  449. }//if
  450. return(Status);
  451. }
  452. RPC_STATUS RPC_ENTRY
  453. BindToEpMapper(
  454. OUT RPC_BINDING_HANDLE PAPI * MapperHandle,
  455. IN RPC_CHAR * NWAddress OPTIONAL,
  456. IN RPC_CHAR * Protseq OPTIONAL,
  457. IN RPC_CHAR * Options OPTIONAL,
  458. IN unsigned ConnTimeout,
  459. IN ULONG CallTimeout,
  460. IN CLIENT_AUTH_INFO *AuthInfo OPTIONAL
  461. )
  462. /*+
  463. Routine Description:
  464. This helper routine is used to by RpcEpRegister[NoReplace],
  465. RpcEpUnRegister and EpResolveEndpoint(epclnt.cxx) to bind to
  466. the EpMapper. If a Protseq is supplied, that particular protseq
  467. is tried, otherwise lrpc is used to connect to the local epmapper.
  468. If a NW Address is specified EpMapper at that host is contacted, else
  469. local Endpoint mapper is used.
  470. Arguments:
  471. MapperHandle- Returns binding handle to the Endpoint mapper
  472. NWAddress - NW address of the Endpoint mapper to bind to.
  473. Ignored if protseq is NULL.
  474. Protseq - Protocol sequence the client wishes to use.
  475. NULL indicates a call to the local endpoint mapper.
  476. ConnTimeout - the connection timeout
  477. CallTimeout - the call timeout
  478. AuthInfo - authentication information for the resolution
  479. Return Value:
  480. RPC_S_OK - The ansi string was successfully converted into a unicode
  481. string.
  482. RPC_S_OUT_OF_MEMORY - Insufficient memory is available for the unicode
  483. string.
  484. EP_S_CANT_PERFORM_OP - The binding was unsuccessful, possibly because
  485. the protocol sequence is not supported.
  486. --*/
  487. {
  488. RPC_STATUS Status = EPT_S_CANT_PERFORM_OP;
  489. RPC_CHAR * BindingString = NULL;
  490. unsigned int i, Count;
  491. BOOL IsLrpc = FALSE;
  492. RPC_SECURITY_QOS_V3 RpcSecurityQos;
  493. ASSERT(EpMapperTable[LrpcEpMapperEntry].ProtocolId == LRPC);
  494. Count = sizeof(EpMapperTable)/sizeof(EpMapperTable[0]);
  495. // If Protseq == NULL use lrpc.
  496. if (NULL == Protseq)
  497. {
  498. ASSERT(NWAddress == 0);
  499. BindingString = RPC_STRING_LITERAL("ncalrpc:[epmapper]");
  500. IsLrpc = TRUE;
  501. }
  502. else
  503. {
  504. for (i = 0; i < Count; i++)
  505. {
  506. if (RpcpStringCompare(Protseq, EpMapperTable[i].Protseq) )
  507. continue;
  508. // Found it.
  509. // skip the optimization if AuthInfo isn't present
  510. if (ARGUMENT_PRESENT(AuthInfo))
  511. {
  512. // convert local named pipes to use LRPC if necessary
  513. if (
  514. (EpMapperTable[i].ProtocolId == NMP)
  515. &&
  516. (
  517. (NWAddress == NULL)
  518. ||
  519. (AuthInfo->Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT)
  520. )
  521. )
  522. {
  523. // move directly to the endpoint mapper entry for LRPC
  524. i = LrpcEpMapperEntry;
  525. }
  526. }
  527. IsLrpc = (EpMapperTable[i].ProtocolId == LRPC);
  528. Status = RpcStringBindingCompose( NULL,
  529. EpMapperTable[i].Protseq,
  530. NWAddress,
  531. EpMapperTable[i].Endpoint,
  532. (EpMapperTable[i].ProtocolId == HTTP ? Options : 0),
  533. &BindingString);
  534. break;
  535. }
  536. }
  537. if (BindingString)
  538. {
  539. Status = RpcBindingFromStringBinding(BindingString, MapperHandle);
  540. }
  541. if (BindingString != NULL && Protseq != NULL)
  542. {
  543. RpcStringFree(&BindingString);
  544. }
  545. if (Status != RPC_S_OK)
  546. {
  547. return(EPT_S_CANT_PERFORM_OP);
  548. }
  549. if (AuthInfo && (RpcpStringNCompare(Protseq, RPC_STRING_LITERAL("ncacn_"), 6) == 0))
  550. {
  551. Status = SetAuthInformation (*MapperHandle, AuthInfo);
  552. if (Status != RPC_S_OK)
  553. return Status;
  554. }
  555. else if (IsLrpc)
  556. {
  557. // mutually authenticate the endpoint mapper for LRPC
  558. RpcSecurityQos.Version = RPC_C_SECURITY_QOS_VERSION_3;
  559. RpcSecurityQos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  560. RpcSecurityQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  561. RpcSecurityQos.Capabilities
  562. = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  563. RpcSecurityQos.AdditionalSecurityInfoType = 0;
  564. RpcSecurityQos.u.HttpCredentials = NULL;
  565. RpcSecurityQos.Sid = (PVOID)&LocalSystem;
  566. Status = RpcBindingSetAuthInfoEx (*MapperHandle,
  567. NULL,
  568. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  569. RPC_C_AUTHN_WINNT,
  570. NULL, // AuthIdentity
  571. NULL, // AuthzSvc
  572. (RPC_SECURITY_QOS *)&RpcSecurityQos
  573. );
  574. if (Status != RPC_S_OK)
  575. {
  576. RpcBindingFree(MapperHandle);
  577. return(EPT_S_CANT_PERFORM_OP);
  578. }
  579. }
  580. Status = RpcMgmtSetComTimeout(*MapperHandle, ConnTimeout);
  581. if (Status != RPC_S_OK)
  582. {
  583. RpcBindingFree(MapperHandle);
  584. return(EPT_S_CANT_PERFORM_OP);
  585. }
  586. Status = RpcBindingSetOption(*MapperHandle,
  587. RPC_C_OPT_CALL_TIMEOUT,
  588. CallTimeout);
  589. if (Status != RPC_S_OK)
  590. {
  591. RpcBindingFree(MapperHandle);
  592. return(Status);
  593. }
  594. return(RPC_S_OK);
  595. }
  596. void RPC_ENTRY
  597. EpFreeLookupHandle (
  598. IN void PAPI * EpLookupHandle
  599. )
  600. {
  601. EP_LOOKUP_DATA PAPI * EpLookupData = (EP_LOOKUP_DATA PAPI *) EpLookupHandle;
  602. if ( EpLookupData->Endpoints != 0 )
  603. {
  604. while ( EpLookupData->NumberOfEndpoints > 0 )
  605. {
  606. EpLookupData->NumberOfEndpoints -= 1;
  607. delete EpLookupData->Endpoints[EpLookupData->NumberOfEndpoints];
  608. }
  609. RpcpFarFree(EpLookupData->Endpoints);
  610. }
  611. RpcpFarFree(EpLookupData);
  612. }
  613. HPROCESS hRpcssContext = 0;
  614. RPC_STATUS RPC_ENTRY
  615. I_RpcServerAllocateIpPort(
  616. IN DWORD Flags,
  617. OUT USHORT *pPort
  618. )
  619. {
  620. USHORT Port;
  621. RPC_STATUS status;
  622. RPC_BINDING_HANDLE hServer;
  623. PORT_TYPE type;
  624. RPC_SECURITY_QOS_V3 RpcSecurityQos;
  625. *pPort = 0;
  626. // Figure out what sort of port to allocate
  627. if (Flags & RPC_C_USE_INTERNET_PORT)
  628. {
  629. type = PORT_INTERNET;
  630. Flags &= ~RPC_C_USE_INTERNET_PORT;
  631. }
  632. else if (Flags & RPC_C_USE_INTRANET_PORT)
  633. {
  634. type = PORT_INTRANET;
  635. Flags &= ~RPC_C_USE_INTRANET_PORT;
  636. }
  637. else
  638. {
  639. type = PORT_DEFAULT;
  640. }
  641. // Setup process context in the endpoint mapper if needed.
  642. if (hRpcssContext == 0)
  643. {
  644. HPROCESS hProcess;
  645. status = RpcBindingFromStringBinding(RPC_STRING_LITERAL("ncalrpc:[epmapper]"),
  646. &hServer);
  647. if (status != RPC_S_OK)
  648. {
  649. return(status);
  650. }
  651. // mutually authenticate the endpoint mapper
  652. RpcSecurityQos.Version = RPC_C_SECURITY_QOS_VERSION_3;
  653. RpcSecurityQos.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  654. RpcSecurityQos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  655. RpcSecurityQos.Capabilities
  656. = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH;
  657. RpcSecurityQos.AdditionalSecurityInfoType = 0;
  658. RpcSecurityQos.u.HttpCredentials = NULL;
  659. RpcSecurityQos.Sid = (PVOID)&LocalSystem;
  660. status = RpcBindingSetAuthInfoEx (hServer,
  661. (RPC_CHAR *)&LocalSystem,
  662. RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
  663. RPC_C_AUTHN_WINNT,
  664. NULL, // AuthIdentity
  665. NULL, // AuthzSvc
  666. (RPC_SECURITY_QOS *)&RpcSecurityQos
  667. );
  668. if (status != RPC_S_OK)
  669. {
  670. return(status);
  671. }
  672. hProcess = 0;
  673. status = OpenEndpointMapper(hServer,
  674. &hProcess);
  675. RPC_STATUS statust =
  676. RpcBindingFree(&hServer);
  677. ASSERT(statust == RPC_S_OK);
  678. if (status != RPC_S_OK)
  679. {
  680. return(status);
  681. }
  682. GlobalMutexRequest();
  683. if (hRpcssContext != 0)
  684. {
  685. ASSERT(hRpcssContext != hProcess);
  686. RpcSmDestroyClientContext(&hProcess);
  687. }
  688. else
  689. {
  690. hRpcssContext = hProcess;
  691. }
  692. GlobalMutexClear();
  693. }
  694. // Actually allocate a port.
  695. RPC_STATUS allocstatus;
  696. status = AllocateReservedIPPort(hRpcssContext,
  697. type,
  698. &allocstatus,
  699. pPort);
  700. if (status != RPC_S_OK)
  701. {
  702. ASSERT(*pPort == 0);
  703. return(status);
  704. }
  705. return(allocstatus);
  706. }
  707. // Very special code for our older (NT 3.1 Era) servers.
  708. //
  709. // These server send out unique pointers which will confuse our
  710. // stubs while unmarshalling. Here we go through and fixup the
  711. // node id's to look like full pointers.
  712. //
  713. // This code can be removed when support for NT 3.1 era servers
  714. // is no longer required.
  715. extern "C"
  716. void FixupForUniquePointerServers(PRPC_MESSAGE pMessage)
  717. {
  718. int CurrentPointer = 3;
  719. unsigned int NumberOfPointers;
  720. unsigned int i;
  721. unsigned long __RPC_FAR *pBuffer;
  722. pBuffer = (unsigned long __RPC_FAR *) pMessage->Buffer;
  723. // The output buffer looks like:
  724. // [ out-context handle (20b) ]
  725. // [ count (4b) ]
  726. // [ max (4b) ]
  727. // [ min (4b) ]
  728. // [ length (4b) ] // should be the same as count
  729. // [ pointer node (count of them) ]
  730. ASSERT(pBuffer[5] == pBuffer[8]);
  731. NumberOfPointers = pBuffer[5];
  732. ASSERT(pMessage->BufferLength >= 4 * 9 + 4 * NumberOfPointers);
  733. for(i = 0; i < NumberOfPointers; i++)
  734. {
  735. if (pBuffer[9 + i] != 0)
  736. {
  737. pBuffer[9 + i] = CurrentPointer;
  738. CurrentPointer++;
  739. }
  740. }
  741. return;
  742. }
  743. #if defined(WIN) || defined(WIN32)
  744. void __RPC_FAR * __RPC_API
  745. MIDL_user_allocate(
  746. size_t Size
  747. )
  748. /*++
  749. Routine Description:
  750. MIDL generated stubs need this routine.
  751. Arguments:
  752. Size - Supplies the length of the memory to allocate in bytes.
  753. Return Value:
  754. The buffer allocated will be returned, if there is sufficient memory,
  755. otherwise, zero will be returned.
  756. --*/
  757. {
  758. void PAPI * pvBuf;
  759. pvBuf = I_RpcAllocate(Size);
  760. return(pvBuf);
  761. }
  762. void __RPC_API
  763. MIDL_user_free (
  764. void __RPC_FAR *Buf
  765. )
  766. {
  767. I_RpcFree(Buf);
  768. }
  769. #endif