File: System\ServiceModel\Security\WSTrustFeb2005.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// 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>();
                }
            }
        }
 
    }
}