| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Security.Tokens
- {
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.IdentityModel.Claims;
- using System.IdentityModel.Policy;
- using System.IO;
- using System.Runtime;
- using System.Runtime.Serialization;
- using System.Security.Principal;
- using System.ServiceModel;
- using System.ServiceModel.Dispatcher;
- using System.Xml;
- struct SecurityContextCookieSerializer
- {
- const int SupportedPersistanceVersion = 1;
- SecurityStateEncoder securityStateEncoder;
- IList<Type> knownTypes;
- public SecurityContextCookieSerializer(SecurityStateEncoder securityStateEncoder, IList<Type> knownTypes)
- {
- if (securityStateEncoder == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("securityStateEncoder");
- }
- this.securityStateEncoder = securityStateEncoder;
- this.knownTypes = knownTypes ?? new List<Type>();
- }
- SecurityContextSecurityToken DeserializeContext(byte[] serializedContext, byte[] cookieBlob, string id, XmlDictionaryReaderQuotas quotas)
- {
- SctClaimDictionary dictionary = SctClaimDictionary.Instance;
- XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(serializedContext, 0, serializedContext.Length, dictionary, quotas, null, null);
- int cookieVersion = -1;
- UniqueId cookieContextId = null;
- DateTime effectiveTime = SecurityUtils.MinUtcDateTime;
- DateTime expiryTime = SecurityUtils.MaxUtcDateTime;
- byte[] key = null;
- string localId = null;
- UniqueId keyGeneration = null;
- DateTime keyEffectiveTime = SecurityUtils.MinUtcDateTime;
- DateTime keyExpirationTime = SecurityUtils.MaxUtcDateTime;
- List<ClaimSet> claimSets = null;
- IList<IIdentity> identities = null;
- bool isCookie = true;
- reader.ReadFullStartElement(dictionary.SecurityContextSecurityToken, dictionary.EmptyString);
- while (reader.IsStartElement())
- {
- if (reader.IsStartElement(dictionary.Version, dictionary.EmptyString))
- {
- cookieVersion = reader.ReadElementContentAsInt();
- }
- else if (reader.IsStartElement(dictionary.ContextId, dictionary.EmptyString))
- {
- cookieContextId = reader.ReadElementContentAsUniqueId();
- }
- else if (reader.IsStartElement(dictionary.Id, dictionary.EmptyString))
- {
- localId = reader.ReadElementContentAsString();
- }
- else if (reader.IsStartElement(dictionary.EffectiveTime, dictionary.EmptyString))
- {
- effectiveTime = new DateTime(XmlHelper.ReadElementContentAsInt64(reader), DateTimeKind.Utc);
- }
- else if (reader.IsStartElement(dictionary.ExpiryTime, dictionary.EmptyString))
- {
- expiryTime = new DateTime(XmlHelper.ReadElementContentAsInt64(reader), DateTimeKind.Utc);
- }
- else if (reader.IsStartElement(dictionary.Key, dictionary.EmptyString))
- {
- key = reader.ReadElementContentAsBase64();
- }
- else if (reader.IsStartElement(dictionary.KeyGeneration, dictionary.EmptyString))
- {
- keyGeneration = reader.ReadElementContentAsUniqueId();
- }
- else if (reader.IsStartElement(dictionary.KeyEffectiveTime, dictionary.EmptyString))
- {
- keyEffectiveTime = new DateTime(XmlHelper.ReadElementContentAsInt64(reader), DateTimeKind.Utc);
- }
- else if (reader.IsStartElement(dictionary.KeyExpiryTime, dictionary.EmptyString))
- {
- keyExpirationTime = new DateTime(XmlHelper.ReadElementContentAsInt64(reader), DateTimeKind.Utc);
- }
- else if (reader.IsStartElement(dictionary.Identities, dictionary.EmptyString))
- {
- identities = SctClaimSerializer.DeserializeIdentities(reader, dictionary, DataContractSerializerDefaults.CreateSerializer(typeof(IIdentity), this.knownTypes, int.MaxValue));
- }
- else if (reader.IsStartElement(dictionary.ClaimSets, dictionary.EmptyString))
- {
- reader.ReadStartElement();
- DataContractSerializer claimSetSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(ClaimSet), this.knownTypes, int.MaxValue);
- DataContractSerializer claimSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(Claim), this.knownTypes, int.MaxValue);
- claimSets = new List<ClaimSet>(1);
- while (reader.IsStartElement())
- {
- claimSets.Add(SctClaimSerializer.DeserializeClaimSet(reader, dictionary, claimSetSerializer, claimSerializer));
- }
-
- reader.ReadEndElement();
- }
- else if (reader.IsStartElement(dictionary.IsCookieMode, dictionary.EmptyString))
- {
- isCookie = reader.ReadElementString() == "1" ? true : false;
- }
- else
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieXmlParseError));
- }
- }
- reader.ReadEndElement();
- if (cookieVersion != SupportedPersistanceVersion)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SerializedTokenVersionUnsupported, cookieVersion)));
- }
- if (cookieContextId == null)
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieValueMissingOrIncorrect, "ContextId"));
- }
- if (key == null || key.Length == 0)
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieValueMissingOrIncorrect, "Key"));
- }
- if (localId != id)
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieValueMissingOrIncorrect, "Id"));
- }
- List<IAuthorizationPolicy> authorizationPolicies;
- if (claimSets != null)
- {
- authorizationPolicies = new List<IAuthorizationPolicy>(1);
- authorizationPolicies.Add(new SctUnconditionalPolicy(identities, claimSets, expiryTime));
- }
- else
- {
- authorizationPolicies = null;
- }
- return new SecurityContextSecurityToken(cookieContextId, localId, key, effectiveTime, expiryTime,
- authorizationPolicies != null ? authorizationPolicies.AsReadOnly() : null, isCookie, cookieBlob, keyGeneration, keyEffectiveTime, keyExpirationTime);
- }
- public byte[] CreateCookieFromSecurityContext(UniqueId contextId, string id, byte[] key, DateTime tokenEffectiveTime,
- DateTime tokenExpirationTime, UniqueId keyGeneration, DateTime keyEffectiveTime, DateTime keyExpirationTime,
- ReadOnlyCollection<IAuthorizationPolicy> authorizationPolicies)
- {
- if (contextId == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextId");
- }
- if (key == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("key");
- }
- MemoryStream stream = new MemoryStream();
- XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream, SctClaimDictionary.Instance, null);
- SctClaimDictionary dictionary = SctClaimDictionary.Instance;
- writer.WriteStartElement(dictionary.SecurityContextSecurityToken, dictionary.EmptyString);
- writer.WriteStartElement(dictionary.Version, dictionary.EmptyString);
- writer.WriteValue(SupportedPersistanceVersion);
- writer.WriteEndElement();
- if (id != null)
- writer.WriteElementString(dictionary.Id, dictionary.EmptyString, id);
- XmlHelper.WriteElementStringAsUniqueId(writer, dictionary.ContextId, dictionary.EmptyString, contextId);
- writer.WriteStartElement(dictionary.Key, dictionary.EmptyString);
- writer.WriteBase64(key, 0, key.Length);
- writer.WriteEndElement();
- if (keyGeneration != null)
- {
- XmlHelper.WriteElementStringAsUniqueId(writer, dictionary.KeyGeneration, dictionary.EmptyString, keyGeneration);
- }
- XmlHelper.WriteElementContentAsInt64(writer, dictionary.EffectiveTime, dictionary.EmptyString, tokenEffectiveTime.ToUniversalTime().Ticks);
- XmlHelper.WriteElementContentAsInt64(writer, dictionary.ExpiryTime, dictionary.EmptyString, tokenExpirationTime.ToUniversalTime().Ticks);
- XmlHelper.WriteElementContentAsInt64(writer, dictionary.KeyEffectiveTime, dictionary.EmptyString, keyEffectiveTime.ToUniversalTime().Ticks);
- XmlHelper.WriteElementContentAsInt64(writer, dictionary.KeyExpiryTime, dictionary.EmptyString, keyExpirationTime.ToUniversalTime().Ticks);
- AuthorizationContext authContext = null;
- if (authorizationPolicies != null)
- authContext = AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies);
- if (authContext != null && authContext.ClaimSets.Count != 0)
- {
- DataContractSerializer identitySerializer = DataContractSerializerDefaults.CreateSerializer(typeof(IIdentity), this.knownTypes, int.MaxValue);
- DataContractSerializer claimSetSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(ClaimSet), this.knownTypes, int.MaxValue);
- DataContractSerializer claimSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(Claim), this.knownTypes, int.MaxValue);
- SctClaimSerializer.SerializeIdentities(authContext, dictionary, writer, identitySerializer);
- writer.WriteStartElement(dictionary.ClaimSets, dictionary.EmptyString);
- for (int i = 0; i < authContext.ClaimSets.Count; i++)
- {
- SctClaimSerializer.SerializeClaimSet(authContext.ClaimSets[i], dictionary, writer, claimSetSerializer, claimSerializer);
- }
- writer.WriteEndElement();
- }
- writer.WriteEndElement();
- writer.Flush();
- byte[] serializedContext = stream.ToArray();
- return this.securityStateEncoder.EncodeSecurityState(serializedContext);
- }
- public SecurityContextSecurityToken CreateSecurityContextFromCookie(byte[] encodedCookie, UniqueId contextId, UniqueId generation, string id, XmlDictionaryReaderQuotas quotas)
- {
- byte[] cookie = null;
- try
- {
- cookie = this.securityStateEncoder.DecodeSecurityState(encodedCookie);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieBlobDecodeFailure), e);
- }
- SecurityContextSecurityToken sct = DeserializeContext(cookie, encodedCookie, id, quotas);
- if (sct.ContextId != contextId)
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieValueMissingOrIncorrect, "ContextId"));
- }
- if (sct.KeyGeneration != generation)
- {
- OnInvalidCookieFailure(SR.GetString(SR.SctCookieValueMissingOrIncorrect, "KeyGeneration"));
- }
- return sct;
- }
-
- internal static void OnInvalidCookieFailure(string reason)
- {
- OnInvalidCookieFailure(reason, null);
- }
- internal static void OnInvalidCookieFailure(string reason, Exception e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.InvalidSecurityContextCookie, reason), e));
- }
- class SctUnconditionalPolicy : IAuthorizationPolicy
- {
- SecurityUniqueId id = SecurityUniqueId.Create();
- IList<IIdentity> identities;
- IList<ClaimSet> claimSets;
- DateTime expirationTime;
- public SctUnconditionalPolicy(IList<IIdentity> identities, IList<ClaimSet> claimSets, DateTime expirationTime)
- {
- this.identities = identities;
- this.claimSets = claimSets;
- this.expirationTime = expirationTime;
- }
- public string Id
- {
- get { return this.id.Value; }
- }
- public ClaimSet Issuer
- {
- get { return ClaimSet.System; }
- }
- public bool Evaluate(EvaluationContext evaluationContext, ref object state)
- {
- for (int i = 0; i < this.claimSets.Count; ++i)
- {
- evaluationContext.AddClaimSet(this, this.claimSets[i]);
- }
- if (this.identities != null)
- {
- object obj;
- if (!evaluationContext.Properties.TryGetValue(SecurityUtils.Identities, out obj))
- {
- evaluationContext.Properties.Add(SecurityUtils.Identities, this.identities);
- }
- else
- {
- // null if other overrides the property with something else
- List<IIdentity> dstIdentities = obj as List<IIdentity>;
- if (dstIdentities != null)
- {
- dstIdentities.AddRange(this.identities);
- }
- }
- }
- evaluationContext.RecordExpirationTime(this.expirationTime);
- return true;
- }
- }
- }
- }
|