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.

1279 lines
39 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. if (gfRPCVerifierEnabledWithBreaks)
  324. {
  325. // Locator is an unsafe feature to use. We should flag it in the verifier.
  326. RPC_VERIFIER_WARNING_MSG("Possible security threat: Client is using the locator name service",
  327. RPC_VERIFIER_UNSAFE_FEATURE);
  328. RPC_VERIFIER_PRINT_OFFENDING_STACK(1, 4);
  329. }
  330. return(BindingHandle->InquireEntryName(EntryNameSyntax, EntryName));
  331. #else
  332. return RPC_S_CANNOT_SUPPORT;
  333. #endif
  334. }
  335. RPC_STATUS RPC_ENTRY
  336. THUNK_FN(I_RpcNsBindingSetEntryName) (
  337. IN RPC_BINDING_HANDLE,
  338. IN unsigned long,
  339. IN unsigned char *
  340. )
  341. {
  342. return RPC_S_CANNOT_SUPPORT;
  343. }
  344. RPC_STATUS RPC_ENTRY
  345. I_RpcNsBindingSetEntryName (
  346. IN RPC_BINDING_HANDLE Binding,
  347. IN unsigned long EntryNameSyntax,
  348. IN unsigned short PAPI * EntryName
  349. )
  350. /*++
  351. Routine Description:
  352. This routine is a private entry point for use by name service support
  353. dlls; it allows them to set the entry name in a binding handle
  354. before returning it from import or lookup. If an entry name already
  355. exists in the binding handle, we just go ahead and overwrite the
  356. old one with new one.
  357. Arguments:
  358. Binding - Supplies the binding handle for which we want to set the
  359. entry name.
  360. EntryNameSyntax - Supplies the syntax used by the entry name. We need
  361. to save this information for when the entry name is inquired.
  362. EntryName - Supplies the entry name for this binding handle.
  363. Return Value:
  364. RPC_S_OK - The entry name has been successfully set for the binding
  365. handle.
  366. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  367. the operation.
  368. RPC_S_INVALID_BINDING - The binding argument does not specify a binding
  369. handle.
  370. RPC_S_WRONG_KIND_OF_BINDING - The binding argument does specify a
  371. binding handle, but it is not a client binding handle (ie. one
  372. owned by the client side rpc runtime).
  373. --*/
  374. {
  375. #if !defined(NO_LOCATOR_CODE)
  376. BINDING_HANDLE * BindingHandle;
  377. InitializeIfNecessary();
  378. BindingHandle = (BINDING_HANDLE *) Binding;
  379. if (BindingHandle->InvalidHandle(BINDING_HANDLE_TYPE))
  380. return(RPC_S_INVALID_BINDING);
  381. if (gfRPCVerifierEnabledWithBreaks)
  382. {
  383. // Locator is an unsafe feature to use. We should flag it in the verifier.
  384. RPC_VERIFIER_WARNING_MSG("Possible security threat: Client is using the locator name service",
  385. RPC_VERIFIER_UNSAFE_FEATURE);
  386. RPC_VERIFIER_PRINT_OFFENDING_STACK(1, 4);
  387. }
  388. return(BindingHandle->SetEntryName(EntryNameSyntax, EntryName));
  389. #else
  390. return RPC_S_CANNOT_SUPPORT;
  391. #endif
  392. }
  393. RPC_STATUS RPC_ENTRY
  394. RpcBindingInqAuthInfo (
  395. IN RPC_BINDING_HANDLE Binding,
  396. OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
  397. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  398. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  399. OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
  400. OUT unsigned long PAPI * AuthzSvc OPTIONAL
  401. )
  402. /*++
  403. Routine Description:
  404. This routine is used to return the authentication and authorization for
  405. a binding handle. You should also see RpcBindingSetAuthInfoW.
  406. Arguments:
  407. Binding - Supplies the binding handle for which we wish to query the
  408. authentication and authorization information.
  409. ServerPrincName - Optionally returns the server principal name set for
  410. the binding handle.
  411. AuthnLevel - Optionally returns the authentication level set for the
  412. binding handle.
  413. AuthnSvc - Optionally returns the authentication service set for the
  414. binding handle.
  415. AuthIdentity - Optionally returns a handle to the security context
  416. being used for authentication and authorization.
  417. AuthzSvc - Optionally returns the authorization service set for the
  418. binding handle.
  419. Return Value:
  420. RPC_S_OK - We successfully returned the information requested.
  421. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  422. the operation.
  423. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  424. not a valid binding handle.
  425. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  426. be specified as the binding argument.
  427. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been
  428. called on the binding handle, so there is not authentication or
  429. authorization to be returned.
  430. --*/
  431. {
  432. BINDING_HANDLE * BindingObject;
  433. CLIENT_AUTH_INFO * ClientAuthInfo;
  434. InitializeIfNecessary();
  435. return( RpcBindingInqAuthInfoEx(
  436. Binding,
  437. ServerPrincName,
  438. AuthnLevel,
  439. AuthnSvc,
  440. AuthIdentity,
  441. AuthzSvc,
  442. 0,
  443. 0
  444. ) );
  445. }
  446. RPC_STATUS RPC_ENTRY
  447. RpcBindingInqAuthInfoEx (
  448. IN RPC_BINDING_HANDLE Binding,
  449. OUT unsigned short PAPI * PAPI * ServerPrincName, OPTIONAL
  450. OUT unsigned long PAPI * AuthnLevel, OPTIONAL
  451. OUT unsigned long PAPI * AuthnSvc, OPTIONAL
  452. OUT RPC_AUTH_IDENTITY_HANDLE PAPI * AuthIdentity, OPTIONAL
  453. OUT unsigned long PAPI * AuthzSvc, OPTIONAL
  454. IN unsigned long RpcSecurityQosVersion,
  455. OUT RPC_SECURITY_QOS * SecurityQos
  456. )
  457. /*++
  458. Routine Description:
  459. This routine is used to return the authentication and authorization for
  460. a binding handle. You should also see RpcBindingSetAuthInfoW.
  461. Arguments:
  462. Binding - Supplies the binding handle for which we wish to query the
  463. authentication and authorization information.
  464. ServerPrincName - Optionally returns the server principal name set for
  465. the binding handle.
  466. AuthnLevel - Optionally returns the authentication level set for the
  467. binding handle.
  468. AuthnSvc - Optionally returns the authentication service set for the
  469. binding handle.
  470. AuthIdentity - Optionally returns a handle to the security context
  471. being used for authentication and authorization.
  472. AuthzSvc - Optionally returns the authorization service set for the
  473. binding handle.
  474. RpcSecurityQosVersion - Indicates a version for RPC_SECURITY_QOS structure,
  475. that optionally can be inquired. If SecurityQOS passes in is 0, this
  476. is ignored.
  477. SecurityQOS - is the version of the Security Quality Of Service
  478. Return Value:
  479. RPC_S_OK - We successfully returned the information requested.
  480. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete
  481. the operation.
  482. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  483. not a valid binding handle.
  484. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  485. be specified as the binding argument.
  486. RPC_S_BINDING_HAS_NO_AUTH - RpcBindingInqAuthInfo has not yet been
  487. called on the binding handle, so there is not authentication or
  488. authorization to be returned.
  489. --*/
  490. {
  491. BINDING_HANDLE * BindingObject;
  492. CLIENT_AUTH_INFO * ClientAuthInfo;
  493. InitializeIfNecessary();
  494. BindingObject = (BINDING_HANDLE *) Binding;
  495. if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) )
  496. {
  497. return(RPC_S_INVALID_BINDING);
  498. }
  499. ClientAuthInfo = BindingObject->InquireAuthInformation();
  500. if ( ClientAuthInfo == 0
  501. || ClientAuthInfo->AuthenticationLevel == RPC_C_AUTHN_LEVEL_NONE)
  502. {
  503. return(RPC_S_BINDING_HAS_NO_AUTH);
  504. }
  505. if (ARGUMENT_PRESENT(AuthnLevel))
  506. {
  507. *AuthnLevel = ClientAuthInfo->AuthenticationLevel;
  508. }
  509. if (ARGUMENT_PRESENT(AuthnSvc))
  510. {
  511. *AuthnSvc = ClientAuthInfo->AuthenticationService;
  512. }
  513. if (ARGUMENT_PRESENT(AuthIdentity))
  514. {
  515. *AuthIdentity = ClientAuthInfo->AuthIdentity;
  516. }
  517. if (ARGUMENT_PRESENT(AuthzSvc))
  518. {
  519. *AuthzSvc = ClientAuthInfo->AuthorizationService;
  520. }
  521. if (ARGUMENT_PRESENT(ServerPrincName))
  522. {
  523. if ( ClientAuthInfo->ServerPrincipalName == 0 )
  524. {
  525. *ServerPrincName = 0;
  526. }
  527. else
  528. {
  529. *ServerPrincName = DuplicateStringPAPI(
  530. ClientAuthInfo->ServerPrincipalName);
  531. if ( *ServerPrincName == 0 )
  532. {
  533. return(RPC_S_OUT_OF_MEMORY);
  534. }
  535. }
  536. }
  537. if (ARGUMENT_PRESENT(SecurityQos))
  538. {
  539. if (RpcSecurityQosVersion != RPC_C_SECURITY_QOS_VERSION)
  540. {
  541. if (ARGUMENT_PRESENT(ServerPrincName))
  542. delete *ServerPrincName;
  543. return (RPC_S_INVALID_ARG);
  544. }
  545. SecurityQos->Version = RPC_C_SECURITY_QOS_VERSION;
  546. SecurityQos->Capabilities = ClientAuthInfo->Capabilities;
  547. SecurityQos->ImpersonationType = ClientAuthInfo->ImpersonationType;
  548. SecurityQos->IdentityTracking = ClientAuthInfo->IdentityTracking;
  549. }
  550. return(RPC_S_OK);
  551. }
  552. RPC_STATUS RPC_ENTRY
  553. RpcBindingSetAuthInfo (
  554. IN RPC_BINDING_HANDLE Binding,
  555. IN unsigned short PAPI * ServerPrincName,
  556. IN unsigned long AuthnLevel,
  557. IN unsigned long AuthnSvc,
  558. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  559. IN unsigned long AuthzSvc
  560. )
  561. /*++
  562. Routine Description:
  563. A client application will use this routine to specify the authentication
  564. and authorization information in a binding handle, so that the binding
  565. handle can be used to make authenticated remote procedure calls. If
  566. the this routine is not used, then all remote procedure calls on the
  567. binding handle will be unauthenticated.
  568. Arguments:
  569. Binding - Supplies binding handle for which we want to set authentication
  570. and authorization information.
  571. ServerPrincName - Supplies the expected principal name of the server
  572. referenced by the binding handle (that is supplied as the binding
  573. argument). This information is necessary for some security services
  574. to be able to authenticate with the server.
  575. AuthnLevel - Supplies a value indicating the amount (or level) of
  576. authentication to be performed on remote procedure calls using
  577. the binding handle. If we do not support the requested level,
  578. we will upgrade to the next highest supported level.
  579. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for
  580. authentication service being used should be used.
  581. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication.
  582. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only
  583. when the client first talks to the server.
  584. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will
  585. use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols,
  586. authentication will be performed at the beginning of each
  587. remote procedure call.
  588. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that
  589. the data it is received from the expected client.
  590. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that
  591. the data is from the expected client, we will verify that none
  592. of it has been modified.
  593. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the
  594. support in packet integrity, as well as encrypting all remote
  595. procedure call data.
  596. AuthnSvc - Supplies the authentication service to use.
  597. AuthIdentify - Optionally supplies authentication and authorization
  598. credentials to use; if this argument is not specified, the security
  599. context for the current address space will be used.
  600. AuthzSvc - Supplies the authorization service being used by the
  601. server. The client must know this so that the correct authorization
  602. information can be sent to the server.
  603. Return Value:
  604. RPC_S_OK - The supplied authentication and authorization information has
  605. been set in the binding handle.
  606. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  607. operation.
  608. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  609. not a valid binding handle.
  610. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  611. be specified as the binding argument.
  612. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  613. not supported.
  614. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is
  615. not supported.
  616. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied
  617. by the auth identity argument) is invalid.
  618. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is
  619. not supported.
  620. --*/
  621. {
  622. return ( RpcBindingSetAuthInfoEx(
  623. Binding,
  624. ServerPrincName,
  625. AuthnLevel,
  626. AuthnSvc,
  627. AuthIdentity,
  628. AuthzSvc,
  629. 0 ) );
  630. }
  631. RPC_STATUS RPC_ENTRY
  632. RpcBindingSetAuthInfoEx (
  633. IN RPC_BINDING_HANDLE Binding,
  634. IN unsigned short PAPI * ServerPrincName,
  635. IN unsigned long AuthnLevel,
  636. IN unsigned long AuthnSvc,
  637. IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL
  638. IN unsigned long AuthzSvc,
  639. IN RPC_SECURITY_QOS *SecurityQOS
  640. )
  641. /*++
  642. Routine Description:
  643. A client application will use this routine to specify the authentication
  644. and authorization information in a binding handle, so that the binding
  645. handle can be used to make authenticated remote procedure calls. If
  646. the this routine is not used, then all remote procedure calls on the
  647. binding handle will be unauthenticated.
  648. Arguments:
  649. Binding - Supplies binding handle for which we want to set authentication
  650. and authorization information.
  651. ServerPrincName - Supplies the expected principal name of the server
  652. referenced by the binding handle (that is supplied as the binding
  653. argument). This information is necessary for some security services
  654. to be able to authenticate with the server.
  655. AuthnLevel - Supplies a value indicating the amount (or level) of
  656. authentication to be performed on remote procedure calls using
  657. the binding handle. If we do not support the requested level,
  658. we will upgrade to the next highest supported level.
  659. RPC_C_AUTHN_LEVEL_DEFAULT - Indicates that the default level for
  660. authentication service being used should be used.
  661. RPC_C_AUTHN_LEVEL_NONE - Do not perform any authentication.
  662. RPC_C_AUTHN_LEVEL_CONNECT - Authentication will be performed only
  663. when the client first talks to the server.
  664. RPC_C_AUTHN_LEVEL_CALL - For connection based protocols, we will
  665. use RPC_C_AUTHN_LEVEL_PKT instead; for datagram based protocols,
  666. authentication will be performed at the beginning of each
  667. remote procedure call.
  668. RPC_C_AUTHN_LEVEL_PKT - All data will be authenticated to insure that
  669. the data it is received from the expected client.
  670. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY - In addition, to authenticating that
  671. the data is from the expected client, we will verify that none
  672. of it has been modified.
  673. RPC_C_AUTHN_LEVEL_PKT_PRIVACY - Finally, this includes all of the
  674. support in packet integrity, as well as encrypting all remote
  675. procedure call data.
  676. AuthnSvc - Supplies the authentication service to use.
  677. AuthIdentify - Optionally supplies authentication and authorization
  678. credentials to use; if this argument is not specified, the security
  679. context for the current address space will be used.
  680. AuthzSvc - Supplies the authorization service being used by the
  681. server. The client must know this so that the correct authorization
  682. information can be sent to the server.
  683. SecurityQOS - a security QOS stucture. Currently accepting RPC_C_SECURITY_QOS_VERSION_2
  684. and RPC_C_SECURITY_QOS_VERSION_1
  685. Return Value:
  686. RPC_S_OK - The supplied authentication and authorization information has
  687. been set in the binding handle.
  688. RPC_S_OUT_OF_MEMORY - Insufficient memory is available to complete the
  689. operation.
  690. RPC_S_INVALID_BINDING - The value supplied as the binding argument is
  691. not a valid binding handle.
  692. RPC_S_WRONG_KIND_OF_BINDING - A binding handle on the client side must
  693. be specified as the binding argument.
  694. RPC_S_UNKNOWN_AUTHN_SERVICE - The specified authentication service is
  695. not supported.
  696. RPC_S_UNKNOWN_AUTHN_LEVEL - The specified authentication level is
  697. not supported.
  698. RPC_S_INVALID_AUTH_IDENTITY - The specified security context (supplied
  699. by the auth identity argument) is invalid.
  700. RPC_S_UNKNOWN_AUTHZ_SERVICE - The specified authorization service is
  701. not supported.
  702. --*/
  703. {
  704. BINDING_HANDLE * BindingObject;
  705. RPC_STATUS Status;
  706. RPC_CHAR __RPC_FAR * ServerName;
  707. unsigned long ImpersonationType;
  708. unsigned long IdentityTracking;
  709. unsigned long Capabilities;
  710. void *AdditionalCredentials;
  711. ULONG AdditionalTransportCredentialsType;
  712. THREAD *Thread;
  713. RPC_HTTP_TRANSPORT_CREDENTIALS_W *HttpCredentials;
  714. unsigned int i;
  715. PSID Sid;
  716. InitializeIfNecessary();
  717. Thread = ThreadSelf();
  718. if (Thread)
  719. {
  720. RpcpPurgeEEInfoFromThreadIfNecessary(Thread);
  721. }
  722. BindingObject = (BINDING_HANDLE *) Binding;
  723. if ((SecurityQOS != 0) &&
  724. ( (SecurityQOS->Version < RPC_C_SECURITY_QOS_VERSION_1) ||
  725. (SecurityQOS->Version > RPC_C_SECURITY_QOS_VERSION_3) ) )
  726. {
  727. return(RPC_S_INVALID_ARG);
  728. }
  729. if ( BindingObject->InvalidHandle(BINDING_HANDLE_TYPE) )
  730. {
  731. return(RPC_S_INVALID_BINDING);
  732. }
  733. //
  734. // For no authentication, bail out now.
  735. //
  736. if (AuthnSvc == RPC_C_AUTHN_NONE)
  737. {
  738. if ((AuthnLevel != RPC_C_AUTHN_LEVEL_NONE) &&
  739. (AuthnLevel != RPC_C_AUTHN_LEVEL_DEFAULT))
  740. {
  741. return(RPC_S_UNKNOWN_AUTHN_LEVEL);
  742. }
  743. // fall through - we will set all defaults
  744. }
  745. if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
  746. {
  747. RpcpGetDefaultSecurityProviderInfo();
  748. AuthnSvc = DefaultProviderId;
  749. }
  750. if (AuthnSvc == RPC_C_AUTHN_GSS_SCHANNEL)
  751. {
  752. if (AuthnLevel < RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
  753. {
  754. AuthnLevel = RPC_C_AUTHN_LEVEL_PKT_PRIVACY;
  755. }
  756. }
  757. Sid = NULL;
  758. if (SecurityQOS != 0)
  759. {
  760. IdentityTracking = SecurityQOS->IdentityTracking;
  761. ImpersonationType= SecurityQOS->ImpersonationType;
  762. Capabilities = SecurityQOS->Capabilities;
  763. // if we were given the hint for lightweight local MA,
  764. // we must have been told to use MA in the first place
  765. if (Capabilities & RPC_C_QOS_CAPABILITIES_LOCAL_MA_HINT)
  766. {
  767. if ((Capabilities & RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH) == 0)
  768. return RPC_S_INVALID_ARG;
  769. // doesn't work for datagrams
  770. if (((BINDING_HANDLE *)Binding)->InvalidHandle(DG_BINDING_HANDLE_TYPE) == FALSE)
  771. return RPC_S_INVALID_ARG;
  772. }
  773. // by the condition above, we know we can't have the local MA hint only -
  774. // if we have local MA hint, we must have full MA also. Thus we can check
  775. // for full MA only and effectively address both
  776. if (Capabilities & RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH)
  777. {
  778. // if we were asked for full MA, either SID of SPN must be supplied
  779. if (((ServerPrincName == NULL)
  780. ||
  781. (ServerPrincName[0] == '\0') )
  782. &&
  783. (
  784. (SecurityQOS->Version < RPC_C_SECURITY_QOS_VERSION_3)
  785. ||
  786. (((RPC_SECURITY_QOS_V3 *)SecurityQOS)->Sid == NULL)
  787. )
  788. )
  789. {
  790. #if DBG
  791. DbgPrint("RPCRT4: %X: Rejecting invalid arguments to RpcBindingSetAuthInfoEx\n",
  792. GetCurrentProcessId());
  793. #endif
  794. return RPC_S_INVALID_ARG;
  795. }
  796. }
  797. if (SecurityQOS->Version == RPC_C_SECURITY_QOS_VERSION_1)
  798. {
  799. AdditionalTransportCredentialsType = 0;
  800. AdditionalCredentials = NULL;
  801. }
  802. else
  803. {
  804. AdditionalTransportCredentialsType = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->AdditionalSecurityInfoType;
  805. AdditionalCredentials = ((RPC_SECURITY_QOS_V2 *)SecurityQOS)->u.HttpCredentials;
  806. if (AdditionalTransportCredentialsType != RPC_C_AUTHN_INFO_TYPE_HTTP)
  807. {
  808. if (AdditionalTransportCredentialsType != 0)
  809. return(RPC_S_INVALID_ARG);
  810. if (AdditionalCredentials != NULL)
  811. return(RPC_S_INVALID_ARG);
  812. }
  813. else if (AdditionalCredentials == NULL)
  814. return(RPC_S_INVALID_ARG);
  815. else
  816. {
  817. HttpCredentials = (RPC_HTTP_TRANSPORT_CREDENTIALS_W *)AdditionalCredentials;
  818. if (HttpCredentials->TransportCredentials)
  819. {
  820. if (HttpCredentials->TransportCredentials->User)
  821. {
  822. if (RpcpStringLength(HttpCredentials->TransportCredentials->User)
  823. != HttpCredentials->TransportCredentials->UserLength)
  824. {
  825. return(RPC_S_INVALID_ARG);
  826. }
  827. }
  828. else if (HttpCredentials->TransportCredentials->UserLength)
  829. return(RPC_S_INVALID_ARG);
  830. if (HttpCredentials->TransportCredentials->Domain)
  831. {
  832. if (RpcpStringLength(HttpCredentials->TransportCredentials->Domain)
  833. != HttpCredentials->TransportCredentials->DomainLength)
  834. {
  835. return(RPC_S_INVALID_ARG);
  836. }
  837. }
  838. else if (HttpCredentials->TransportCredentials->DomainLength)
  839. return(RPC_S_INVALID_ARG);
  840. if (HttpCredentials->TransportCredentials->Password)
  841. {
  842. if (RpcpStringLength(HttpCredentials->TransportCredentials->Password)
  843. != HttpCredentials->TransportCredentials->PasswordLength)
  844. {
  845. return(RPC_S_INVALID_ARG);
  846. }
  847. }
  848. else if (HttpCredentials->TransportCredentials->PasswordLength)
  849. return(RPC_S_INVALID_ARG);
  850. if (HttpCredentials->TransportCredentials->Flags != SEC_WINNT_AUTH_IDENTITY_UNICODE)
  851. return(RPC_S_INVALID_ARG);
  852. }
  853. // if you don't want to authenticate against anyone, you can't authenticate
  854. if (HttpCredentials->AuthenticationTarget == 0)
  855. return(RPC_S_INVALID_ARG);
  856. // if you don't support any method of authentication, you can't authenticate
  857. if (HttpCredentials->NumberOfAuthnSchemes == 0)
  858. return(RPC_S_INVALID_ARG);
  859. // if you don't support any method of authentication, you can't authenticate
  860. if (HttpCredentials->AuthnSchemes == NULL)
  861. return(RPC_S_INVALID_ARG);
  862. // check whether Negotiate, Passport or Digest are in the list of auth scehemes. If yes,
  863. // reject the call since we don't support them yet.
  864. for (i = 0; i < HttpCredentials->NumberOfAuthnSchemes; i ++)
  865. {
  866. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_PASSPORT)
  867. return RPC_S_CANNOT_SUPPORT;
  868. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_NEGOTIATE)
  869. return RPC_S_CANNOT_SUPPORT;
  870. if (HttpCredentials->AuthnSchemes[i] == RPC_C_HTTP_AUTHN_SCHEME_DIGEST)
  871. return RPC_S_CANNOT_SUPPORT;
  872. }
  873. }
  874. if (SecurityQOS->Version == RPC_C_SECURITY_QOS_VERSION_3)
  875. {
  876. // doesn't work for datagrams
  877. if ((((BINDING_HANDLE *)Binding)->InvalidHandle(DG_BINDING_HANDLE_TYPE) == FALSE)
  878. && ((RPC_SECURITY_QOS_V3 *)SecurityQOS)->Sid)
  879. return RPC_S_INVALID_ARG;
  880. Sid = ((RPC_SECURITY_QOS_V3 *)SecurityQOS)->Sid;
  881. }
  882. }
  883. }
  884. else
  885. {
  886. IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
  887. ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE;
  888. Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
  889. AdditionalTransportCredentialsType = 0;
  890. AdditionalCredentials = NULL;
  891. }
  892. if (AuthnSvc == RPC_C_AUTHN_NONE)
  893. {
  894. Status = BindingObject->SetAuthInformation(
  895. ServerPrincName,
  896. AuthnLevel,
  897. AuthnSvc,
  898. AuthIdentity,
  899. AuthzSvc,
  900. 0,
  901. ImpersonationType,
  902. IdentityTracking,
  903. Capabilities,
  904. FALSE, // Acquire new credentials
  905. AdditionalTransportCredentialsType,
  906. AdditionalCredentials,
  907. Sid
  908. );
  909. }
  910. else
  911. {
  912. Status = BindingObject->SetAuthInformation(
  913. ServerPrincName,
  914. AuthnLevel,
  915. AuthnSvc,
  916. AuthIdentity,
  917. AuthzSvc,
  918. 0,
  919. ImpersonationType,
  920. IdentityTracking,
  921. Capabilities,
  922. TRUE, // Acquire new credentials
  923. AdditionalTransportCredentialsType,
  924. AdditionalCredentials,
  925. Sid
  926. );
  927. }
  928. return (Status);
  929. }
  930. RPC_STATUS RPC_ENTRY
  931. I_RpcBindingInqSecurityContext (
  932. IN RPC_BINDING_HANDLE Binding,
  933. OUT void **SecurityContextHandle
  934. )
  935. /*++
  936. Routine Description:
  937. Arguments:
  938. Return Value:
  939. The status for the operation is returned.
  940. --*/
  941. {
  942. CALL * Call;
  943. InitializeIfNecessary();
  944. Call = (CALL *) Binding;
  945. if (Call->InvalidHandle(CALL_TYPE))
  946. return(RPC_S_INVALID_BINDING);
  947. return(Call->InqSecurityContext(SecurityContextHandle));
  948. }
  949. RPC_STATUS RPC_ENTRY
  950. I_RpcTurnOnEEInfoPropagation (
  951. void
  952. )
  953. /*++
  954. Routine Description:
  955. Turns on extended error info propagation for this process.
  956. Arguments:
  957. Return Value:
  958. RPC_S_OK.
  959. --*/
  960. {
  961. g_fSendEEInfo = TRUE;
  962. return RPC_S_OK;
  963. }