//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Security { using System.IdentityModel.Policy; using System.Collections.ObjectModel; using System.IdentityModel.Claims; using System.Collections.Generic; using System.Runtime.Serialization; using System.IO; using System.Xml; using System.ServiceModel.Dispatcher; using System.Security.Principal; using System.ServiceModel.Security.Tokens; [Serializable] class SerializableAuthorizationContext { static readonly IList redBitsKnownType = new List( new Type[] { typeof(DefaultClaimSet), typeof(WindowsClaimSet), typeof(X509CertificateClaimSet), typeof(Claim) }); byte[] contextBlob; DateTime expirationTime; string id; IList knownTypes; SerializableAuthorizationContext(byte[] contextBlob, DateTime expirationTime, string id, IList knownTypes) { if (contextBlob == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextBlob"); } this.expirationTime = expirationTime; this.id = id; this.contextBlob = contextBlob; this.knownTypes = knownTypes; } public static SerializableAuthorizationContext From(AuthorizationContext authorizationContext) { if (authorizationContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext"); } IList knownTypes = BuildKnownClaimTypes(authorizationContext); byte[] contextBlob = CreateSerializableBlob(authorizationContext, knownTypes); return new SerializableAuthorizationContext(contextBlob, authorizationContext.ExpirationTime, authorizationContext.Id, knownTypes); } public AuthorizationContext Retrieve() { List authorizationPolicies = new List(1); authorizationPolicies.Add(RetrievePolicyFromBlob(this.contextBlob, this.id, this.expirationTime, this.knownTypes)); return AuthorizationContext.CreateDefaultAuthorizationContext(authorizationPolicies); } static IList BuildKnownClaimTypes(AuthorizationContext authorizationContext) { List knownTypes = new List(); foreach (ClaimSet claimSet in authorizationContext.ClaimSets) { Type claimSetType = claimSet.GetType(); if (!redBitsKnownType.Contains(claimSetType) && !knownTypes.Contains(claimSetType)) { knownTypes.Add(claimSetType); } foreach (Claim claim in claimSet) { Type claimType = claim.GetType(); if (!redBitsKnownType.Contains(claimType) && !knownTypes.Contains(claimType)) { knownTypes.Add(claimType); } } } if (knownTypes.Count != 0) { return knownTypes; } return null; } static byte[] CreateSerializableBlob(AuthorizationContext authorizationContext, IList knownTypes) { if (authorizationContext == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("authorizationContext"); } MemoryStream stream = new MemoryStream(); XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream, SctClaimDictionary.Instance, null); SctClaimDictionary claimDictionary = SctClaimDictionary.Instance; writer.WriteStartElement(claimDictionary.SecurityContextSecurityToken, claimDictionary.EmptyString); writer.WriteStartElement(claimDictionary.Version, claimDictionary.EmptyString); writer.WriteValue(1); writer.WriteEndElement(); if ((authorizationContext != null) && (authorizationContext.ClaimSets.Count != 0)) { DataContractSerializer identitySerializer = DataContractSerializerDefaults.CreateSerializer(typeof(IIdentity), knownTypes, 0x7fffffff); DataContractSerializer claimSetSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(ClaimSet), knownTypes, 0x7fffffff); DataContractSerializer claimSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(Claim), knownTypes, 0x7fffffff); SctClaimSerializer.SerializeIdentities(authorizationContext, claimDictionary, writer, identitySerializer); writer.WriteStartElement(claimDictionary.ClaimSets, claimDictionary.EmptyString); for (int i = 0; i < authorizationContext.ClaimSets.Count; i++) { SctClaimSerializer.SerializeClaimSet(authorizationContext.ClaimSets[i], claimDictionary, writer, claimSetSerializer, claimSerializer); } writer.WriteEndElement(); } writer.WriteEndElement(); writer.Flush(); return stream.ToArray(); } static IAuthorizationPolicy RetrievePolicyFromBlob(byte[] contextBlob, string id, DateTime expirationTime, IList knownTypes) { if (contextBlob == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contextBlob"); } if (id == null) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("id"); } SctClaimDictionary claimDictionary = SctClaimDictionary.Instance; XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(contextBlob, 0, contextBlob.Length, claimDictionary, XmlDictionaryReaderQuotas.Max, null, null); IList identities = null; IList claimSets = null; int versionNumber = -1; reader.ReadFullStartElement(claimDictionary.SecurityContextSecurityToken, claimDictionary.EmptyString); while (reader.IsStartElement()) { if (reader.IsStartElement(claimDictionary.Version, claimDictionary.EmptyString)) { versionNumber = reader.ReadElementContentAsInt(); if (versionNumber != 1) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR2.GetString(SR2.SerializedAuthorizationContextVersionUnsupported, versionNumber))); } } else { if (reader.IsStartElement(claimDictionary.Identities, claimDictionary.EmptyString)) { identities = SctClaimSerializer.DeserializeIdentities(reader, claimDictionary, DataContractSerializerDefaults.CreateSerializer(typeof(IIdentity), knownTypes, 0x7fffffff)); continue; } if (reader.IsStartElement(claimDictionary.ClaimSets, claimDictionary.EmptyString)) { reader.ReadStartElement(); DataContractSerializer claimSetSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(ClaimSet), knownTypes, 0x7fffffff); DataContractSerializer claimSerializer = DataContractSerializerDefaults.CreateSerializer(typeof(Claim), knownTypes, 0x7fffffff); claimSets = new List(1); while (reader.IsStartElement()) { claimSets.Add(SctClaimSerializer.DeserializeClaimSet(reader, claimDictionary, claimSetSerializer, claimSerializer)); } reader.ReadEndElement(); continue; } } } reader.ReadEndElement(); return new SctUnconditionalPolicy(identities, id, claimSets, expirationTime); } class SctUnconditionalPolicy : IAuthorizationPolicy, IAuthorizationComponent { IList claimSets; DateTime expirationTime; string id; IList identities; public SctUnconditionalPolicy(IList identities, string id, IList claimSets, DateTime expirationTime) { this.identities = identities; this.claimSets = claimSets; this.expirationTime = expirationTime; this.id = id; } public string Id { get { return this.id; } } public ClaimSet Issuer { get { return ClaimSet.System; } } public bool Evaluate(EvaluationContext evaluationContext, ref object state) { for (int num1 = 0; num1 < this.claimSets.Count; num1++) { evaluationContext.AddClaimSet(this, this.claimSets[num1]); } if (this.identities != null) { object obj; if (!evaluationContext.Properties.TryGetValue("Identities", out obj)) { evaluationContext.Properties.Add("Identities", (object)this.identities); } else { List identities = obj as List; if (identities != null) { identities.AddRange(this.identities); } } } evaluationContext.RecordExpirationTime(this.expirationTime); return true; } } } }