AcceleratedTokenProvider.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.ObjectModel;
  7. using System.IdentityModel.Policy;
  8. using System.IdentityModel.Tokens;
  9. using System.Runtime;
  10. using System.ServiceModel;
  11. using System.ServiceModel.Channels;
  12. using System.ServiceModel.Description;
  13. using System.ServiceModel.Diagnostics;
  14. using System.Xml;
  15. using SafeFreeCredentials = System.IdentityModel.SafeFreeCredentials;
  16. class AcceleratedTokenProvider :
  17. NegotiationTokenProvider<AcceleratedTokenProviderState>
  18. {
  19. internal const SecurityKeyEntropyMode defaultKeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
  20. SecurityKeyEntropyMode keyEntropyMode = defaultKeyEntropyMode;
  21. SecurityBindingElement bootstrapSecurityBindingElement;
  22. Uri privacyNoticeUri;
  23. int privacyNoticeVersion;
  24. ChannelParameterCollection channelParameters;
  25. SafeFreeCredentials credentialsHandle;
  26. bool ownCredentialsHandle;
  27. public AcceleratedTokenProvider(SafeFreeCredentials credentialsHandle)
  28. : base()
  29. {
  30. this.credentialsHandle = credentialsHandle;
  31. }
  32. public SecurityKeyEntropyMode KeyEntropyMode
  33. {
  34. get
  35. {
  36. return this.keyEntropyMode;
  37. }
  38. set
  39. {
  40. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  41. SecurityKeyEntropyModeHelper.Validate(value);
  42. this.keyEntropyMode = value;
  43. }
  44. }
  45. public SecurityBindingElement BootstrapSecurityBindingElement
  46. {
  47. get { return this.bootstrapSecurityBindingElement; }
  48. set
  49. {
  50. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  51. if (value == null)
  52. {
  53. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  54. }
  55. this.bootstrapSecurityBindingElement = (SecurityBindingElement) value.Clone();
  56. }
  57. }
  58. public Uri PrivacyNoticeUri
  59. {
  60. get { return this.privacyNoticeUri; }
  61. set
  62. {
  63. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  64. this.privacyNoticeUri = value;
  65. }
  66. }
  67. public int PrivacyNoticeVersion
  68. {
  69. get { return this.privacyNoticeVersion; }
  70. set
  71. {
  72. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  73. this.privacyNoticeVersion = value;
  74. }
  75. }
  76. public ChannelParameterCollection ChannelParameters
  77. {
  78. get { return this.channelParameters; }
  79. set
  80. {
  81. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  82. this.channelParameters = value;
  83. }
  84. }
  85. // SC/Trust workshop change to turn off context
  86. protected override bool IsMultiLegNegotiation
  87. {
  88. get { return false; }
  89. }
  90. public override XmlDictionaryString RequestSecurityTokenAction
  91. {
  92. get
  93. {
  94. return this.StandardsManager.SecureConversationDriver.IssueAction;
  95. }
  96. }
  97. public override XmlDictionaryString RequestSecurityTokenResponseAction
  98. {
  99. get
  100. {
  101. return this.StandardsManager.SecureConversationDriver.IssueResponseAction;
  102. }
  103. }
  104. public override void OnOpen(TimeSpan timeout)
  105. {
  106. if (this.BootstrapSecurityBindingElement == null)
  107. {
  108. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BootstrapSecurityBindingElementNotSet, this.GetType())));
  109. }
  110. base.OnOpen(timeout);
  111. }
  112. public override void OnOpening()
  113. {
  114. base.OnOpening();
  115. if (this.credentialsHandle == null)
  116. {
  117. if (this.BootstrapSecurityBindingElement == null)
  118. {
  119. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.BootstrapSecurityBindingElementNotSet, this.GetType())));
  120. }
  121. this.credentialsHandle = SecurityUtils.GetCredentialsHandle(this.BootstrapSecurityBindingElement, this.IssuerBindingContext);
  122. this.ownCredentialsHandle = true;
  123. }
  124. }
  125. public override void OnClose(TimeSpan timeout)
  126. {
  127. base.OnClose(timeout);
  128. FreeCredentialsHandle();
  129. }
  130. public override void OnAbort()
  131. {
  132. base.OnAbort();
  133. FreeCredentialsHandle();
  134. }
  135. void FreeCredentialsHandle()
  136. {
  137. if (this.credentialsHandle != null)
  138. {
  139. if (this.ownCredentialsHandle)
  140. {
  141. this.credentialsHandle.Close();
  142. }
  143. this.credentialsHandle = null;
  144. }
  145. }
  146. protected override IChannelFactory<IRequestChannel> GetNegotiationChannelFactory(IChannelFactory<IRequestChannel> transportChannelFactory, ChannelBuilder channelBuilder)
  147. {
  148. ISecurityCapabilities securityCapabilities = this.bootstrapSecurityBindingElement.GetProperty<ISecurityCapabilities>(this.IssuerBindingContext);
  149. SecurityCredentialsManager securityCredentials = this.IssuerBindingContext.BindingParameters.Find<SecurityCredentialsManager>();
  150. if (securityCredentials == null)
  151. {
  152. securityCredentials = ClientCredentials.CreateDefaultCredentials();
  153. }
  154. this.bootstrapSecurityBindingElement.ReaderQuotas = this.IssuerBindingContext.GetInnerProperty<XmlDictionaryReaderQuotas>();
  155. if (this.bootstrapSecurityBindingElement.ReaderQuotas == null)
  156. {
  157. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EncodingBindingElementDoesNotHandleReaderQuotas)));
  158. }
  159. TransportBindingElement transportBindingElement = this.IssuerBindingContext.RemainingBindingElements.Find<TransportBindingElement>();
  160. if (transportBindingElement != null)
  161. this.bootstrapSecurityBindingElement.MaxReceivedMessageSize = transportBindingElement.MaxReceivedMessageSize;
  162. SecurityProtocolFactory securityProtocolFactory = this.bootstrapSecurityBindingElement.CreateSecurityProtocolFactory<IRequestChannel>(this.IssuerBindingContext.Clone(), securityCredentials, false, this.IssuerBindingContext.Clone());
  163. MessageSecurityProtocolFactory soapBindingFactory = (securityProtocolFactory as MessageSecurityProtocolFactory);
  164. if (soapBindingFactory != null)
  165. {
  166. soapBindingFactory.ApplyConfidentiality = soapBindingFactory.ApplyIntegrity
  167. = soapBindingFactory.RequireConfidentiality = soapBindingFactory.RequireIntegrity = true;
  168. MessagePartSpecification bodyPart = new MessagePartSpecification(true);
  169. soapBindingFactory.ProtectionRequirements.IncomingSignatureParts.AddParts(bodyPart, RequestSecurityTokenAction);
  170. soapBindingFactory.ProtectionRequirements.IncomingEncryptionParts.AddParts(bodyPart, RequestSecurityTokenAction);
  171. soapBindingFactory.ProtectionRequirements.OutgoingSignatureParts.AddParts(bodyPart, RequestSecurityTokenResponseAction);
  172. soapBindingFactory.ProtectionRequirements.OutgoingEncryptionParts.AddParts(bodyPart, RequestSecurityTokenResponseAction);
  173. }
  174. securityProtocolFactory.PrivacyNoticeUri = this.PrivacyNoticeUri;
  175. securityProtocolFactory.PrivacyNoticeVersion = this.PrivacyNoticeVersion;
  176. return new SecurityChannelFactory<IRequestChannel>(
  177. securityCapabilities, this.IssuerBindingContext, channelBuilder, securityProtocolFactory, transportChannelFactory);
  178. }
  179. protected override IRequestChannel CreateClientChannel(EndpointAddress target, Uri via)
  180. {
  181. IRequestChannel result = base.CreateClientChannel(target, via);
  182. if (this.channelParameters != null)
  183. {
  184. this.channelParameters.PropagateChannelParameters(result);
  185. }
  186. if (this.ownCredentialsHandle)
  187. {
  188. ChannelParameterCollection newParameters = result.GetProperty<ChannelParameterCollection>();
  189. if (newParameters != null)
  190. {
  191. newParameters.Add(new SspiIssuanceChannelParameter(true, this.credentialsHandle));
  192. }
  193. }
  194. return result;
  195. }
  196. protected override bool CreateNegotiationStateCompletesSynchronously(EndpointAddress target, Uri via)
  197. {
  198. return true;
  199. }
  200. protected override AcceleratedTokenProviderState CreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout)
  201. {
  202. byte[] keyEntropy;
  203. if (this.keyEntropyMode == SecurityKeyEntropyMode.ClientEntropy || this.keyEntropyMode == SecurityKeyEntropyMode.CombinedEntropy)
  204. {
  205. keyEntropy = new byte[this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength / 8];
  206. CryptoHelper.FillRandomBytes(keyEntropy);
  207. }
  208. else
  209. {
  210. keyEntropy = null;
  211. }
  212. return new AcceleratedTokenProviderState(keyEntropy);
  213. }
  214. protected override IAsyncResult BeginCreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout, AsyncCallback callback, object state)
  215. {
  216. return new CompletedAsyncResult<AcceleratedTokenProviderState>(CreateNegotiationState(target, via, timeout), callback, state);
  217. }
  218. protected override AcceleratedTokenProviderState EndCreateNegotiationState(IAsyncResult result)
  219. {
  220. return CompletedAsyncResult<AcceleratedTokenProviderState>.End(result);
  221. }
  222. protected override BodyWriter GetFirstOutgoingMessageBody(AcceleratedTokenProviderState negotiationState, out MessageProperties messageProperties)
  223. {
  224. messageProperties = null;
  225. RequestSecurityToken rst = new RequestSecurityToken(this.StandardsManager);
  226. rst.Context = negotiationState.Context;
  227. rst.KeySize = this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength;
  228. rst.TokenType = this.SecurityContextTokenUri;
  229. byte[] requestorEntropy = negotiationState.GetRequestorEntropy();
  230. if (requestorEntropy != null)
  231. {
  232. rst.SetRequestorEntropy(requestorEntropy);
  233. }
  234. rst.MakeReadOnly();
  235. return rst;
  236. }
  237. protected override BodyWriter GetNextOutgoingMessageBody(Message incomingMessage, AcceleratedTokenProviderState negotiationState)
  238. {
  239. ThrowIfFault(incomingMessage, this.TargetAddress);
  240. if (incomingMessage.Headers.Action != RequestSecurityTokenResponseAction.Value)
  241. {
  242. throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidActionForNegotiationMessage, incomingMessage.Headers.Action)), incomingMessage);
  243. }
  244. // get the claims corresponding to the server
  245. SecurityMessageProperty serverContextProperty = incomingMessage.Properties.Security;
  246. ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies;
  247. if (serverContextProperty != null && serverContextProperty.ServiceSecurityContext != null)
  248. {
  249. authorizationPolicies = serverContextProperty.ServiceSecurityContext.AuthorizationPolicies;
  250. }
  251. else
  252. {
  253. authorizationPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  254. }
  255. RequestSecurityTokenResponse rstr = null;
  256. XmlDictionaryReader bodyReader = incomingMessage.GetReaderAtBodyContents();
  257. using (bodyReader)
  258. {
  259. if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrustFeb2005)
  260. rstr = RequestSecurityTokenResponse.CreateFrom(this.StandardsManager, bodyReader);
  261. else if (this.StandardsManager.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrust13)
  262. {
  263. RequestSecurityTokenResponseCollection rstrc = this.StandardsManager.TrustDriver.CreateRequestSecurityTokenResponseCollection(bodyReader);
  264. foreach (RequestSecurityTokenResponse rstrItem in rstrc.RstrCollection)
  265. {
  266. if (rstr != null)
  267. {
  268. // More than one RSTR is found. So throw an exception.
  269. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.MoreThanOneRSTRInRSTRC)));
  270. }
  271. rstr = rstrItem;
  272. }
  273. }
  274. else
  275. {
  276. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  277. }
  278. incomingMessage.ReadFromBodyContentsToEnd(bodyReader);
  279. }
  280. if (rstr.Context != negotiationState.Context)
  281. {
  282. throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.BadSecurityNegotiationContext)), incomingMessage);
  283. }
  284. byte[] keyEntropy = negotiationState.GetRequestorEntropy();
  285. GenericXmlSecurityToken serviceToken = rstr.GetIssuedToken(null, null, this.keyEntropyMode, keyEntropy, this.SecurityContextTokenUri, authorizationPolicies, this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength, false);
  286. negotiationState.SetServiceToken(serviceToken);
  287. return null;
  288. }
  289. }
  290. }