| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System;
- using System.ServiceModel;
- using System.Security.Cryptography;
- using System.Security.Cryptography.X509Certificates;
- using System.ServiceModel.Security.Tokens;
- using System.IO;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Net.Mail;
- using System.Xml;
- using System.Runtime.Serialization;
- using System.IdentityModel.Claims;
- using System.IdentityModel.Policy;
- using System.Security.Principal;
- static class SctClaimSerializer
- {
- static void SerializeSid(SecurityIdentifier sid, SctClaimDictionary dictionary, XmlDictionaryWriter writer)
- {
- byte[] sidBytes = new byte[sid.BinaryLength];
- sid.GetBinaryForm(sidBytes, 0);
- writer.WriteBase64(sidBytes, 0, sidBytes.Length);
- }
- static void WriteRightAttribute(Claim claim, SctClaimDictionary dictionary, XmlDictionaryWriter writer)
- {
- if (Rights.PossessProperty.Equals(claim.Right))
- return;
- writer.WriteAttributeString(dictionary.Right, dictionary.EmptyString, claim.Right);
- }
- static string ReadRightAttribute(XmlDictionaryReader reader, SctClaimDictionary dictionary)
- {
- string right = reader.GetAttribute(dictionary.Right, dictionary.EmptyString);
- return String.IsNullOrEmpty(right) ? Rights.PossessProperty : right;
- }
- static void WriteSidAttribute(SecurityIdentifier sid, SctClaimDictionary dictionary, XmlDictionaryWriter writer)
- {
- byte[] sidBytes = new byte[sid.BinaryLength];
- sid.GetBinaryForm(sidBytes, 0);
- writer.WriteAttributeString(dictionary.Sid, dictionary.EmptyString, Convert.ToBase64String(sidBytes));
- }
- static SecurityIdentifier ReadSidAttribute(XmlDictionaryReader reader, SctClaimDictionary dictionary)
- {
- byte[] sidBytes = Convert.FromBase64String(reader.GetAttribute(dictionary.Sid, dictionary.EmptyString));
- return new SecurityIdentifier(sidBytes, 0);
- }
- public static void SerializeClaim(Claim claim, SctClaimDictionary dictionary, XmlDictionaryWriter writer, XmlObjectSerializer serializer)
- {
- // the order in which known claim types are checked is optimized for use patterns
- if (claim == null)
- {
- writer.WriteElementString(dictionary.NullValue, dictionary.EmptyString, string.Empty);
- return;
- }
- else if (ClaimTypes.Sid.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.WindowsSidClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- SerializeSid((SecurityIdentifier)claim.Resource, dictionary, writer);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.DenyOnlySid.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.DenyOnlySidClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- SerializeSid((SecurityIdentifier)claim.Resource, dictionary, writer);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.X500DistinguishedName.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.X500DistinguishedNameClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- byte[] rawData = ((X500DistinguishedName)claim.Resource).RawData;
- writer.WriteBase64(rawData, 0, rawData.Length);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Thumbprint.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.X509ThumbprintClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- byte[] thumbprint = (byte[])claim.Resource;
- writer.WriteBase64(thumbprint, 0, thumbprint.Length);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Name.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.NameClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString((string)claim.Resource);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Dns.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.DnsClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString((string)claim.Resource);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Rsa.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.RsaClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString(((RSA)claim.Resource).ToXmlString(false));
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Email.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.MailAddressClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString(((MailAddress)claim.Resource).Address);
- writer.WriteEndElement();
- return;
- }
- else if (claim == Claim.System)
- {
- writer.WriteElementString(dictionary.SystemClaim, dictionary.EmptyString, string.Empty);
- return;
- }
- else if (ClaimTypes.Hash.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.HashClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- byte[] hash = (byte[])claim.Resource;
- writer.WriteBase64(hash, 0, hash.Length);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Spn.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.SpnClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString((string)claim.Resource);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Upn.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.UpnClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString((string)claim.Resource);
- writer.WriteEndElement();
- return;
- }
- else if (ClaimTypes.Uri.Equals(claim.ClaimType))
- {
- writer.WriteStartElement(dictionary.UrlClaim, dictionary.EmptyString);
- WriteRightAttribute(claim, dictionary, writer);
- writer.WriteString(((Uri)claim.Resource).AbsoluteUri);
- writer.WriteEndElement();
- return;
- }
- else
- {
- // this is an extensible claim... need to delegate to xml object serializer
- serializer.WriteObject(writer, claim);
- }
- }
- public static void SerializeClaimSet(ClaimSet claimSet, SctClaimDictionary dictionary, XmlDictionaryWriter writer, XmlObjectSerializer serializer, XmlObjectSerializer claimSerializer)
- {
- if (claimSet is X509CertificateClaimSet)
- {
- X509CertificateClaimSet x509ClaimSet = (X509CertificateClaimSet)claimSet;
- writer.WriteStartElement(dictionary.X509CertificateClaimSet, dictionary.EmptyString);
- byte[] rawData = x509ClaimSet.X509Certificate.RawData;
- writer.WriteBase64(rawData, 0, rawData.Length);
- writer.WriteEndElement();
- }
- else if (claimSet == ClaimSet.System)
- {
- writer.WriteElementString(dictionary.SystemClaimSet, dictionary.EmptyString, String.Empty);
- }
- else if (claimSet == ClaimSet.Windows)
- {
- writer.WriteElementString(dictionary.WindowsClaimSet, dictionary.EmptyString, String.Empty);
- }
- else if (claimSet == ClaimSet.Anonymous)
- {
- writer.WriteElementString(dictionary.AnonymousClaimSet, dictionary.EmptyString, String.Empty);
- }
- else if (claimSet is WindowsClaimSet || claimSet is DefaultClaimSet)
- {
- writer.WriteStartElement(dictionary.ClaimSet, dictionary.EmptyString);
- writer.WriteStartElement(dictionary.PrimaryIssuer, dictionary.EmptyString);
- if (claimSet.Issuer == claimSet)
- {
- writer.WriteElementString(dictionary.NullValue, dictionary.EmptyString, string.Empty);
- }
- else
- {
- SerializeClaimSet(claimSet.Issuer, dictionary, writer, serializer, claimSerializer);
- }
- writer.WriteEndElement();
- foreach (Claim claim in claimSet)
- {
- writer.WriteStartElement(dictionary.Claim, dictionary.EmptyString);
- SerializeClaim(claim, dictionary, writer, claimSerializer);
- writer.WriteEndElement();
- }
- writer.WriteEndElement();
- }
- else
- {
- serializer.WriteObject(writer, claimSet);
- }
- }
- public static Claim DeserializeClaim(XmlDictionaryReader reader, SctClaimDictionary dictionary, XmlObjectSerializer serializer)
- {
- if (reader.IsStartElement(dictionary.NullValue, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return null;
- }
- else if (reader.IsStartElement(dictionary.WindowsSidClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- byte[] sidBytes = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Sid, new SecurityIdentifier(sidBytes, 0), right);
- }
- else if (reader.IsStartElement(dictionary.DenyOnlySidClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- byte[] sidBytes = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.DenyOnlySid, new SecurityIdentifier(sidBytes, 0), right);
- }
- else if (reader.IsStartElement(dictionary.X500DistinguishedNameClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- byte[] rawData = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.X500DistinguishedName, new X500DistinguishedName(rawData), right);
- }
- else if (reader.IsStartElement(dictionary.X509ThumbprintClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- byte[] thumbprint = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Thumbprint, thumbprint, right);
- }
- else if (reader.IsStartElement(dictionary.NameClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string name = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Name, name, right);
- }
- else if (reader.IsStartElement(dictionary.DnsClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string dns = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Dns, dns, right);
- }
- else if (reader.IsStartElement(dictionary.RsaClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string rsaXml = reader.ReadString();
- reader.ReadEndElement();
- System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider();
- rsa.FromXmlString(rsaXml);
- return new Claim(ClaimTypes.Rsa, rsa, right);
- }
- else if (reader.IsStartElement(dictionary.MailAddressClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string address = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Email, new System.Net.Mail.MailAddress(address), right);
- }
- else if (reader.IsStartElement(dictionary.SystemClaim, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return Claim.System;
- }
- else if (reader.IsStartElement(dictionary.HashClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- byte[] hash = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Hash, hash, right);
- }
- else if (reader.IsStartElement(dictionary.SpnClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string spn = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Spn, spn, right);
- }
- else if (reader.IsStartElement(dictionary.UpnClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string upn = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Upn, upn, right);
- }
- else if (reader.IsStartElement(dictionary.UrlClaim, dictionary.EmptyString))
- {
- string right = ReadRightAttribute(reader, dictionary);
- reader.ReadStartElement();
- string url = reader.ReadString();
- reader.ReadEndElement();
- return new Claim(ClaimTypes.Uri, new Uri(url), right);
- }
- else
- {
- return (Claim)serializer.ReadObject(reader);
- }
- }
- public static ClaimSet DeserializeClaimSet(XmlDictionaryReader reader, SctClaimDictionary dictionary, XmlObjectSerializer serializer, XmlObjectSerializer claimSerializer)
- {
- if (reader.IsStartElement(dictionary.NullValue, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return null;
- }
- else if (reader.IsStartElement(dictionary.X509CertificateClaimSet, dictionary.EmptyString))
- {
- reader.ReadStartElement();
- byte[] rawData = reader.ReadContentAsBase64();
- reader.ReadEndElement();
- return new X509CertificateClaimSet(new X509Certificate2(rawData), false);
- }
- else if (reader.IsStartElement(dictionary.SystemClaimSet, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return ClaimSet.System;
- }
- else if (reader.IsStartElement(dictionary.WindowsClaimSet, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return ClaimSet.Windows;
- }
- else if (reader.IsStartElement(dictionary.AnonymousClaimSet, dictionary.EmptyString))
- {
- reader.ReadElementString();
- return ClaimSet.Anonymous;
- }
- else if (reader.IsStartElement(dictionary.ClaimSet, dictionary.EmptyString))
- {
- ClaimSet issuer = null;
- List<Claim> claims = new List<Claim>();
- reader.ReadStartElement();
- if (reader.IsStartElement(dictionary.PrimaryIssuer, dictionary.EmptyString))
- {
- reader.ReadStartElement();
- issuer = DeserializeClaimSet(reader, dictionary, serializer, claimSerializer);
- reader.ReadEndElement();
- }
- while (reader.IsStartElement())
- {
- reader.ReadStartElement();
- claims.Add(DeserializeClaim(reader, dictionary, claimSerializer));
- reader.ReadEndElement();
- }
- reader.ReadEndElement();
- return issuer != null ? new DefaultClaimSet(issuer, claims) : new DefaultClaimSet(claims);
- }
- else
- {
- return (ClaimSet)serializer.ReadObject(reader);
- }
- }
- public static void SerializeIdentities(AuthorizationContext authContext, SctClaimDictionary dictionary, XmlDictionaryWriter writer, XmlObjectSerializer serializer)
- {
- object obj;
- IList<IIdentity> identities;
- if (authContext.Properties.TryGetValue(SecurityUtils.Identities, out obj))
- {
- identities = obj as IList<IIdentity>;
- if (identities != null && identities.Count > 0)
- {
- writer.WriteStartElement(dictionary.Identities, dictionary.EmptyString);
- for (int i = 0; i < identities.Count; ++i)
- {
- SerializePrimaryIdentity(identities[i], dictionary, writer, serializer);
- }
- writer.WriteEndElement();
- }
- }
- }
- static void SerializePrimaryIdentity(IIdentity identity, SctClaimDictionary dictionary, XmlDictionaryWriter writer, XmlObjectSerializer serializer)
- {
- if (identity != null && identity != SecurityUtils.AnonymousIdentity)
- {
- writer.WriteStartElement(dictionary.PrimaryIdentity, dictionary.EmptyString);
- if (identity is WindowsIdentity)
- {
- WindowsIdentity wid = (WindowsIdentity)identity;
- writer.WriteStartElement(dictionary.WindowsSidIdentity, dictionary.EmptyString);
- WriteSidAttribute(wid.User, dictionary, writer);
- // This is to work around WOW64 bug Windows OS 1491447
- string authenticationType = null;
- using (WindowsIdentity self = WindowsIdentity.GetCurrent())
- {
- // is owner or admin? AuthenticationType could throw un-authorized exception
- if ((self.User == wid.Owner) ||
- (wid.Owner != null && self.Groups.Contains(wid.Owner)) ||
- (wid.Owner != SecurityUtils.AdministratorsSid && self.Groups.Contains(SecurityUtils.AdministratorsSid)))
- {
- authenticationType = wid.AuthenticationType;
- }
- }
- if (!String.IsNullOrEmpty(authenticationType))
- writer.WriteAttributeString(dictionary.AuthenticationType, dictionary.EmptyString, authenticationType);
- writer.WriteString(wid.Name);
- writer.WriteEndElement();
- }
- else if (identity is WindowsSidIdentity)
- {
- WindowsSidIdentity wsid = (WindowsSidIdentity)identity;
- writer.WriteStartElement(dictionary.WindowsSidIdentity, dictionary.EmptyString);
- WriteSidAttribute(wsid.SecurityIdentifier, dictionary, writer);
- if (!String.IsNullOrEmpty(wsid.AuthenticationType))
- writer.WriteAttributeString(dictionary.AuthenticationType, dictionary.EmptyString, wsid.AuthenticationType);
- writer.WriteString(wsid.Name);
- writer.WriteEndElement();
- }
- else if (identity is GenericIdentity)
- {
- GenericIdentity genericIdentity = (GenericIdentity)identity;
- writer.WriteStartElement(dictionary.GenericIdentity, dictionary.EmptyString);
- if (!String.IsNullOrEmpty(genericIdentity.AuthenticationType))
- writer.WriteAttributeString(dictionary.AuthenticationType, dictionary.EmptyString, genericIdentity.AuthenticationType);
- writer.WriteString(genericIdentity.Name);
- writer.WriteEndElement();
- }
- else
- {
- serializer.WriteObject(writer, identity);
- }
- writer.WriteEndElement();
- }
- }
- public static IList<IIdentity> DeserializeIdentities(XmlDictionaryReader reader, SctClaimDictionary dictionary, XmlObjectSerializer serializer)
- {
- List<IIdentity> identities = null;
- if (reader.IsStartElement(dictionary.Identities, dictionary.EmptyString))
- {
- identities = new List<IIdentity>();
- reader.ReadStartElement();
- while (reader.IsStartElement(dictionary.PrimaryIdentity, dictionary.EmptyString))
- {
- IIdentity identity = DeserializePrimaryIdentity(reader, dictionary, serializer);
- if (identity != null && identity != SecurityUtils.AnonymousIdentity)
- {
- identities.Add(identity);
- }
- }
- reader.ReadEndElement();
- }
- return identities;
- }
- static IIdentity DeserializePrimaryIdentity(XmlDictionaryReader reader, SctClaimDictionary dictionary, XmlObjectSerializer serializer)
- {
- IIdentity identity = null;
- if (reader.IsStartElement(dictionary.PrimaryIdentity, dictionary.EmptyString))
- {
- reader.ReadStartElement();
- if (reader.IsStartElement(dictionary.WindowsSidIdentity, dictionary.EmptyString))
- {
- SecurityIdentifier sid = ReadSidAttribute(reader, dictionary);
- string authenticationType = reader.GetAttribute(dictionary.AuthenticationType, dictionary.EmptyString);
- reader.ReadStartElement();
- string name = reader.ReadContentAsString();
- identity = new WindowsSidIdentity(sid, name, authenticationType ?? String.Empty);
- reader.ReadEndElement();
- }
- else if (reader.IsStartElement(dictionary.GenericIdentity, dictionary.EmptyString))
- {
- string authenticationType = reader.GetAttribute(dictionary.AuthenticationType, dictionary.EmptyString);
- reader.ReadStartElement();
- string name = reader.ReadContentAsString();
- identity = SecurityUtils.CreateIdentity(name, authenticationType ?? String.Empty);
- reader.ReadEndElement();
- }
- else
- {
- identity = (IIdentity)serializer.ReadObject(reader);
- }
- reader.ReadEndElement();
- }
- return identity;
- }
- }
- }
|