e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
357 lines
16 KiB
C#
357 lines
16 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Security
|
|
{
|
|
using System;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Description;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Xml;
|
|
using System.IdentityModel.Claims;
|
|
using System.IdentityModel.Policy;
|
|
using System.IdentityModel.Tokens;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
using System.ServiceModel.Security.Tokens;
|
|
using HexBinary = System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary;
|
|
using System.ServiceModel.Channels;
|
|
using System.ServiceModel.Security;
|
|
using System.Runtime.Serialization;
|
|
using System.ServiceModel.Dispatcher;
|
|
|
|
using KeyIdentifierEntry = WSSecurityTokenSerializer.KeyIdentifierEntry;
|
|
using KeyIdentifierClauseEntry = WSSecurityTokenSerializer.KeyIdentifierClauseEntry;
|
|
using TokenEntry = WSSecurityTokenSerializer.TokenEntry;
|
|
using StrEntry = WSSecurityTokenSerializer.StrEntry;
|
|
|
|
class WSTrustFeb2005 : WSTrust
|
|
{
|
|
public WSTrustFeb2005(WSSecurityTokenSerializer tokenSerializer)
|
|
: base(tokenSerializer)
|
|
{
|
|
}
|
|
|
|
public override TrustDictionary SerializerDictionary
|
|
{
|
|
get { return XD.TrustFeb2005Dictionary; }
|
|
}
|
|
|
|
public class DriverFeb2005 : Driver
|
|
{
|
|
public DriverFeb2005(SecurityStandardsManager standardsManager)
|
|
: base(standardsManager)
|
|
{
|
|
}
|
|
|
|
public override TrustDictionary DriverDictionary
|
|
{
|
|
get
|
|
{
|
|
return XD.TrustFeb2005Dictionary;
|
|
}
|
|
}
|
|
|
|
public override XmlDictionaryString RequestSecurityTokenResponseFinalAction
|
|
{
|
|
get
|
|
{
|
|
return XD.TrustFeb2005Dictionary.RequestSecurityTokenIssuanceResponse;
|
|
}
|
|
}
|
|
|
|
public override bool IsSessionSupported
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override bool IsIssuedTokensSupported
|
|
{
|
|
get
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public override string IssuedTokensHeaderName
|
|
{
|
|
get
|
|
{
|
|
return this.DriverDictionary.IssuedTokensHeader.Value;
|
|
}
|
|
}
|
|
|
|
public override string IssuedTokensHeaderNamespace
|
|
{
|
|
get
|
|
{
|
|
return this.DriverDictionary.Namespace.Value;
|
|
}
|
|
}
|
|
|
|
public override string RequestTypeRenew
|
|
{
|
|
get
|
|
{
|
|
return this.DriverDictionary.RequestTypeRenew.Value;
|
|
}
|
|
}
|
|
|
|
public override string RequestTypeClose
|
|
{
|
|
get
|
|
{
|
|
return this.DriverDictionary.RequestTypeClose.Value;
|
|
}
|
|
}
|
|
|
|
public override Collection<XmlElement> ProcessUnknownRequestParameters(Collection<XmlElement> unknownRequestParameters, Collection<XmlElement> originalRequestParameters)
|
|
{
|
|
return unknownRequestParameters;
|
|
}
|
|
|
|
protected override void ReadReferences(XmlElement rstrXml, out SecurityKeyIdentifierClause requestedAttachedReference,
|
|
out SecurityKeyIdentifierClause requestedUnattachedReference)
|
|
{
|
|
XmlElement issuedTokenXml = null;
|
|
requestedAttachedReference = null;
|
|
requestedUnattachedReference = null;
|
|
for (int i = 0; i < rstrXml.ChildNodes.Count; ++i)
|
|
{
|
|
XmlElement child = rstrXml.ChildNodes[i] as XmlElement;
|
|
if (child != null)
|
|
{
|
|
if (child.LocalName == this.DriverDictionary.RequestedSecurityToken.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
{
|
|
issuedTokenXml = XmlHelper.GetChildElement(child);
|
|
}
|
|
else if (child.LocalName == this.DriverDictionary.RequestedAttachedReference.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
{
|
|
requestedAttachedReference = GetKeyIdentifierXmlReferenceClause(XmlHelper.GetChildElement(child));
|
|
}
|
|
else if (child.LocalName == this.DriverDictionary.RequestedUnattachedReference.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
{
|
|
requestedUnattachedReference = GetKeyIdentifierXmlReferenceClause(XmlHelper.GetChildElement(child));
|
|
}
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
if (issuedTokenXml != null)
|
|
{
|
|
if (requestedAttachedReference == null)
|
|
{
|
|
this.StandardsManager.TryCreateKeyIdentifierClauseFromTokenXml(issuedTokenXml, SecurityTokenReferenceStyle.Internal, out requestedAttachedReference);
|
|
}
|
|
if (requestedUnattachedReference == null)
|
|
{
|
|
this.StandardsManager.TryCreateKeyIdentifierClauseFromTokenXml(issuedTokenXml, SecurityTokenReferenceStyle.External, out requestedUnattachedReference);
|
|
}
|
|
}
|
|
}
|
|
catch (XmlException)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.TrustDriverIsUnableToCreatedNecessaryAttachedOrUnattachedReferences, issuedTokenXml.ToString())));
|
|
}
|
|
|
|
}
|
|
|
|
protected override bool ReadRequestedTokenClosed(XmlElement rstrXml)
|
|
{
|
|
for (int i = 0; i < rstrXml.ChildNodes.Count; ++i)
|
|
{
|
|
XmlElement child = (rstrXml.ChildNodes[i] as XmlElement);
|
|
if (child != null)
|
|
{
|
|
if (child.LocalName == this.DriverDictionary.RequestedTokenClosed.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected override void ReadTargets(XmlElement rstXml, out SecurityKeyIdentifierClause renewTarget, out SecurityKeyIdentifierClause closeTarget)
|
|
{
|
|
renewTarget = null;
|
|
closeTarget = null;
|
|
|
|
for (int i = 0; i < rstXml.ChildNodes.Count; ++i)
|
|
{
|
|
XmlElement child = (rstXml.ChildNodes[i] as XmlElement);
|
|
if (child != null)
|
|
{
|
|
if (child.LocalName == this.DriverDictionary.RenewTarget.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
renewTarget = this.StandardsManager.SecurityTokenSerializer.ReadKeyIdentifierClause(new XmlNodeReader(child.FirstChild));
|
|
else if (child.LocalName == this.DriverDictionary.CloseTarget.Value && child.NamespaceURI == this.DriverDictionary.Namespace.Value)
|
|
closeTarget = this.StandardsManager.SecurityTokenSerializer.ReadKeyIdentifierClause(new XmlNodeReader(child.FirstChild));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void WriteReferences(RequestSecurityTokenResponse rstr, XmlDictionaryWriter writer)
|
|
{
|
|
if (rstr.RequestedAttachedReference != null)
|
|
{
|
|
writer.WriteStartElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.RequestedAttachedReference, this.DriverDictionary.Namespace);
|
|
this.StandardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(writer, rstr.RequestedAttachedReference);
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
if (rstr.RequestedUnattachedReference != null)
|
|
{
|
|
writer.WriteStartElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.RequestedUnattachedReference, this.DriverDictionary.Namespace);
|
|
this.StandardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(writer, rstr.RequestedUnattachedReference);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
protected override void WriteRequestedTokenClosed(RequestSecurityTokenResponse rstr, XmlDictionaryWriter writer)
|
|
{
|
|
if (rstr.IsRequestedTokenClosed)
|
|
{
|
|
writer.WriteElementString(this.DriverDictionary.RequestedTokenClosed, this.DriverDictionary.Namespace, String.Empty);
|
|
}
|
|
}
|
|
|
|
protected override void WriteTargets(RequestSecurityToken rst, XmlDictionaryWriter writer)
|
|
{
|
|
if (rst.RenewTarget != null)
|
|
{
|
|
writer.WriteStartElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.RenewTarget, this.DriverDictionary.Namespace);
|
|
this.StandardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(writer, rst.RenewTarget);
|
|
writer.WriteEndElement();
|
|
}
|
|
|
|
if (rst.CloseTarget != null)
|
|
{
|
|
writer.WriteStartElement(this.DriverDictionary.Prefix.Value, this.DriverDictionary.CloseTarget, this.DriverDictionary.Namespace);
|
|
this.StandardsManager.SecurityTokenSerializer.WriteKeyIdentifierClause(writer, rst.CloseTarget);
|
|
writer.WriteEndElement();
|
|
}
|
|
}
|
|
|
|
// this is now the abstract in WSTrust
|
|
public override IChannelFactory<IRequestChannel> CreateFederationProxy(EndpointAddress address, Binding binding, KeyedByTypeCollection<IEndpointBehavior> channelBehaviors)
|
|
{
|
|
if (channelBehaviors == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelBehaviors");
|
|
|
|
ChannelFactory<IWsTrustFeb2005SecurityTokenService> result = new ChannelFactory<IWsTrustFeb2005SecurityTokenService>(binding, address);
|
|
SetProtectionLevelForFederation(result.Endpoint.Contract.Operations);
|
|
// remove the default client credentials that gets added to channel factories
|
|
result.Endpoint.Behaviors.Remove<ClientCredentials>();
|
|
for (int i = 0; i < channelBehaviors.Count; ++i)
|
|
{
|
|
result.Endpoint.Behaviors.Add(channelBehaviors[i]);
|
|
}
|
|
// add a behavior that removes the UI channel initializer added by the client credentials since there should be no UI
|
|
// initializer popped up as part of obtaining the federation token (the UI should already have been popped up for the main channel)
|
|
result.Endpoint.Behaviors.Add(new InteractiveInitializersRemovingBehavior());
|
|
|
|
return new RequestChannelFactory<IWsTrustFeb2005SecurityTokenService>(result);
|
|
}
|
|
|
|
[ServiceContract]
|
|
internal interface IWsTrustFeb2005SecurityTokenService
|
|
{
|
|
[OperationContract(IsOneWay = false,
|
|
Action = TrustFeb2005Strings.RequestSecurityTokenIssuance,
|
|
ReplyAction = TrustFeb2005Strings.RequestSecurityTokenIssuanceResponse)]
|
|
[FaultContract(typeof(string), Action = "*", ProtectionLevel = System.Net.Security.ProtectionLevel.Sign)]
|
|
Message RequestToken(Message message);
|
|
}
|
|
|
|
public class InteractiveInitializersRemovingBehavior : IEndpointBehavior
|
|
{
|
|
public void Validate(ServiceEndpoint serviceEndpoint) { }
|
|
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) { }
|
|
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { }
|
|
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
|
|
{
|
|
// it is very unlikely that InteractiveChannelInitializers will be null, this is defensive in case ClientRuntime every has a
|
|
// bug. I am OK with this as ApplyingClientBehavior is a one-time channel setup.
|
|
if (behavior != null && behavior.InteractiveChannelInitializers != null)
|
|
{
|
|
// clear away any interactive initializer
|
|
behavior.InteractiveChannelInitializers.Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RequestChannelFactory<TokenService> : ChannelFactoryBase, IChannelFactory<IRequestChannel>
|
|
{
|
|
ChannelFactory<TokenService> innerChannelFactory;
|
|
|
|
public RequestChannelFactory(ChannelFactory<TokenService> innerChannelFactory)
|
|
{
|
|
this.innerChannelFactory = innerChannelFactory;
|
|
}
|
|
|
|
public IRequestChannel CreateChannel(EndpointAddress address)
|
|
{
|
|
return this.innerChannelFactory.CreateChannel<IRequestChannel>(address);
|
|
}
|
|
|
|
public IRequestChannel CreateChannel(EndpointAddress address, Uri via)
|
|
{
|
|
return this.innerChannelFactory.CreateChannel<IRequestChannel>(address, via);
|
|
}
|
|
|
|
protected override void OnAbort()
|
|
{
|
|
this.innerChannelFactory.Abort();
|
|
}
|
|
|
|
protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
|
|
{
|
|
return this.innerChannelFactory.BeginOpen(timeout, callback, state);
|
|
}
|
|
|
|
protected override void OnEndOpen(IAsyncResult result)
|
|
{
|
|
this.innerChannelFactory.EndOpen(result);
|
|
}
|
|
|
|
protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
|
|
{
|
|
return this.innerChannelFactory.BeginClose(timeout, callback, state);
|
|
}
|
|
|
|
protected override void OnEndClose(IAsyncResult result)
|
|
{
|
|
this.innerChannelFactory.EndClose(result);
|
|
}
|
|
|
|
protected override void OnClose(TimeSpan timeout)
|
|
{
|
|
this.innerChannelFactory.Close(timeout);
|
|
}
|
|
|
|
protected override void OnOpen(TimeSpan timeout)
|
|
{
|
|
this.innerChannelFactory.Open(timeout);
|
|
}
|
|
|
|
public override T GetProperty<T>()
|
|
{
|
|
return this.innerChannelFactory.GetProperty<T>();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|