AcceleratedTokenAuthenticator.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //-----------------------------------------------------------------------------
  4. namespace System.ServiceModel.Security
  5. {
  6. using System.Collections.Generic;
  7. using System.Collections.ObjectModel;
  8. using System.IdentityModel.Policy;
  9. using System.IdentityModel.Tokens;
  10. using System.Runtime;
  11. using System.Runtime.Serialization;
  12. using System.ServiceModel;
  13. using System.ServiceModel.Channels;
  14. using System.ServiceModel.Description;
  15. using System.ServiceModel.Diagnostics;
  16. using System.ServiceModel.Dispatcher;
  17. using System.ServiceModel.Security.Tokens;
  18. using System.Xml;
  19. sealed class AcceleratedTokenAuthenticator : NegotiationTokenAuthenticator<NegotiationTokenAuthenticatorState>
  20. {
  21. SecurityBindingElement bootstrapSecurityBindingElement;
  22. SecurityKeyEntropyMode keyEntropyMode;
  23. bool shouldMatchRstWithEndpointFilter;
  24. bool preserveBootstrapTokens;
  25. public AcceleratedTokenAuthenticator()
  26. : base()
  27. {
  28. keyEntropyMode = AcceleratedTokenProvider.defaultKeyEntropyMode;
  29. }
  30. public bool PreserveBootstrapTokens
  31. {
  32. get
  33. {
  34. return this.preserveBootstrapTokens;
  35. }
  36. set
  37. {
  38. this.preserveBootstrapTokens = value;
  39. }
  40. }
  41. public override XmlDictionaryString RequestSecurityTokenAction
  42. {
  43. get
  44. {
  45. return this.StandardsManager.SecureConversationDriver.IssueAction;
  46. }
  47. }
  48. public override XmlDictionaryString RequestSecurityTokenResponseAction
  49. {
  50. get
  51. {
  52. return this.StandardsManager.SecureConversationDriver.IssueResponseAction;
  53. }
  54. }
  55. public override XmlDictionaryString RequestSecurityTokenResponseFinalAction
  56. {
  57. get
  58. {
  59. return this.StandardsManager.SecureConversationDriver.IssueResponseAction;
  60. }
  61. }
  62. public SecurityBindingElement BootstrapSecurityBindingElement
  63. {
  64. get { return this.bootstrapSecurityBindingElement; }
  65. set
  66. {
  67. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  68. if (value == null)
  69. {
  70. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
  71. }
  72. this.bootstrapSecurityBindingElement = (SecurityBindingElement)value.Clone();
  73. }
  74. }
  75. public SecurityKeyEntropyMode KeyEntropyMode
  76. {
  77. get
  78. {
  79. return this.keyEntropyMode;
  80. }
  81. set
  82. {
  83. this.CommunicationObject.ThrowIfDisposedOrImmutable();
  84. SecurityKeyEntropyModeHelper.Validate(value);
  85. this.keyEntropyMode = value;
  86. }
  87. }
  88. protected override bool IsMultiLegNegotiation
  89. {
  90. get
  91. {
  92. return false;
  93. }
  94. }
  95. protected override MessageFilter GetListenerFilter()
  96. {
  97. return new RstDirectFilter(this.StandardsManager, this);
  98. }
  99. protected override Binding GetNegotiationBinding(Binding binding)
  100. {
  101. CustomBinding customBinding = new CustomBinding(binding);
  102. customBinding.Elements.Insert(0, new AcceleratedTokenAuthenticatorBindingElement(this));
  103. return customBinding;
  104. }
  105. internal IChannelListener<TChannel> BuildNegotiationChannelListener<TChannel>(BindingContext context)
  106. where TChannel : class, IChannel
  107. {
  108. SecurityCredentialsManager securityCredentials = this.IssuerBindingContext.BindingParameters.Find<SecurityCredentialsManager>();
  109. if (securityCredentials == null)
  110. {
  111. securityCredentials = ServiceCredentials.CreateDefaultCredentials();
  112. }
  113. this.bootstrapSecurityBindingElement.ReaderQuotas = context.GetInnerProperty<XmlDictionaryReaderQuotas>();
  114. if (this.bootstrapSecurityBindingElement.ReaderQuotas == null)
  115. {
  116. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.EncodingBindingElementDoesNotHandleReaderQuotas)));
  117. }
  118. TransportBindingElement transportBindingElement = context.RemainingBindingElements.Find<TransportBindingElement>();
  119. if (transportBindingElement != null)
  120. this.bootstrapSecurityBindingElement.MaxReceivedMessageSize = transportBindingElement.MaxReceivedMessageSize;
  121. SecurityProtocolFactory securityProtocolFactory = this.bootstrapSecurityBindingElement.CreateSecurityProtocolFactory<TChannel>(this.IssuerBindingContext.Clone(), securityCredentials, true, this.IssuerBindingContext.Clone());
  122. MessageSecurityProtocolFactory soapBindingFactory = securityProtocolFactory as MessageSecurityProtocolFactory;
  123. if (soapBindingFactory != null)
  124. {
  125. soapBindingFactory.ApplyConfidentiality = soapBindingFactory.ApplyIntegrity
  126. = soapBindingFactory.RequireConfidentiality = soapBindingFactory.RequireIntegrity = true;
  127. MessagePartSpecification bodyPart = new MessagePartSpecification(true);
  128. soapBindingFactory.ProtectionRequirements.OutgoingSignatureParts.AddParts(bodyPart, RequestSecurityTokenResponseAction);
  129. soapBindingFactory.ProtectionRequirements.OutgoingEncryptionParts.AddParts(bodyPart, RequestSecurityTokenResponseAction);
  130. soapBindingFactory.ProtectionRequirements.IncomingSignatureParts.AddParts(bodyPart, RequestSecurityTokenAction);
  131. soapBindingFactory.ProtectionRequirements.IncomingEncryptionParts.AddParts(bodyPart, RequestSecurityTokenAction);
  132. }
  133. SecurityChannelListener<TChannel> securityChannelListener =
  134. new SecurityChannelListener<TChannel>(this.bootstrapSecurityBindingElement, context);
  135. securityChannelListener.SecurityProtocolFactory = securityProtocolFactory;
  136. // do not send back unsecured faults over composite duplex
  137. securityChannelListener.SendUnsecuredFaults = !SecurityUtils.IsCompositeDuplexBinding(context);
  138. ChannelBuilder channelBuilder = new ChannelBuilder(context, true);
  139. securityChannelListener.InitializeListener(channelBuilder);
  140. this.shouldMatchRstWithEndpointFilter = SecurityUtils.ShouldMatchRstWithEndpointFilter(this.bootstrapSecurityBindingElement);
  141. return securityChannelListener;
  142. }
  143. protected override BodyWriter ProcessRequestSecurityToken(Message request, RequestSecurityToken requestSecurityToken, out NegotiationTokenAuthenticatorState negotiationState)
  144. {
  145. if (request == null)
  146. {
  147. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("request");
  148. }
  149. if (requestSecurityToken == null)
  150. {
  151. throw TraceUtility.ThrowHelperArgumentNull("requestSecurityToken", request);
  152. }
  153. try
  154. {
  155. if (requestSecurityToken.RequestType != null && requestSecurityToken.RequestType != this.StandardsManager.TrustDriver.RequestTypeIssue)
  156. {
  157. throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.InvalidRstRequestType, requestSecurityToken.RequestType)), request);
  158. }
  159. if (requestSecurityToken.TokenType != null && requestSecurityToken.TokenType != this.SecurityContextTokenUri)
  160. {
  161. throw TraceUtility.ThrowHelperWarning(new SecurityNegotiationException(SR.GetString(SR.CannotIssueRstTokenType, requestSecurityToken.TokenType)), request);
  162. }
  163. EndpointAddress appliesTo;
  164. DataContractSerializer appliesToSerializer;
  165. string appliesToName;
  166. string appliesToNamespace;
  167. requestSecurityToken.GetAppliesToQName(out appliesToName, out appliesToNamespace);
  168. if (appliesToName == AddressingStrings.EndpointReference && appliesToNamespace == request.Version.Addressing.Namespace)
  169. {
  170. if (request.Version.Addressing == AddressingVersion.WSAddressing10)
  171. {
  172. appliesToSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(EndpointAddress10), DataContractSerializerDefaults.MaxItemsInObjectGraph);
  173. appliesTo = requestSecurityToken.GetAppliesTo<EndpointAddress10>(appliesToSerializer).ToEndpointAddress();
  174. }
  175. else if (request.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
  176. {
  177. appliesToSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(EndpointAddressAugust2004), DataContractSerializerDefaults.MaxItemsInObjectGraph);
  178. appliesTo = requestSecurityToken.GetAppliesTo<EndpointAddressAugust2004>(appliesToSerializer).ToEndpointAddress();
  179. }
  180. else
  181. {
  182. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  183. new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, request.Version.Addressing)));
  184. }
  185. }
  186. else
  187. {
  188. appliesTo = null;
  189. appliesToSerializer = null;
  190. }
  191. if (this.shouldMatchRstWithEndpointFilter)
  192. {
  193. SecurityUtils.MatchRstWithEndpointFilter(request, this.EndpointFilterTable, this.ListenUri);
  194. }
  195. int issuedKeySize;
  196. byte[] issuerEntropy;
  197. byte[] proofKey;
  198. SecurityToken proofToken;
  199. WSTrust.Driver.ProcessRstAndIssueKey(requestSecurityToken, null, this.KeyEntropyMode, this.SecurityAlgorithmSuite,
  200. out issuedKeySize, out issuerEntropy, out proofKey, out proofToken);
  201. UniqueId contextId = SecurityUtils.GenerateUniqueId();
  202. string id = SecurityUtils.GenerateId();
  203. DateTime effectiveTime = DateTime.UtcNow;
  204. DateTime expirationTime = TimeoutHelper.Add(effectiveTime, this.ServiceTokenLifetime);
  205. // ensure that a SecurityContext is present in the message
  206. SecurityMessageProperty securityProperty = request.Properties.Security;
  207. ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies;
  208. if (securityProperty != null)
  209. authorizationPolicies = SecuritySessionSecurityTokenAuthenticator.CreateSecureConversationPolicies(securityProperty, expirationTime);
  210. else
  211. authorizationPolicies = EmptyReadOnlyCollection<IAuthorizationPolicy>.Instance;
  212. SecurityContextSecurityToken serviceToken = this.IssueSecurityContextToken(contextId, id, proofKey, effectiveTime, expirationTime, authorizationPolicies,
  213. this.EncryptStateInServiceToken);
  214. if (this.preserveBootstrapTokens)
  215. {
  216. serviceToken.BootstrapMessageProperty = (securityProperty == null) ? null : (SecurityMessageProperty)securityProperty.CreateCopy();
  217. SecurityUtils.ErasePasswordInUsernameTokenIfPresent(serviceToken.BootstrapMessageProperty);
  218. }
  219. RequestSecurityTokenResponse rstr = new RequestSecurityTokenResponse(this.StandardsManager);
  220. rstr.Context = requestSecurityToken.Context;
  221. rstr.KeySize = issuedKeySize;
  222. rstr.RequestedUnattachedReference = this.IssuedSecurityTokenParameters.CreateKeyIdentifierClause(serviceToken, SecurityTokenReferenceStyle.External);
  223. rstr.RequestedAttachedReference = this.IssuedSecurityTokenParameters.CreateKeyIdentifierClause(serviceToken, SecurityTokenReferenceStyle.Internal);
  224. rstr.TokenType = this.SecurityContextTokenUri;
  225. rstr.RequestedSecurityToken = serviceToken;
  226. if (issuerEntropy != null)
  227. {
  228. rstr.SetIssuerEntropy(issuerEntropy);
  229. rstr.ComputeKey = true;
  230. }
  231. if (proofToken != null)
  232. {
  233. rstr.RequestedProofToken = proofToken;
  234. }
  235. if (appliesTo != null)
  236. {
  237. if (request.Version.Addressing == AddressingVersion.WSAddressing10)
  238. {
  239. rstr.SetAppliesTo<EndpointAddress10>(EndpointAddress10.FromEndpointAddress(appliesTo), appliesToSerializer);
  240. }
  241. else if (request.Version.Addressing == AddressingVersion.WSAddressingAugust2004)
  242. {
  243. rstr.SetAppliesTo<EndpointAddressAugust2004>(EndpointAddressAugust2004.FromEndpointAddress(appliesTo), appliesToSerializer);
  244. }
  245. else
  246. {
  247. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  248. new ProtocolException(SR.GetString(SR.AddressingVersionNotSupported, request.Version.Addressing)));
  249. }
  250. }
  251. rstr.MakeReadOnly();
  252. negotiationState = new NegotiationTokenAuthenticatorState();
  253. negotiationState.SetServiceToken(serviceToken);
  254. if (this.StandardsManager.MessageSecurityVersion.SecureConversationVersion == SecureConversationVersion.WSSecureConversationFeb2005)
  255. return rstr;
  256. else if (this.StandardsManager.MessageSecurityVersion.SecureConversationVersion == SecureConversationVersion.WSSecureConversation13)
  257. {
  258. List<RequestSecurityTokenResponse> rstrList = new List<RequestSecurityTokenResponse>(1);
  259. rstrList.Add(rstr);
  260. RequestSecurityTokenResponseCollection rstrCollection = new RequestSecurityTokenResponseCollection(rstrList, this.StandardsManager);
  261. return rstrCollection;
  262. }
  263. else
  264. {
  265. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
  266. }
  267. }
  268. finally
  269. {
  270. SecuritySessionSecurityTokenAuthenticator.RemoveCachedTokensIfRequired(request.Properties.Security);
  271. }
  272. }
  273. protected override BodyWriter ProcessRequestSecurityTokenResponse(NegotiationTokenAuthenticatorState negotiationState, Message request, RequestSecurityTokenResponse requestSecurityTokenResponse)
  274. {
  275. throw TraceUtility.ThrowHelperWarning(new NotSupportedException(SR.GetString(SR.RstDirectDoesNotExpectRstr)), request);
  276. }
  277. class RstDirectFilter : HeaderFilter
  278. {
  279. SecurityStandardsManager standardsManager;
  280. AcceleratedTokenAuthenticator authenticator;
  281. public RstDirectFilter(SecurityStandardsManager standardsManager, AcceleratedTokenAuthenticator authenticator)
  282. {
  283. this.standardsManager = standardsManager;
  284. this.authenticator = authenticator;
  285. }
  286. public override bool Match(Message message)
  287. {
  288. if (message.Headers.Action == this.authenticator.RequestSecurityTokenAction.Value)
  289. {
  290. return this.standardsManager.DoesMessageContainSecurityHeader(message);
  291. }
  292. else
  293. {
  294. return false;
  295. }
  296. }
  297. }
  298. }
  299. class AcceleratedTokenAuthenticatorBindingElement : BindingElement
  300. {
  301. AcceleratedTokenAuthenticator authenticator;
  302. public AcceleratedTokenAuthenticatorBindingElement(AcceleratedTokenAuthenticator authenticator)
  303. {
  304. this.authenticator = authenticator;
  305. }
  306. public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
  307. {
  308. if (context == null)
  309. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context");
  310. return authenticator.BuildNegotiationChannelListener<TChannel>(context);
  311. }
  312. public override BindingElement Clone()
  313. {
  314. return new AcceleratedTokenAuthenticatorBindingElement(this.authenticator);
  315. }
  316. public override T GetProperty<T>(BindingContext context)
  317. {
  318. if (typeof(T) == typeof(ISecurityCapabilities))
  319. {
  320. return (T)(object)authenticator.BootstrapSecurityBindingElement.GetProperty<ISecurityCapabilities>(context);
  321. }
  322. return context.GetInnerProperty<T>();
  323. }
  324. }
  325. }