|
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Security
{
using System;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Xml;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Security.Principal;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IdentityModel.Claims;
using System.IdentityModel.Policy;
using System.IdentityModel.Tokens;
using System.IdentityModel.Selectors;
using System.ServiceModel.Security.Tokens;
using System.IO;
using System.ServiceModel.Security;
using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
using System.ServiceModel.Dispatcher;
class RequestSecurityTokenResponse : BodyWriter
{
static int minSaneKeySizeInBits = 8 * 8; // 8 Bytes.
static int maxSaneKeySizeInBits = (16 * 1024) * 8; // 16 K
SecurityStandardsManager standardsManager;
string context;
int keySize;
bool computeKey;
string tokenType;
SecurityKeyIdentifierClause requestedAttachedReference;
SecurityKeyIdentifierClause requestedUnattachedReference;
SecurityToken issuedToken;
SecurityToken proofToken;
SecurityToken entropyToken;
BinaryNegotiation negotiationData;
XmlElement rstrXml;
DateTime effectiveTime;
DateTime expirationTime;
bool isLifetimeSet;
byte[] authenticator;
bool isReceiver;
bool isReadOnly;
byte[] cachedWriteBuffer;
int cachedWriteBufferLength;
bool isRequestedTokenClosed;
object appliesTo;
XmlObjectSerializer appliesToSerializer;
Type appliesToType;
Object thisLock = new Object();
System.IdentityModel.XmlBuffer issuedTokenBuffer;
public RequestSecurityTokenResponse()
: this(SecurityStandardsManager.DefaultInstance)
{
}
public RequestSecurityTokenResponse(MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer)
: this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer))
{
}
public RequestSecurityTokenResponse(XmlElement requestSecurityTokenResponseXml,
string context,
string tokenType,
int keySize,
SecurityKeyIdentifierClause requestedAttachedReference,
SecurityKeyIdentifierClause requestedUnattachedReference,
bool computeKey,
DateTime validFrom,
DateTime validTo,
bool isRequestedTokenClosed)
: this(SecurityStandardsManager.DefaultInstance,
requestSecurityTokenResponseXml,
context,
tokenType,
keySize,
requestedAttachedReference,
requestedUnattachedReference,
computeKey,
validFrom,
validTo,
isRequestedTokenClosed,
null)
{
}
public RequestSecurityTokenResponse(MessageSecurityVersion messageSecurityVersion,
SecurityTokenSerializer securityTokenSerializer,
XmlElement requestSecurityTokenResponseXml,
string context,
string tokenType,
int keySize,
SecurityKeyIdentifierClause requestedAttachedReference,
SecurityKeyIdentifierClause requestedUnattachedReference,
bool computeKey,
DateTime validFrom,
DateTime validTo,
bool isRequestedTokenClosed)
: this(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer),
requestSecurityTokenResponseXml,
context,
tokenType,
keySize,
requestedAttachedReference,
requestedUnattachedReference,
computeKey,
validFrom,
validTo,
isRequestedTokenClosed,
null)
{
}
internal RequestSecurityTokenResponse(SecurityStandardsManager standardsManager)
: base(true)
{
if (standardsManager == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("standardsManager"));
}
this.standardsManager = standardsManager;
effectiveTime = SecurityUtils.MinUtcDateTime;
expirationTime = SecurityUtils.MaxUtcDateTime;
isRequestedTokenClosed = false;
this.isLifetimeSet = false;
this.isReceiver = false;
this.isReadOnly = false;
}
internal RequestSecurityTokenResponse(SecurityStandardsManager standardsManager,
XmlElement rstrXml,
string context,
string tokenType,
int keySize,
SecurityKeyIdentifierClause requestedAttachedReference,
SecurityKeyIdentifierClause requestedUnattachedReference,
bool computeKey,
DateTime validFrom,
DateTime validTo,
bool isRequestedTokenClosed,
System.IdentityModel.XmlBuffer issuedTokenBuffer)
: base(true)
{
if (standardsManager == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("standardsManager"));
}
this.standardsManager = standardsManager;
if (rstrXml == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("rstrXml");
this.rstrXml = rstrXml;
this.context = context;
this.tokenType = tokenType;
this.keySize = keySize;
this.requestedAttachedReference = requestedAttachedReference;
this.requestedUnattachedReference = requestedUnattachedReference;
this.computeKey = computeKey;
this.effectiveTime = validFrom.ToUniversalTime();
this.expirationTime = validTo.ToUniversalTime();
this.isLifetimeSet = true;
this.isRequestedTokenClosed = isRequestedTokenClosed;
this.issuedTokenBuffer = issuedTokenBuffer;
this.isReceiver = true;
this.isReadOnly = true;
}
public string Context
{
get
{
return this.context;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.context = value;
}
}
public string TokenType
{
get
{
return this.tokenType;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.tokenType = value;
}
}
public SecurityKeyIdentifierClause RequestedAttachedReference
{
get
{
return this.requestedAttachedReference;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.requestedAttachedReference = value;
}
}
public SecurityKeyIdentifierClause RequestedUnattachedReference
{
get
{
return this.requestedUnattachedReference;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.requestedUnattachedReference = value;
}
}
public DateTime ValidFrom
{
get
{
return this.effectiveTime;
}
}
public DateTime ValidTo
{
get
{
return this.expirationTime;
}
}
public bool ComputeKey
{
get
{
return this.computeKey;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.computeKey = value;
}
}
public int KeySize
{
get
{
return this.keySize;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
if (value < 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBeNonNegative)));
this.keySize = value;
}
}
public bool IsRequestedTokenClosed
{
get
{
return this.isRequestedTokenClosed;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.isRequestedTokenClosed = value;
}
}
public bool IsReadOnly
{
get
{
return this.isReadOnly;
}
}
protected Object ThisLock
{
get
{
return this.thisLock;
}
}
internal bool IsReceiver
{
get
{
return this.isReceiver;
}
}
internal SecurityStandardsManager StandardsManager
{
get
{
return this.standardsManager;
}
set
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.standardsManager = (value != null ? value : SecurityStandardsManager.DefaultInstance);
}
}
public SecurityToken EntropyToken
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRSTR, "EntropyToken")));
}
return this.entropyToken;
}
}
public SecurityToken RequestedSecurityToken
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRSTR, "IssuedToken")));
}
return this.issuedToken;
}
set
{
if (this.isReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.issuedToken = value;
}
}
public SecurityToken RequestedProofToken
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRSTR, "ProofToken")));
}
return this.proofToken;
}
set
{
if (this.isReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.proofToken = value;
}
}
public XmlElement RequestSecurityTokenResponseXml
{
get
{
if (!this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTROnly, "RequestSecurityTokenXml")));
}
return this.rstrXml;
}
}
internal object AppliesTo
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesTo")));
}
return this.appliesTo;
}
}
internal XmlObjectSerializer AppliesToSerializer
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesToSerializer")));
}
return this.appliesToSerializer;
}
}
internal Type AppliesToType
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRST, "AppliesToType")));
}
return this.appliesToType;
}
}
internal bool IsLifetimeSet
{
get
{
if (this.isReceiver)
{
// PreSharp Bug: Property get methods should not throw exceptions.
#pragma warning suppress 56503
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemNotAvailableInDeserializedRSTR, "IsLifetimeSet")));
}
return this.isLifetimeSet;
}
}
internal System.IdentityModel.XmlBuffer IssuedTokenBuffer
{
get
{
return this.issuedTokenBuffer;
}
}
public void SetIssuerEntropy(byte[] issuerEntropy)
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.entropyToken = (issuerEntropy != null) ? new NonceToken(issuerEntropy) : null;
}
internal void SetIssuerEntropy(WrappedKeySecurityToken issuerEntropy)
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.entropyToken = issuerEntropy;
}
public SecurityToken GetIssuerEntropy()
{
return this.GetIssuerEntropy(null);
}
internal SecurityToken GetIssuerEntropy(SecurityTokenResolver resolver)
{
if (this.isReceiver)
{
return this.standardsManager.TrustDriver.GetEntropy(this, resolver);
}
else
return this.entropyToken;
}
public void SetLifetime(DateTime validFrom, DateTime validTo)
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
if (validFrom.ToUniversalTime() > validTo.ToUniversalTime())
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.EffectiveGreaterThanExpiration));
}
this.effectiveTime = validFrom.ToUniversalTime();
this.expirationTime = validTo.ToUniversalTime();
this.isLifetimeSet = true;
}
public void SetAppliesTo<T>(T appliesTo, XmlObjectSerializer serializer)
{
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
if (appliesTo != null && serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
}
this.appliesTo = appliesTo;
this.appliesToSerializer = serializer;
this.appliesToType = typeof(T);
}
public void GetAppliesToQName(out string localName, out string namespaceUri)
{
if (!this.isReceiver)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTOnly, "MatchesAppliesTo")));
this.standardsManager.TrustDriver.GetAppliesToQName(this, out localName, out namespaceUri);
}
public T GetAppliesTo<T>()
{
return this.GetAppliesTo<T>(DataContractSerializerDefaults.CreateSerializer(typeof(T), DataContractSerializerDefaults.MaxItemsInObjectGraph));
}
public T GetAppliesTo<T>(XmlObjectSerializer serializer)
{
if (this.isReceiver)
{
if (serializer == null)
{
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serializer");
}
return this.standardsManager.TrustDriver.GetAppliesTo<T>(this, serializer);
}
else
{
return (T)this.appliesTo;
}
}
internal void SetBinaryNegotiation(BinaryNegotiation negotiation)
{
if (negotiation == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("negotiation");
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.negotiationData = negotiation;
}
internal BinaryNegotiation GetBinaryNegotiation()
{
if (this.isReceiver)
return this.standardsManager.TrustDriver.GetBinaryNegotiation(this);
else
return this.negotiationData;
}
internal void SetAuthenticator(byte[] authenticator)
{
if (authenticator == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authenticator");
if (this.IsReadOnly)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
this.authenticator = DiagnosticUtility.Utility.AllocateByteArray(authenticator.Length);
Buffer.BlockCopy(authenticator, 0, this.authenticator, 0, authenticator.Length);
}
internal byte[] GetAuthenticator()
{
if (this.isReceiver)
return this.standardsManager.TrustDriver.GetAuthenticator(this);
else
{
if (this.authenticator == null)
return null;
else
{
byte[] result = DiagnosticUtility.Utility.AllocateByteArray(this.authenticator.Length);
Buffer.BlockCopy(this.authenticator, 0, result, 0, this.authenticator.Length);
return result;
}
}
}
void OnWriteTo(XmlWriter w)
{
if (this.isReceiver)
{
this.rstrXml.WriteTo(w);
}
else
{
this.standardsManager.TrustDriver.WriteRequestSecurityTokenResponse(this, w);
}
}
public void WriteTo(XmlWriter writer)
{
if (writer == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
if (this.IsReadOnly)
{
// cache the serialized bytes to ensure repeatability
if (this.cachedWriteBuffer == null)
{
MemoryStream stream = new MemoryStream();
using (XmlDictionaryWriter binaryWriter = XmlDictionaryWriter.CreateBinaryWriter(stream, XD.Dictionary))
{
this.OnWriteTo(binaryWriter);
binaryWriter.Flush();
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
this.cachedWriteBuffer = stream.GetBuffer();
this.cachedWriteBufferLength = (int)stream.Length;
}
}
writer.WriteNode(XmlDictionaryReader.CreateBinaryReader(this.cachedWriteBuffer, 0, this.cachedWriteBufferLength, XD.Dictionary, XmlDictionaryReaderQuotas.Max), false);
}
else
this.OnWriteTo(writer);
}
public static RequestSecurityTokenResponse CreateFrom(XmlReader reader)
{
return CreateFrom(SecurityStandardsManager.DefaultInstance, reader);
}
public static RequestSecurityTokenResponse CreateFrom(XmlReader reader, MessageSecurityVersion messageSecurityVersion, SecurityTokenSerializer securityTokenSerializer)
{
return CreateFrom(SecurityUtils.CreateSecurityStandardsManager(messageSecurityVersion, securityTokenSerializer), reader);
}
internal static RequestSecurityTokenResponse CreateFrom(SecurityStandardsManager standardsManager, XmlReader reader)
{
return standardsManager.TrustDriver.CreateRequestSecurityTokenResponse(reader);
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
WriteTo(writer);
}
public void MakeReadOnly()
{
if (!this.isReadOnly)
{
this.isReadOnly = true;
this.OnMakeReadOnly();
}
}
public GenericXmlSecurityToken GetIssuedToken(SecurityTokenResolver resolver, IList<SecurityTokenAuthenticator> allowedAuthenticators, SecurityKeyEntropyMode keyEntropyMode, byte[] requestorEntropy, string expectedTokenType,
ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
{
return this.GetIssuedToken(resolver, allowedAuthenticators, keyEntropyMode, requestorEntropy, expectedTokenType, authorizationPolicies, 0, false);
}
public virtual GenericXmlSecurityToken GetIssuedToken(SecurityTokenResolver resolver, IList<SecurityTokenAuthenticator> allowedAuthenticators, SecurityKeyEntropyMode keyEntropyMode, byte[] requestorEntropy, string expectedTokenType,
ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, int defaultKeySize, bool isBearerKeyType)
{
if (!this.isReceiver)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTROnly, "GetIssuedToken")));
return this.standardsManager.TrustDriver.GetIssuedToken(this, resolver, allowedAuthenticators, keyEntropyMode, requestorEntropy, expectedTokenType, authorizationPolicies, defaultKeySize, isBearerKeyType);
}
public virtual GenericXmlSecurityToken GetIssuedToken(string expectedTokenType, ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies, RSA clientKey)
{
if (!this.isReceiver)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ItemAvailableInDeserializedRSTROnly, "GetIssuedToken")));
return this.standardsManager.TrustDriver.GetIssuedToken(this, expectedTokenType, authorizationPolicies, clientKey);
}
protected internal virtual void OnWriteCustomAttributes(XmlWriter writer)
{ }
protected internal virtual void OnWriteCustomElements(XmlWriter writer)
{ }
protected virtual void OnMakeReadOnly() { }
public static byte[] ComputeCombinedKey(byte[] requestorEntropy, byte[] issuerEntropy, int keySizeInBits)
{
if (requestorEntropy == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("requestorEntropy");
if (issuerEntropy == null)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("issuerEntropy");
// Do a sanity check here. We don't want to allow invalid keys or keys that are too
// large.
if ((keySizeInBits < minSaneKeySizeInBits) || (keySizeInBits > maxSaneKeySizeInBits))
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidKeySizeSpecifiedInNegotiation, keySizeInBits, minSaneKeySizeInBits, maxSaneKeySizeInBits)));
Psha1DerivedKeyGenerator generator = new Psha1DerivedKeyGenerator(requestorEntropy);
return generator.GenerateDerivedKey(new byte[] { }, issuerEntropy, keySizeInBits, 0);
}
}
}
|