Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1200 lines
35 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1991 - 1999
  3. Module Name:
  4. dcebind.cxx
  5. Abstract:
  6. This module contains the code implementing the Binding Object DCE RPC
  7. runtime APIs. APIs which are used only by server applications do not
  8. live here.
  9. Author:
  10. Michael Montague (mikemon) 25-Sep-1991
  11. Revision History:
  12. --*/
  13. #include <precomp.hxx>
  14. #include <rpccfg.h>
  15. #include <CharConv.hxx>
  16. RPC_STATUS RPC_ENTRY
  17. RpcBindingCopy (
  18. IN RPC_BINDING_HANDLE SourceBinding,
  19. OUT RPC_BINDING_HANDLE PAPI * DestinationBinding
  20. )
  21. /*++
  22. Routine Description:
  23. This routine copies binding information and creates a new binding
  24. handle.
  25. Arguments:
  26. SourceBinding - Supplies the binding to be duplicated.
  27. DestinationBinding - Returns a new binding which is a duplicate of
  28. SourceBinding.
  29. Return Value:
  30. The status for the operation is returned.
  31. --*/
  32. {
  33. MESSAGE_OBJECT * Binding;
  34. THREAD *Thread;
  35. InitializeIfNecessary();
  36. Thread = ThreadSelf();
  37. if (Thread == NULL)
  38. return RPC_S_OUT_OF_MEMORY;
  39. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  40. Binding = (MESSAGE_OBJECT *) SourceBinding;
  41. if (Binding->InvalidHandle(BINDING_HANDLE_TYPE))
  42. {
  43. return NDRCCopyContextHandle(SourceBinding, DestinationBinding);
  44. }
  45. return(Binding->BindingCopy((BINDING_HANDLE *PAPI *) DestinationBinding, 0));
  46. }
  47. RPC_STATUS RPC_ENTRY
  48. I_RpcBindingCopy (
  49. IN RPC_BINDING_HANDLE SourceBinding,
  50. OUT RPC_BINDING_HANDLE PAPI * DestinationBinding
  51. )
  52. /*++
  53. Routine Description:
  54. This routine copies binding information and creates a new binding
  55. handle. In addition, context is being maintained by the server over
  56. this binding handle.
  57. Arguments:
  58. SourceBinding - Supplies the binding to be duplicated.
  59. DestinationBinding - Returns a new binding which is a duplicate of
  60. SourceBinding.
  61. Return Value:
  62. The status for the operation is returned.
  63. --*/
  64. {
  65. MESSAGE_OBJECT * Binding;
  66. InitializeIfNecessary();
  67. Binding = (MESSAGE_OBJECT *) SourceBinding;
  68. if (Binding->InvalidHandle(BINDING_HANDLE_TYPE))
  69. return(RPC_S_INVALID_BINDING);
  70. return(Binding->BindingCopy((BINDING_HANDLE * PAPI *) DestinationBinding, 1));
  71. }
  72. RPC_STATUS RPC_ENTRY
  73. RpcBindingFree (
  74. IN OUT RPC_BINDING_HANDLE PAPI * Binding
  75. )
  76. /*++
  77. Routine Description :
  78. RpcBindingFree releases binding handle resources.
  79. Arguments:
  80. Binding - Supplies the binding handle to be freed, and returns zero.
  81. Return Value:
  82. The status of the operation is returned.
  83. --*/
  84. {
  85. BINDING_HANDLE * BindingHandle;
  86. RPC_STATUS Status;
  87. // if we're shutting down, don't bother
  88. // Since our other threads have been nuked, data structures may
  89. // be in half modified state. Therefore it is unsafe to proceed
  90. // with freeing the binding handle during shutdown
  91. if (RtlDllShutdownInProgress())
  92. {
  93. *Binding = 0;
  94. return RPC_S_OK;
  95. }
  96. InitializeIfNecessary();
  97. // here it will be more efficient if we succeed, but other code will manage fine
  98. // even if we don't, so we don't really care about return value
  99. ThreadSelf();
  100. ASSERT(!RpcpCheckHeap());
  101. BindingHandle = (BINDING_HANDLE *) *Binding;
  102. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  103. return(RPC_S_INVALID_BINDING);
  104. Status = BindingHandle->BindingFree();
  105. *Binding = 0;
  106. return(Status);
  107. }
  108. RPC_STATUS RPC_ENTRY
  109. RpcBindingReset (
  110. IN RPC_BINDING_HANDLE Binding
  111. )
  112. /*++
  113. Routine Description:
  114. This routine sets the endpoint in the supplied binding handle to
  115. zero. This makes the binding handle a partiallly bound binding
  116. handle. NOTE: this routine will fail if the binding handle has
  117. already been used to make remote procedure calls. Based on how
  118. this routine will be used (to iterate through the entries in the
  119. endpoint mapper database), this should not be a problem.
  120. Arguments:
  121. Binding - Supplies the binding handle for which the endpoint will
  122. be set to zero, hence making it a partially bound binding handle.
  123. Return Value:
  124. RPC_S_OK - The operation completed successfully.
  125. RPC_S_INVALID_BINDING - The supplied argument is not a valid binding.
  126. RPC_S_WRONG_KIND_OF_BINDING - Either the supplied binding is not a
  127. client binding handle or it is a client binding handle which has
  128. already been used to make remote procedure calls.
  129. --*/
  130. {
  131. BINDING_HANDLE * BindingHandle;
  132. THREAD *Thread;
  133. Thread = ThreadSelf();
  134. if (Thread == NULL)
  135. return RPC_S_OUT_OF_MEMORY;
  136. BindingHandle = (BINDING_HANDLE *) Binding;
  137. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  138. return(RPC_S_INVALID_BINDING);
  139. return(BindingHandle->BindingReset());
  140. }
  141. RPC_STATUS RPC_ENTRY
  142. RpcBindingFromStringBinding (
  143. IN unsigned short PAPI * StringBinding,
  144. OUT RPC_BINDING_HANDLE PAPI * Binding
  145. )
  146. /*++
  147. Routine Description:
  148. This routine returns a binding handle from a string representation
  149. of a binding handle.
  150. Arguments:
  151. StringBinding - Supplies the string representation of a binding handle.
  152. Binding - Returns a binding handle constructed from the string
  153. representation.
  154. Return Value:
  155. The status of the operation is returned.
  156. --*/
  157. {
  158. DCE_BINDING * DceBinding;
  159. RPC_STATUS Status;
  160. BINDING_HANDLE * BindingHandle;
  161. RPC_CHAR __RPC_FAR * CopiedStringBinding;
  162. THREAD *Thread;
  163. InitializeIfNecessary();
  164. ASSERT(!RpcpCheckHeap());
  165. Thread = ThreadSelf();
  166. if (!Thread)
  167. return RPC_S_OUT_OF_MEMORY;
  168. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  169. *Binding = 0;
  170. CopiedStringBinding = (RPC_CHAR *)
  171. _alloca( (RpcpStringLength(StringBinding)+1)*(sizeof(RPC_CHAR)) );
  172. if (CopiedStringBinding == 0)
  173. {
  174. return (RPC_S_OUT_OF_MEMORY);
  175. }
  176. RpcpStringCopy(CopiedStringBinding, StringBinding);
  177. DceBinding = new DCE_BINDING(CopiedStringBinding, &Status);
  178. if (DceBinding == 0)
  179. Status = RPC_S_OUT_OF_MEMORY;
  180. if (Status == RPC_S_OK)
  181. {
  182. BindingHandle = DceBinding->CreateBindingHandle(&Status);
  183. if (Status == RPC_S_OK)
  184. *Binding = BindingHandle;
  185. //
  186. // DceBinding gets deleted by the callee, if the above call fails
  187. //
  188. }
  189. else
  190. {
  191. delete DceBinding;
  192. }
  193. return(Status);
  194. }
  195. RPC_STATUS RPC_ENTRY
  196. RpcBindingSetObject (
  197. IN RPC_BINDING_HANDLE Binding,
  198. IN UUID PAPI * ObjectUuid
  199. )
  200. /*++
  201. Routine Description:
  202. This routine sets the object UUID value in a binding handle.
  203. Arguments:
  204. Binding - Supplies the binding handle for which the object UUID is
  205. to be set.
  206. ObjectUuid - Supplies the UUID value to put into the binding handle.
  207. Return Values:
  208. RPC_S_OK - The operation completed successfully.
  209. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  210. handle.
  211. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a
  212. binding handle, but it is not a client binding handle (ie. one
  213. owned by the client side rpc runtime).
  214. --*/
  215. {
  216. BINDING_HANDLE * BindingHandle;
  217. InitializeIfNecessary();
  218. BindingHandle = (BINDING_HANDLE *) Binding;
  219. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  220. return(RPC_S_INVALID_BINDING);
  221. BindingHandle->SetObjectUuid((RPC_UUID PAPI *) ObjectUuid);
  222. return(RPC_S_OK);
  223. }
  224. RPC_STATUS RPC_ENTRY
  225. RpcBindingVectorFree (
  226. IN OUT RPC_BINDING_VECTOR PAPI * PAPI * BindingVector
  227. )
  228. /*++
  229. Routine Description:
  230. This routine frees the binding handles contained in the vector, and
  231. the vector itself.
  232. Arguments:
  233. BindingVector - Supplies a vector of binding handles which will be
  234. freed. On return, the pointer to the binding vector will be
  235. set to zero.
  236. Return Value:
  237. The status of the operation will be returned.
  238. --*/
  239. {
  240. unsigned int Index, Count;
  241. RPC_BINDING_VECTOR PAPI * Vector;
  242. RPC_STATUS Status;
  243. InitializeIfNecessary();
  244. for (Index = 0, Vector = *BindingVector,
  245. Count = (unsigned int) Vector->Count;
  246. Index < Count; Index++)
  247. if (Vector->BindingH[Index] != 0)
  248. {
  249. Status = RpcBindingFree(&(Vector->BindingH[Index]));
  250. if (Status != RPC_S_OK)
  251. return(Status);
  252. }
  253. RpcpFarFree(*BindingVector);
  254. *BindingVector = 0;
  255. return(RPC_S_OK);
  256. }
  257. RPC_STATUS RPC_ENTRY
  258. RpcEpResolveBinding (
  259. IN RPC_BINDING_HANDLE Binding,
  260. IN RPC_IF_HANDLE IfSpec
  261. )
  262. /*++
  263. Routine Description:
  264. This routine is used to resolve a partially-bound binding handle
  265. into a fully-bound binding handle. A partially-bound binding
  266. handle is one in which the endpoint is not specified. To make
  267. the binding handle fully-bound, we need to determine the endpoint.
  268. Arguments:
  269. Binding - Supplies a partially-bound binding handle to resolve into
  270. a fully bound one. Specifying a fully-bound binding handle to
  271. this routine is not an error; it has no effect on the binding
  272. handle.
  273. IfSpec - Supplies a handle to the description of the interface for
  274. which we wish to resolve the endpoint. This information will
  275. be used to find the correct server on the machine specified by
  276. the network address in the binding handle.
  277. Return Value:
  278. RPC_S_OK - The binding handle is now fully-bound.
  279. RPC_S_NO_ENDPOINT_FOUND - We were unable to resolve the endpoint
  280. for this particular combination of binding handle (network address)
  281. and interface.
  282. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to resolve
  283. the endpoint.
  284. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  285. handle.
  286. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a
  287. binding handle, but it is not a client binding handle (ie. one
  288. owned by the client side rpc runtime).
  289. --*/
  290. {
  291. BINDING_HANDLE * BindingHandle;
  292. InitializeIfNecessary();
  293. BindingHandle = (BINDING_HANDLE *) Binding;
  294. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  295. return(RPC_S_INVALID_BINDING);
  296. return(BindingHandle->ResolveBinding((PRPC_CLIENT_INTERFACE) IfSpec));
  297. }
  298. RPC_STATUS RPC_ENTRY
  299. RpcNsBindingInqEntryName (
  300. IN RPC_BINDING_HANDLE Binding,
  301. IN unsigned long EntryNameSyntax,
  302. OUT unsigned short PAPI * PAPI * EntryName
  303. )
  304. /*++
  305. Routine Description:
  306. Arguments:
  307. Return Value:
  308. RPC_S_OK - The entry name for the binding handle has been successfully
  309. inquired and returned.
  310. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  311. handle.
  312. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a
  313. binding handle, but it is not a client binding handle (ie. one
  314. owned by the client side rpc runtime).
  315. --*/
  316. {
  317. #if !defined(NO_LOCATOR_CODE)
  318. BINDING_HANDLE * BindingHandle;
  319. InitializeIfNecessary();
  320. BindingHandle = (BINDING_HANDLE *) Binding;
  321. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  322. return(RPC_S_INVALID_BINDING);
  323. return(BindingHandle->InquireEntryName(EntryNameSyntax, EntryName));
  324. #else
  325. return RPC_S_CANNOT_SUPPORT;
  326. #endif
  327. }
  328. RPC_STATUS RPC_ENTRY
  329. THUNK_FN(I_RpcNsBindingSetEntryName) (
  330. IN RPC_BINDING_HANDLE,
  331. IN unsigned long,
  332. IN unsigned char *
  333. )
  334. {
  335. return RPC_S_CANNOT_SUPPORT;
  336. }
  337. RPC_STATUS RPC_ENTRY
  338. I_RpcNsBindingSetEntryName (
  339. IN RPC_BINDING_HANDLE Binding,
  340. IN unsigned long EntryNameSyntax,
  341. IN unsigned short PAPI * EntryName
  342. )
  343. /*++
  344. Routine Description:
  345. This routine is a private entry point for use by name service support
  346. dlls; it allows them to set the entry name in a binding handle
  347. before returning it from import or lookup. If an entry name already
  348. exists in the binding handle, we just go ahead and overwrite the
  349. old one with new one.
  350. Arguments:
  351. Binding - Supplies the binding handle for which we want to set the
  352. entry name.
  353. EntryNameSyntax - Supplies the syntax used by the entry name. We need
  354. to save this information for when the entry name is inquired.
  355. EntryName - Supplies the entry name for this binding handle.
  356. Return Value:
  357. RPC_S_OK - The entry name has been successfully set for the binding
  358. handle.
  359. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  360. the operation.
  361. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  362. handle.
  363. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a
  364. binding handle, but it is not a client binding handle (ie. one
  365. owned by the client side rpc runtime).
  366. --*/
  367. {
  368. #if !defined(NO_LOCATOR_CODE)
  369. BINDING_HANDLE * BindingHandle;
  370. InitializeIfNecessary();
  371. BindingHandle = (BINDING_HANDLE *) Binding;
  372. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  373. return(RPC_S_INVALID_BINDING);
  374. return(BindingHandle->SetEntryName(EntryNameSyntax, EntryName));
  375. #else
  376. return RPC_S_CANNOT_SUPPORT;
  377. #endif
  378. }
  379. RPC_STATUS RPC_ENTRY
  380. RpcBindingInqAuthInfo (
  381. IN RPC_BINDING_HANDLE Binding,
  382. OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
  383. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  384. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  385. OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
  386. OUT unsigned long PAPI * AuthzSvc OPTIONAL
  387. )
  388. /*++
  389. Routine Description:
  390. This routine is used to return the authentication and authorization for
  391. a binding handle. You should also see RpcBindingSetAuthInfoW.
  392. Arguments:
  393. Binding - Supplies the binding handle for which we wish to query the
  394. authentication and authorization information.
  395. ServerPrincName - Optionally returns the server principal name set for
  396. the binding handle.
  397. AuthnLevel - Optionally returns the authentication level set for the
  398. binding handle.
  399. AuthnSvc - Optionally returns the authentication service set for the
  400. binding handle.
  401. AuthIdentity - Optionally returns a handle to the security context
  402. being used for authentication and authorization.
  403. AuthzSvc - Optionally returns the authorization service set for the
  404. binding handle.
  405. Return Value:
  406. RPC_S_OK - We successfully returned the information requested.
  407. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  408. the operation.
  409. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  410. not a valid binding handle.
  411. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  412. be specified as the binding argument.
  413. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been
  414. called on the binding handle, so there is not authentication or
  415. authorization to be returned.
  416. --*/
  417. {
  418. BINDING_HANDLE * BindingObject;
  419. CLIENT_AUTH_INFO * ClientAuthInfo;
  420. InitializeIfNecessary();
  421. return( RpcBindingInqAuthInfoEx(
  422. Binding,
  423. ServerPrincName,
  424. AuthnLevel,
  425. AuthnSvc,
  426. AuthIdentity,
  427. AuthzSvc,
  428. 0,
  429. 0
  430. ) );
  431. }
  432. RPC_STATUS RPC_ENTRY
  433. RpcBindingInqAuthInfoEx (
  434. IN RPC_BINDING_HANDLE Binding,
  435. OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
  436. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  437. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  438. OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
  439. OUT unsigned long PAPI * AuthzSvc, OPTIONAL
  440. IN unsigned long RpcSecurityQosVersion,
  441. OUT RPC_SECURITY_QOS * SecurityQos
  442. )
  443. /*++
  444. Routine Description:
  445. This routine is used to return the authentication and authorization for
  446. a binding handle. You should also see RpcBindingSetAuthInfoW.
  447. Arguments:
  448. Binding - Supplies the binding handle for which we wish to query the
  449. authentication and authorization information.
  450. ServerPrincName - Optionally returns the server principal name set for
  451. the binding handle.
  452. AuthnLevel - Optionally returns the authentication level set for the
  453. binding handle.
  454. AuthnSvc - Optionally returns the authentication service set for the
  455. binding handle.
  456. AuthIdentity - Optionally returns a handle to the security context
  457. being used for authentication and authorization.
  458. AuthzSvc - Optionally returns the authorization service set for the
  459. binding handle.
  460. RpcSecurityQosVersion - Indicates a version for RPC_SECURITY_QOS structure,
  461. that optionally can be inquired. If SecurityQOS passes in is 0, this
  462. is ignored.
  463. SecurityQOS - is the version of the Security Quality Of Service
  464. Return Value:
  465. RPC_S_OK - We successfully returned the information requested.
  466. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  467. the operation.
  468. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  469. not a valid binding handle.
  470. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  471. be specified as the binding argument.
  472. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been
  473. called on the binding handle, so there is not authentication or
  474. authorization to be returned.
  475. --*/
  476. {
  477. BINDING_HANDLE * BindingObject;
  478. CLIENT_AUTH_INFO * ClientAuthInfo;
  479. InitializeIfNecessary();
  480. BindingObject = (BINDING_HANDLE *) Binding;
  481. if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) )
  482. {
  483. return(RPC_S_INVALID_BINDING);
  484. }
  485. ClientAuthInfo = BindingObject->InquireAuthInformation();
  486. if ( ClientAuthInfo == 0
  487. || ClientAuthInfo->AuthenticationLevel == RPC_C_AUTHN_LEVEL_NONE)
  488. {
  489. return(RPC_S_BINDING_HAS_NO_AUTH);
  490. }
  491. if (ARGUMENT_PRESENT(AuthnLevel))
  492. {
  493. *AuthnLevel = ClientAuthInfo->AuthenticationLevel;
  494. }
  495. if (ARGUMENT_PRESENT(AuthnSvc))
  496. {
  497. *AuthnSvc = ClientAuthInfo->AuthenticationService;
  498. }
  499. if (ARGUMENT_PRESENT(AuthIdentity))
  500. {
  501. *AuthIdentity = ClientAuthInfo->AuthIdentity;
  502. }
  503. if (ARGUMENT_PRESENT(AuthzSvc))
  504. {
  505. *AuthzSvc = ClientAuthInfo->AuthorizationService;
  506. }
  507. if (ARGUMENT_PRESENT(ServerPrincName))
  508. {
  509. if ( ClientAuthInfo->ServerPrincipalName == 0 )
  510. {
  511. *ServerPrincName = 0;
  512. }
  513. else
  514. {
  515. *ServerPrincName = DuplicateStringPAPI(
  516. ClientAuthInfo->ServerPrincipalName);
  517. if ( *ServerPrincName == 0 )
  518. {
  519. return(RPC_S_OUT_OF_MEMORY);
  520. }
  521. }
  522. }
  523. if (ARGUMENT_PRESENT(SecurityQos))
  524. {
  525. if (RpcSecurityQosVersion != RPC_C_SECURITY_QOS_VERSION)
  526. {
  527. if (ARGUMENT_PRESENT(ServerPrincName))
  528. delete *ServerPrincName;
  529. return (RPC_S_INVALID_ARG);
  530. }
  531. SecurityQos->Version = RPC_C_SECURITY_QOS_VERSION;
  532. SecurityQos->Capabilities = ClientAuthInfo->Capabilities;
  533. SecurityQos->ImpersonationType = ClientAuthInfo->ImpersonationType;
  534. SecurityQos->IdentityTracking = ClientAuthInfo->IdentityTracking;
  535. }
  536. return(RPC_S_OK);
  537. }
  538. RPC_STATUS RPC_ENTRY
  539. RpcBindingSetAuthInfo (
  540. IN RPC_BINDING_HANDLE Binding,
  541. IN unsigned short PAPI * ServerPrincName,
  542. IN unsigned long AuthnLevel,
  543. IN unsigned long AuthnSvc,
  544. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  545. IN unsigned long AuthzSvc
  546. )
  547. /*++
  548. Routine Description:
  549. A client application will use this routine to specify the authentication
  550. and authorization information in a binding handle, so that the binding
  551. handle can be used to make authenticated remote procedure calls. If
  552. the this routine is not used, then all remote procedure calls on the
  553. binding handle will be unauthenticated.
  554. Arguments:
  555. Binding - Supplies binding handle for which we want to set authentication
  556. and authorization information.
  557. ServerPrincName - Supplies the expected principal name of the server
  558. referenced by the binding handle (that is supplied as the binding
  559. argument). This information is necessary for some security services
  560. to be able to authenticate with the server.
  561. AuthnLevel - Supplies a value indicating the amount (or level) of
  562. authentication to be performed on remote procedure calls using
  563. the binding handle. If we do not support the requested level,
  564. we will upgrade to the next highest supported level.
  565. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for
  566. authentication service being used should be used.
  567. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication.
  568. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only
  569. when the client first talks to the server.
  570. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will
  571. use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols,
  572. authentication will be performed at the beginning of each
  573. remote procedure call.
  574. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that
  575. the data it is received from the expected client.
  576. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that
  577. the data is from the expected client, we will verify that none
  578. of it has been modified.
  579. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the
  580. support in packet integrity, as well as encrypting all remote
  581. procedure call data.
  582. AuthnSvc - Supplies the authentication service to use.
  583. AuthIdentify - Optionally supplies authentication and authorization
  584. credentials to use; if this argument is not specified, the security
  585. context for the current address space will be used.
  586. AuthzSvc - Supplies the authorization service being used by the
  587. server. The client must know this so that the correct authorization
  588. information can be sent to the server.
  589. Return Value:
  590. RPC_S_OK - The supplied authentication and authorization information has
  591. been set in the binding handle.
  592. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  593. operation.
  594. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  595. not a valid binding handle.
  596. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  597. be specified as the binding argument.
  598. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  599. not supported.
  600. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is
  601. not supported.
  602. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied
  603. by the auth identity argument) is invalid.
  604. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is
  605. not supported.
  606. --*/
  607. {
  608. return ( RpcBindingSetAuthInfoEx(
  609. Binding,
  610. ServerPrincName,
  611. AuthnLevel,
  612. AuthnSvc,
  613. AuthIdentity,
  614. AuthzSvc,
  615. 0 ) );
  616. }
  617. RPC_STATUS RPC_ENTRY
  618. RpcBindingSetAuthInfoEx (
  619. IN RPC_BINDING_HANDLE Binding,
  620. IN unsigned short PAPI * ServerPrincName,
  621. IN unsigned long AuthnLevel,
  622. IN unsigned long AuthnSvc,
  623. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  624. IN unsigned long AuthzSvc,
  625. IN RPC_SECURITY_QOS *SecurityQOS
  626. )
  627. /*++
  628. Routine Description:
  629. A client application will use this routine to specify the authentication
  630. and authorization information in a binding handle, so that the binding
  631. handle can be used to make authenticated remote procedure calls. If
  632. the this routine is not used, then all remote procedure calls on the
  633. binding handle will be unauthenticated.
  634. Arguments:
  635. Binding - Supplies binding handle for which we want to set authentication
  636. and authorization information.
  637. ServerPrincName - Supplies the expected principal name of the server
  638. referenced by the binding handle (that is supplied as the binding
  639. argument). This information is necessary for some security services
  640. to be able to authenticate with the server.
  641. AuthnLevel - Supplies a value indicating the amount (or level) of
  642. authentication to be performed on remote procedure calls using
  643. the binding handle. If we do not support the requested level,
  644. we will upgrade to the next highest supported level.
  645. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for
  646. authentication service being used should be used.
  647. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication.
  648. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only
  649. when the client first talks to the server.
  650. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will
  651. use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols,
  652. authentication will be performed at the beginning of each
  653. remote procedure call.
  654. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that
  655. the data it is received from the expected client.
  656. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that
  657. the data is from the expected client, we will verify that none
  658. of it has been modified.
  659. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the
  660. support in packet integrity, as well as encrypting all remote
  661. procedure call data.
  662. AuthnSvc - Supplies the authentication service to use.
  663. AuthIdentify - Optionally supplies authentication and authorization
  664. credentials to use; if this argument is not specified, the security
  665. context for the current address space will be used.
  666. AuthzSvc - Supplies the authorization service being used by the
  667. server. The client must know this so that the correct authorization
  668. information can be sent to the server.
  669. SecurityQOS - a security QOS stucture. Currently accepting RPC_C_SECURITY_QOS_VERSION_2
  670. and RPC_C_SECURITY_QOS_VERSION_1
  671. Return Value:
  672. RPC_S_OK - The supplied authentication and authorization information has
  673. been set in the binding handle.
  674. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  675. operation.
  676. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  677. not a valid binding handle.
  678. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  679. be specified as the binding argument.
  680. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  681. not supported.
  682. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is
  683. not supported.
  684. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied
  685. by the auth identity argument) is invalid.
  686. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is
  687. not supported.
  688. --*/
  689. {
  690. BINDING_HANDLE * BindingObject;
  691. RPC_STATUS Status;
  692. RPC_CHAR __RPC_FAR * ServerName;
  693. unsigned long ImpersonationType;
  694. unsigned long IdentityTracking;
  695. unsigned long Capabilities;
  696. void *AdditionalCredentials;
  697. ULONG AdditionalTransportCredentialsType;
  698. THREAD *Thread;
  699. RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials;
  700. unsigned int i;
  701. InitializeIfNecessary();
  702. Thread = ThreadSelf();
  703. if (Thread)
  704. {
  705. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  706. }
  707. BindingObject = (BINDING_HANDLE *) Binding;
  708. if ((SecurityQOS != 0) &&
  709. (SecurityQOS->Version != RPC_C_SECURITY_QOS_VERSION_1) &&
  710. (SecurityQOS->Version != RPC_C_SECURITY_QOS_VERSION_2) )
  711. {
  712. return(RPC_S_INVALID_ARG);
  713. }
  714. if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) )
  715. {
  716. return(RPC_S_INVALID_BINDING);
  717. }
  718. //
  719. // For no authentication, bail out now.
  720. //
  721. if (AuthnSvc == RPC_C_AUTHN_NONE)
  722. {
  723. if ((AuthnLevel != RPC_C_AUTHN_LEVEL_NONE) &&
  724. (AuthnLevel != RPC_C_AUTHN_LEVEL_DEFAULT))
  725. {
  726. return(RPC_S_UNKNOWN_AUTHN_LEVEL);
  727. }
  728. //
  729. // Clear the authentication info..
  730. //
  731. Status = BindingObject->SetAuthInformation(
  732. 0,
  733. RPC_C_AUTHN_LEVEL_NONE,
  734. AuthnSvc,
  735. 0,
  736. 0
  737. );
  738. return(Status);
  739. }
  740. if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
  741. {
  742. RpcpGetDefaultSecurityProviderInfo();
  743. AuthnSvc = DefaultProviderId;
  744. }
  745. if (AuthnSvc == RPC_C_AUTHN_GSS_SCHANNEL)
  746. {
  747. if (AuthnLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
  748. {
  749. AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  750. }
  751. }
  752. if (SecurityQOS != 0)
  753. {
  754. IdentityTracking = SecurityQOS->IdentityTracking;
  755. ImpersonationType= SecurityQOS->ImpersonationType;
  756. Capabilities = SecurityQOS->Capabilities;
  757. if (SecurityQOS->Version == RPC_C_SECURITY_QOS_VERSION_1)
  758. {
  759. AdditionalTransportCredentialsType = 0;
  760. AdditionalCredentials = NULL;
  761. }
  762. else
  763. {
  764. AdditionalTransportCredentialsType = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->AdditionalSecurityInfoType;
  765. AdditionalCredentials = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->u.HttpCredentials;
  766. if (AdditionalTransportCredentialsType != RPC_C_AUTHN_INFO_TYPE_HTTP)
  767. {
  768. if (AdditionalTransportCredentialsType != 0)
  769. return(RPC_S_INVALID_ARG);
  770. if (AdditionalCredentials != NULL)
  771. return(RPC_S_INVALID_ARG);
  772. }
  773. else if (AdditionalCredentials == NULL)
  774. return(RPC_S_INVALID_ARG);
  775. else
  776. {
  777. HttpCredentials = (RPC_HTTP_TRANSPORT_CREDENTIALS_W *)AdditionalCredentials;
  778. if (HttpCredentials->TransportCredentials)
  779. {
  780. if (HttpCredentials->TransportCredentials->User)
  781. {
  782. if (RpcpStringLength(HttpCredentials->TransportCredentials->User)
  783. != HttpCredentials->TransportCredentials->UserLength)
  784. {
  785. return(RPC_S_INVALID_ARG);
  786. }
  787. }
  788. else if (HttpCredentials->TransportCredentials->UserLength)
  789. return(RPC_S_INVALID_ARG);
  790. if (HttpCredentials->TransportCredentials->Domain)
  791. {
  792. if (RpcpStringLength(HttpCredentials->TransportCredentials->Domain)
  793. != HttpCredentials->TransportCredentials->DomainLength)
  794. {
  795. return(RPC_S_INVALID_ARG);
  796. }
  797. }
  798. else if (HttpCredentials->TransportCredentials->DomainLength)
  799. return(RPC_S_INVALID_ARG);
  800. if (HttpCredentials->TransportCredentials->Password)
  801. {
  802. if (RpcpStringLength(HttpCredentials->TransportCredentials->Password)
  803. != HttpCredentials->TransportCredentials->PasswordLength)
  804. {
  805. return(RPC_S_INVALID_ARG);
  806. }
  807. }
  808. else if (HttpCredentials->TransportCredentials->PasswordLength)
  809. return(RPC_S_INVALID_ARG);
  810. if (HttpCredentials->TransportCredentials->Flags != SEC_WINNT_AUTH_IDENTITY_UNICODE)
  811. return(RPC_S_INVALID_ARG);
  812. }
  813. // if you don't want to authenticate against anyone, you can't authenticate
  814. if (HttpCredentials->AuthenticationTarget == 0)
  815. return(RPC_S_INVALID_ARG);
  816. // if you don't support any method of authentication, you can't authenticate
  817. if (HttpCredentials->NumberOfAuthnSchemes == 0)
  818. return(RPC_S_INVALID_ARG);
  819. // if you don't support any method of authentication, you can't authenticate
  820. if (HttpCredentials->AuthnSchemes == NULL)
  821. return(RPC_S_INVALID_ARG);
  822. // check whether Negotiate, Passport or Digest are in the list of auth scehemes. If yes,
  823. // reject the call since we don't support them yet.
  824. for (i = 0; i < HttpCredentials->NumberOfAuthnSchemes; i ++)
  825. {
  826. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_PASSPORT)
  827. return RPC_S_CANNOT_SUPPORT;
  828. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE)
  829. return RPC_S_CANNOT_SUPPORT;
  830. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_DIGEST)
  831. return RPC_S_CANNOT_SUPPORT;
  832. }
  833. }
  834. }
  835. }
  836. else
  837. {
  838. IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  839. ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  840. Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  841. AdditionalTransportCredentialsType = 0;
  842. AdditionalCredentials = NULL;
  843. }
  844. Status = BindingObject->SetAuthInformation(
  845. ServerPrincName,
  846. AuthnLevel,
  847. AuthnSvc,
  848. AuthIdentity,
  849. AuthzSvc,
  850. 0,
  851. ImpersonationType,
  852. IdentityTracking,
  853. Capabilities,
  854. TRUE, // Acquire new credentials
  855. AdditionalTransportCredentialsType,
  856. AdditionalCredentials
  857. );
  858. return (Status);
  859. }
  860. RPC_STATUS RPC_ENTRY
  861. I_RpcBindingInqSecurityContext (
  862. IN RPC_BINDING_HANDLE Binding,
  863. OUT void **SecurityContextHandle
  864. )
  865. /*++
  866. Routine Description:
  867. Arguments:
  868. Return Value:
  869. The status for the operation is returned.
  870. --*/
  871. {
  872. CALL * Call;
  873. InitializeIfNecessary();
  874. Call = (CALL *) Binding;
  875. if (Call->InvalidHandle(CALL_TYPE))
  876. return(RPC_S_INVALID_BINDING);
  877. return(Call->InqSecurityContext(SecurityContextHandle));
  878. }
  879. RPC_STATUS RPC_ENTRY
  880. I_RpcTurnOnEEInfoPropagation (
  881. void
  882. )
  883. /*++
  884. Routine Description:
  885. Turns on extended error info propagation for this process.
  886. Arguments:
  887. Return Value:
  888. RPC_S_OK.
  889. --*/
  890. {
  891. g_fSendEEInfo = TRUE;
  892. return RPC_S_OK;
  893. }