File: System\ServiceModel\Security\MessageSecurityProtocolFactory.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.Collections.Generic;
    using System.ServiceModel;
    using System.IO;
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy;
    using System.IdentityModel.Selectors;
    using System.Security.Cryptography;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Security.Tokens;
    using System.Text;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Runtime.Serialization;
    using System.Net.Security;
 
    abstract class MessageSecurityProtocolFactory : SecurityProtocolFactory
    {
        internal const MessageProtectionOrder defaultMessageProtectionOrder = MessageProtectionOrder.SignBeforeEncrypt;
        internal const bool defaultDoRequestSignatureConfirmation = false;
 
        bool applyIntegrity = true;
        bool applyConfidentiality = true;
        bool doRequestSignatureConfirmation = defaultDoRequestSignatureConfirmation;
        IdentityVerifier identityVerifier;
        ChannelProtectionRequirements protectionRequirements = new ChannelProtectionRequirements();
        MessageProtectionOrder messageProtectionOrder = defaultMessageProtectionOrder;
        bool requireIntegrity = true;
        bool requireConfidentiality = true;
        List<SecurityTokenAuthenticator> wrappedKeyTokenAuthenticator;
 
        protected MessageSecurityProtocolFactory()
        {
        }
 
        internal MessageSecurityProtocolFactory(MessageSecurityProtocolFactory factory)
            : base(factory)
        {
            if (factory == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("factory");
 
            this.applyIntegrity = factory.applyIntegrity;
            this.applyConfidentiality = factory.applyConfidentiality;
            this.identityVerifier = factory.identityVerifier;
            this.protectionRequirements = new ChannelProtectionRequirements(factory.protectionRequirements);
            this.messageProtectionOrder = factory.messageProtectionOrder;
            this.requireIntegrity = factory.requireIntegrity;
            this.requireConfidentiality = factory.requireConfidentiality;
            this.doRequestSignatureConfirmation = factory.doRequestSignatureConfirmation;
        }
 
        public bool ApplyConfidentiality
        {
            get
            {
                return this.applyConfidentiality;
            }
            set
            {
                ThrowIfImmutable();
                this.applyConfidentiality = value;
            }
        }
 
        public bool ApplyIntegrity
        {
            get
            {
                return this.applyIntegrity;
            }
            set
            {
                ThrowIfImmutable();
                this.applyIntegrity = value;
            }
        }
 
        public bool DoRequestSignatureConfirmation
        {
            get
            {
                return this.doRequestSignatureConfirmation;
            }
            set
            {
                ThrowIfImmutable();
                this.doRequestSignatureConfirmation = value;
            }
        }
 
        public IdentityVerifier IdentityVerifier
        {
            get
            {
                return this.identityVerifier;
            }
            set
            {
                ThrowIfImmutable();
                this.identityVerifier = value;
            }
        }
 
        public ChannelProtectionRequirements ProtectionRequirements
        {
            get
            {
                return this.protectionRequirements;
            }
        }
 
        public MessageProtectionOrder MessageProtectionOrder
        {
            get
            {
                return this.messageProtectionOrder;
            }
            set
            {
                ThrowIfImmutable();
                this.messageProtectionOrder = value;
            }
        }
 
        public bool RequireIntegrity
        {
            get
            {
                return this.requireIntegrity;
            }
            set
            {
                ThrowIfImmutable();
                this.requireIntegrity = value;
            }
        }
 
        public bool RequireConfidentiality
        {
            get
            {
                return this.requireConfidentiality;
            }
            set
            {
                ThrowIfImmutable();
                this.requireConfidentiality = value;
            }
        }
 
        internal List<SecurityTokenAuthenticator> WrappedKeySecurityTokenAuthenticator
        {
            get
            {
                return this.wrappedKeyTokenAuthenticator;
            }
        }
 
        protected virtual void ValidateCorrelationSecuritySettings()
        {
            if (this.ActAsInitiator && this.SupportsRequestReply)
            {
                bool savesCorrelationTokenOnRequest = this.ApplyIntegrity || this.ApplyConfidentiality;
                bool needsCorrelationTokenOnReply = this.RequireIntegrity || this.RequireConfidentiality;
                if (!savesCorrelationTokenOnRequest && needsCorrelationTokenOnReply)
                {
                    OnPropertySettingsError("ApplyIntegrity", false);
                }
            }
        }
 
        public override void OnOpen(TimeSpan timeout)
        {
            base.OnOpen(timeout);
            this.protectionRequirements.MakeReadOnly();
 
            if (this.DetectReplays && !this.RequireIntegrity)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("RequireIntegrity", SR.GetString(SR.ForReplayDetectionToBeDoneRequireIntegrityMustBeSet));
            }
 
            if (this.DoRequestSignatureConfirmation)
            {
                if (!this.SupportsRequestReply)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SignatureConfirmationRequiresRequestReply));
                }
                if (!this.StandardsManager.SecurityVersion.SupportsSignatureConfirmation)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.SecurityVersionDoesNotSupportSignatureConfirmation, this.StandardsManager.SecurityVersion));
                }
            }
 
            this.wrappedKeyTokenAuthenticator = new List<SecurityTokenAuthenticator>(1);
            SecurityTokenAuthenticator authenticator = new NonValidatingSecurityTokenAuthenticator<WrappedKeySecurityToken>();
            this.wrappedKeyTokenAuthenticator.Add(authenticator);
 
            ValidateCorrelationSecuritySettings();
        }
 
        static MessagePartSpecification ExtractMessageParts(string action,
            ScopedMessagePartSpecification scopedParts, bool isForSignature)
        {
            MessagePartSpecification parts = null;
 
            if (scopedParts.TryGetParts(action, out parts))
            {
                return parts;
            }
            else if (scopedParts.TryGetParts(MessageHeaders.WildcardAction, out parts))
            {
                return parts;
            }
 
            // send back a fault indication that the action is unknown
            SecurityVersion wss = MessageSecurityVersion.Default.SecurityVersion;
            FaultCode subCode = new FaultCode(wss.InvalidSecurityFaultCode.Value, wss.HeaderNamespace.Value);
            FaultCode senderCode = FaultCode.CreateSenderFaultCode(subCode);
            FaultReason reason = new FaultReason(SR.GetString(SR.InvalidOrUnrecognizedAction, action), System.Globalization.CultureInfo.CurrentCulture);
            MessageFault fault = MessageFault.CreateFault(senderCode, reason);
            if (isForSignature)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoSignaturePartsSpecified, action), null, fault));
            }
            else
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoEncryptionPartsSpecified, action), null, fault));
            }
        }
 
        internal MessagePartSpecification GetIncomingEncryptionParts(string action)
        {
            if (this.RequireConfidentiality)
            {
                //return ExtractMessageParts(action, (this.SecurityTokenManager is ClientCredentialsSecurityTokenManager) ? this.ProtectionRequirements.OutgoingEncryptionParts : this.ProtectionRequirements.IncomingEncryptionParts, false);
 
                if (this.IsDuplexReply)
                    return ExtractMessageParts(action, this.ProtectionRequirements.OutgoingEncryptionParts, false);
                else
                    return ExtractMessageParts(action, (this.ActAsInitiator) ? this.ProtectionRequirements.OutgoingEncryptionParts : this.ProtectionRequirements.IncomingEncryptionParts, false);
            }
            else
            {
                return MessagePartSpecification.NoParts;
            }
        }
 
        internal MessagePartSpecification GetIncomingSignatureParts(string action)
        {
            if (this.RequireIntegrity)
            {
                //return ExtractMessageParts(action, (this.SecurityTokenManager is ClientCredentialsSecurityTokenManager) ? this.ProtectionRequirements.OutgoingSignatureParts : this.ProtectionRequirements.IncomingSignatureParts, true);
                if (this.IsDuplexReply)
                    return ExtractMessageParts(action, this.ProtectionRequirements.OutgoingSignatureParts, true);
                else
                    return ExtractMessageParts(action, (this.ActAsInitiator) ? this.ProtectionRequirements.OutgoingSignatureParts : this.ProtectionRequirements.IncomingSignatureParts, true);
            }
            else
            {
                return MessagePartSpecification.NoParts;
            }
        }
 
        internal MessagePartSpecification GetOutgoingEncryptionParts(string action)
        {
            if (this.ApplyConfidentiality)
            {
                //return ExtractMessageParts(action, (this.SecurityTokenManager is ClientCredentialsSecurityTokenManager) ? this.ProtectionRequirements.IncomingEncryptionParts : this.ProtectionRequirements.OutgoingEncryptionParts, false);
                if (this.IsDuplexReply)
                    return ExtractMessageParts(action, this.ProtectionRequirements.OutgoingEncryptionParts, false);
                else
                    return ExtractMessageParts(action, (this.ActAsInitiator) ? this.ProtectionRequirements.IncomingEncryptionParts : this.ProtectionRequirements.OutgoingEncryptionParts, false);
            }
            else
            {
                return MessagePartSpecification.NoParts;
            }
        }
 
        internal MessagePartSpecification GetOutgoingSignatureParts(string action)
        {
            if (this.ApplyIntegrity)
            {
                //return ExtractMessageParts(action, (this.SecurityTokenManager is ClientCredentialsSecurityTokenManager) ? this.ProtectionRequirements.IncomingSignatureParts : this.ProtectionRequirements.OutgoingSignatureParts, true);
                if (this.IsDuplexReply)
                    return ExtractMessageParts(action, this.ProtectionRequirements.OutgoingSignatureParts, true);
                else
                    return ExtractMessageParts(action, (this.ActAsInitiator) ? this.ProtectionRequirements.IncomingSignatureParts : this.ProtectionRequirements.OutgoingSignatureParts, true);
            }
            else
            {
                return MessagePartSpecification.NoParts;
            }
        }
    }
}