| File: System\ServiceModel\Security\RequestSecurityToken.cs | Web Access |
| Project: src\src\System.ServiceModel.Primitives\src\System.ServiceModel.Primitives.csproj (System.ServiceModel.Primitives) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.ServiceModel.Channels; using System.IdentityModel.Tokens; using System.IdentityModel.Selectors; using System.Runtime.Serialization; using System.Xml; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Globalization; using System.Security.Authentication.ExtendedProtection; namespace System.ServiceModel.Security { internal class RequestSecurityToken : BodyWriter { #pragma warning disable CS0649 // Field is never assign to private string _context; private string _tokenType; private string _requestType; private SecurityToken _entropyToken; private BinaryNegotiation _negotiationData; private XmlElement _rstXml; private IList<XmlElement> _requestProperties; private ArraySegment<byte> _cachedWriteBuffer; private int _cachedWriteBufferLength; private int _keySize; private SecurityKeyIdentifierClause _renewTarget; private SecurityKeyIdentifierClause _closeTarget; private SecurityStandardsManager _standardsManager; private bool _isReadOnly; private object _appliesTo; private DataContractSerializer _appliesToSerializer; private Type _appliesToType; #pragma warning restore CS0649 // Field is never assign to private object _thisLock = new Object(); public RequestSecurityToken() : this(SecurityStandardsManager.DefaultInstance) { } public RequestSecurityToken(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer) : this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer)) { } public RequestSecurityToken(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer, XmlElement requestSecurityTokenXml, string context, string tokenType, string requestType, int keySize, SecurityKeyIdentifierClause renewTarget, SecurityKeyIdentifierClause closeTarget) : this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer), requestSecurityTokenXml, context, tokenType, requestType, keySize, renewTarget, closeTarget) { } public RequestSecurityToken(XmlElement requestSecurityTokenXml, string context, string tokenType, string requestType, int keySize, SecurityKeyIdentifierClause renewTarget, SecurityKeyIdentifierClause closeTarget) : this(SecurityStandardsManager.DefaultInstance, requestSecurityTokenXml, context, tokenType, requestType, keySize, renewTarget, closeTarget) { } internal RequestSecurityToken(SecurityStandardsManager standardsManager, XmlElement rstXml, string context, string tokenType, string requestType, int keySize, SecurityKeyIdentifierClause renewTarget, SecurityKeyIdentifierClause closeTarget) : base(true) { _standardsManager = standardsManager ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(standardsManager))); _rstXml = rstXml ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(rstXml)); _context = context; _tokenType = tokenType; _keySize = keySize; _requestType = requestType; _renewTarget = renewTarget; _closeTarget = closeTarget; IsReceiver = true; _isReadOnly = true; } internal RequestSecurityToken(SecurityStandardsManager standardsManager) : this(standardsManager, true) { // no op } internal RequestSecurityToken(SecurityStandardsManager standardsManager, bool isBuffered) : base(isBuffered) { _standardsManager = standardsManager ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(standardsManager))); _requestType = _standardsManager.TrustDriver.RequestTypeIssue; _requestProperties = null; IsReceiver = false; _isReadOnly = false; } public ChannelBinding GetChannelBinding() { if (Message == null) { return null; } ChannelBindingMessageProperty channelBindingMessageProperty = null; ChannelBindingMessageProperty.TryGet(Message, out channelBindingMessageProperty); ChannelBinding channelBinding = null; if (channelBindingMessageProperty != null) { channelBinding = channelBindingMessageProperty.ChannelBinding; } return channelBinding; } /// <summary> /// Will hold a reference to the outbound message from which we will fish the ChannelBinding out of. /// </summary> public Message Message { get; set; } public string Context { get { return _context; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _context = value; } } public string TokenType { get { return _tokenType; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _tokenType = value; } } public int KeySize { get { return _keySize; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } if (value < 0) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value), SRP.ValueMustBeNonNegative)); } _keySize = value; } } public bool IsReadOnly { get { return _isReadOnly; } } public IEnumerable<XmlElement> RequestProperties { get { if (IsReceiver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.ItemNotAvailableInDeserializedRST, "RequestProperties"))); } return _requestProperties; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } if (value != null) { int index = 0; Collection<XmlElement> coll = new Collection<XmlElement>(); foreach (XmlElement property in value) { if (property == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(String.Format(CultureInfo.InvariantCulture, "value[{0}]", index))); } coll.Add(property); ++index; } _requestProperties = coll; } else { _requestProperties = null; } } } public string RequestType { get { return _requestType; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _requestType = value ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value)); } } public SecurityKeyIdentifierClause RenewTarget { get { return _renewTarget; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _renewTarget = value; } } public SecurityKeyIdentifierClause CloseTarget { get { return _closeTarget; } set { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _closeTarget = value; } } public XmlElement RequestSecurityTokenXml { get { if (!IsReceiver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.ItemAvailableInDeserializedRSTOnly, "RequestSecurityTokenXml"))); } return _rstXml; } } internal bool IsReceiver { get; } internal object AppliesTo { get { if (IsReceiver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.ItemNotAvailableInDeserializedRST, nameof(AppliesTo)))); } return _appliesTo; } } internal DataContractSerializer AppliesToSerializer { get { if (IsReceiver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.ItemNotAvailableInDeserializedRST, nameof(AppliesToSerializer)))); } return _appliesToSerializer; } } internal Type AppliesToType { get { if (IsReceiver) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.Format(SRP.ItemNotAvailableInDeserializedRST, nameof(AppliesToType)))); } return _appliesToType; } } internal BinaryNegotiation GetBinaryNegotiation() { if (IsReceiver) { return _standardsManager.TrustDriver.GetBinaryNegotiation(this); } return _negotiationData; } public SecurityToken GetRequestorEntropy() { return GetRequestorEntropy(null); } internal SecurityToken GetRequestorEntropy(SecurityTokenResolver resolver) { if (IsReceiver) { return _standardsManager.TrustDriver.GetEntropy(this, resolver); } else { return _entropyToken; } } public void SetRequestorEntropy(byte[] entropy) { if (IsReadOnly) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SRP.ObjectIsReadOnly)); } _entropyToken = (entropy != null) ? new NonceToken(entropy) : null; } public T GetAppliesTo<T>(XmlObjectSerializer serializer) { if (IsReceiver) { if (serializer == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); } return _standardsManager.TrustDriver.GetAppliesTo<T>(this, serializer); } else { return (T)_appliesTo; } } private void OnWriteTo(XmlWriter writer) { if (IsReceiver) { _rstXml.WriteTo(writer); } else { _standardsManager.TrustDriver.WriteRequestSecurityToken(this, writer); } } public void WriteTo(XmlWriter writer) { if (writer == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writer)); } if (IsReadOnly) { // cache the serialized bytes to ensure repeatability if (_cachedWriteBuffer.Array == null) { MemoryStream stream = new MemoryStream(); using (XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, XD.Dictionary)) { OnWriteTo(binaryWriter); binaryWriter.Flush(); stream.Flush(); stream.Seek(0, SeekOrigin.Begin); bool gotBuffer = stream.TryGetBuffer(out _cachedWriteBuffer); if (!gotBuffer) { throw new UnauthorizedAccessException(SRP.UnauthorizedAccess_MemStreamBuffer); } _cachedWriteBufferLength = (int)stream.Length; } } writer.WriteNode(XmlDictionaryReader.CreateBinaryReader(_cachedWriteBuffer.Array, 0, _cachedWriteBufferLength, XD.Dictionary, XmlDictionaryReaderQuotas.Max), false); } else { OnWriteTo(writer); } } internal static RequestSecurityToken CreateFrom(SecurityStandardsManager standardsManager, XmlReader reader) { return standardsManager.TrustDriver.CreateRequestSecurityToken(reader); } public void MakeReadOnly() { if (!_isReadOnly) { _isReadOnly = true; if (_requestProperties != null) { _requestProperties = new ReadOnlyCollection<XmlElement>(_requestProperties); } OnMakeReadOnly(); } } internal protected virtual void OnWriteCustomAttributes(XmlWriter writer) { } internal protected virtual void OnWriteCustomElements(XmlWriter writer) { } internal protected virtual void OnMakeReadOnly() { } protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { WriteTo(writer); } } }