You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			333 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			333 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| //     Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Collections.ObjectModel;
 | |
| using System.Diagnostics;
 | |
| using System.IdentityModel.Diagnostics;
 | |
| using System.IdentityModel.Policy;
 | |
| using System.Security.Claims;
 | |
| using System.Security.Principal;
 | |
| 
 | |
| using SysClaimSet = System.IdentityModel.Claims.ClaimSet;
 | |
| 
 | |
| namespace System.IdentityModel.Tokens
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Defines an AuthorizationPolicy that carries the IDFx Claims. When IDFx is enabled 
 | |
|     /// a new set of Security Token Authenticators are added to the system. These Authenticators 
 | |
|     /// will generate the new Claims defined in System.Security.Claims.
 | |
|     /// </summary>
 | |
|     internal class AuthorizationPolicy : IAuthorizationPolicy
 | |
|     {
 | |
| #pragma warning disable 1591
 | |
|         public const string ClaimsPrincipalKey = "ClaimsPrincipal"; // This key must be different from "Principal". "Principal" is reserved for Custom mode.
 | |
|         public const string IdentitiesKey = "Identities";
 | |
| #pragma warning restore 1591
 | |
| 
 | |
|         List<ClaimsIdentity> _identityCollection = new List<ClaimsIdentity>();
 | |
| 
 | |
|         //
 | |
|         // Add an issuer to specify that this is a IDFx issued AuthorizationPolicy.
 | |
|         //
 | |
|         SysClaimSet _issuer = SysClaimSet.System;
 | |
|         string _id = UniqueId.CreateUniqueId();
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Initializes an instance of <see cref="AuthorizationPolicy"/>
 | |
|         /// </summary>
 | |
|         public AuthorizationPolicy()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Initializes an instance of <see cref="AuthorizationPolicy"/>
 | |
|         /// </summary>
 | |
|         /// <param name="identity">ClaimsIdentity for the AuthorizationPolicy.</param>
 | |
|         /// <exception cref="ArgumentNullException">One of the input argument is null.</exception>
 | |
|         public AuthorizationPolicy(ClaimsIdentity identity)
 | |
|         {
 | |
|             if (identity == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
 | |
|             }
 | |
| 
 | |
|             _identityCollection.Add(identity);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Initializes an instance of <see cref="AuthorizationPolicy"/>
 | |
|         /// </summary>
 | |
|         /// <param name="identityCollection">Collection of identities.</param>
 | |
|         public AuthorizationPolicy(IEnumerable<ClaimsIdentity> identityCollection)
 | |
|         {
 | |
|             if (identityCollection == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identityCollection");
 | |
|             }
 | |
| 
 | |
|             List<ClaimsIdentity> collection = new List<ClaimsIdentity>();
 | |
|             foreach (ClaimsIdentity identity in identityCollection)
 | |
|             {
 | |
|                 collection.Add(identity);
 | |
|             }
 | |
| 
 | |
|             _identityCollection = collection;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a ClaimsIdentity collection.
 | |
|         /// </summary>
 | |
|         public ReadOnlyCollection<ClaimsIdentity> IdentityCollection
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _identityCollection.AsReadOnly();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #region IAuthorizationPolicy Members
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Evaluates the current Policy. This is provided for backward compatibility
 | |
|         /// of WCF Claims model. We always return true without affecting the EvaluationContext.
 | |
|         /// </summary>
 | |
|         /// <param name="evaluationContext">The current EvaluationContext.</param>
 | |
|         /// <param name="state">The reference state object.</param>
 | |
|         /// <returns>True if the Policy was successfully applied.</returns>
 | |
|         public bool Evaluate(EvaluationContext evaluationContext, ref object state)
 | |
|         {
 | |
|             if (null == evaluationContext || null == evaluationContext.Properties)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("evaluationContext");
 | |
|             }
 | |
| 
 | |
|             if (0 == _identityCollection.Count)
 | |
|             {
 | |
|                 //
 | |
|                 // Nothing to do here.
 | |
|                 //
 | |
|                 return true;
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Locate or create the ClaimsPrincipal
 | |
|             //
 | |
|             object principalObj = null;
 | |
|             if (!evaluationContext.Properties.TryGetValue(ClaimsPrincipalKey, out principalObj))
 | |
|             {
 | |
|                 ClaimsPrincipal principalToAdd = CreateClaimsPrincipalFromIdentities(_identityCollection);
 | |
| 
 | |
|                 evaluationContext.Properties.Add(ClaimsPrincipalKey, principalToAdd);
 | |
| 
 | |
|                 if (DiagnosticUtility.ShouldTrace(TraceEventType.Information))
 | |
|                 {
 | |
|                     TraceUtility.TraceEvent(
 | |
|                         TraceEventType.Information,
 | |
|                         TraceCode.Diagnostics,
 | |
|                         SR.GetString(SR.TraceSetPrincipalOnEvaluationContext),
 | |
|                         new ClaimsPrincipalTraceRecord(principalToAdd),
 | |
|                         null,
 | |
|                         null);
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 ClaimsPrincipal principal = principalObj as ClaimsPrincipal;
 | |
|                 if (null != principal && null != principal.Identities)
 | |
|                 {
 | |
|                     principal.AddIdentities(_identityCollection);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     //
 | |
|                     // Someone stomped on our ClaimsPrincipal property key in the properties collection
 | |
|                     // Just trace this for now.
 | |
|                     //
 | |
|                     if (DiagnosticUtility.ShouldTrace(TraceEventType.Error))
 | |
|                     {
 | |
|                         TraceUtility.TraceString(
 | |
|                             TraceEventType.Error,
 | |
|                             SR.GetString(SR.ID8004,
 | |
|                             ClaimsPrincipalKey));
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Locate or create evaluationContext.Properties[ "Identities" ] with identities
 | |
|             //
 | |
|             object identitiesObj = null;
 | |
|             if (!evaluationContext.Properties.TryGetValue(IdentitiesKey, out identitiesObj))
 | |
|             {
 | |
|                 List<ClaimsIdentity> identities = new List<ClaimsIdentity>();
 | |
|                 foreach (ClaimsIdentity ici in _identityCollection)
 | |
|                 {
 | |
|                     identities.Add(ici);
 | |
|                 }
 | |
| 
 | |
|                 evaluationContext.Properties.Add(IdentitiesKey, identities);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 List<ClaimsIdentity> identities;
 | |
|                 identities = identitiesObj as List<ClaimsIdentity>;
 | |
| 
 | |
|                 foreach (ClaimsIdentity ici in _identityCollection)
 | |
|                 {
 | |
|                     identities.Add(ici);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
| 
 | |
|             return true;
 | |
|         }
 | |
| 
 | |
|         private static ClaimsPrincipal CreateClaimsPrincipalFromIdentities(IEnumerable<ClaimsIdentity> identities)
 | |
|         {
 | |
|             ClaimsIdentity selectedClaimsIdentity = SelectPrimaryIdentity(identities);
 | |
| 
 | |
|             if (selectedClaimsIdentity == null)
 | |
|             {
 | |
|                 //return an anonymous identity
 | |
|                 return new ClaimsPrincipal(new ClaimsIdentity());
 | |
|             }
 | |
| 
 | |
|             ClaimsPrincipal principal = CreateFromIdentity(selectedClaimsIdentity);
 | |
| 
 | |
|             // Add the remaining identities.
 | |
|             foreach (ClaimsIdentity identity in identities)
 | |
|             {
 | |
|                 if (identity != selectedClaimsIdentity)
 | |
|                 {
 | |
|                     principal.AddIdentity(identity);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return principal;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates the appropriate implementation of an IClaimsPrincipal base on the
 | |
|         /// type of the specified IIdentity (e.g. WindowsClaimsPrincipal for a WindowsIdentity). 
 | |
|         /// Note the appropriate IClaimsIdentity is generated based on the specified IIdentity
 | |
|         /// as well.
 | |
|         /// </summary>
 | |
|         /// <param name="identity">An implementation of IIdentity</param>
 | |
|         /// <returns>A claims-based principal.</returns>
 | |
|         private static ClaimsPrincipal CreateFromIdentity(IIdentity identity)
 | |
|         {
 | |
|             if (null == identity)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identity");
 | |
|             }
 | |
| 
 | |
|             WindowsIdentity wci = identity as WindowsIdentity;
 | |
|             if (null != wci)
 | |
|             {
 | |
|                 return new WindowsPrincipal(wci);
 | |
|             }
 | |
| 
 | |
|             WindowsIdentity wi = identity as WindowsIdentity;
 | |
|             if (null != wi)
 | |
|             {
 | |
|                 return new WindowsPrincipal(wi);
 | |
|             }
 | |
| 
 | |
|             ClaimsIdentity ici = identity as ClaimsIdentity;
 | |
|             if (null != ici)
 | |
|             {
 | |
|                 return new ClaimsPrincipal(ici);
 | |
|             }
 | |
| 
 | |
|             return new ClaimsPrincipal(new ClaimsIdentity(identity));
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// This method iterates through the collection of ClaimsIdentities
 | |
|         /// and determines which identity must be used as the primary one.
 | |
|         /// </summary>
 | |
|         /// <remarks>
 | |
|         /// If the identities collection contains a WindowsClaimsIdentity, it is the most preferred.
 | |
|         /// If the identities collection contains an RsaClaimsIdentity, it is the least preferred.
 | |
|         /// </remarks>
 | |
|         private static ClaimsIdentity SelectPrimaryIdentity(IEnumerable<ClaimsIdentity> identities)
 | |
|         {
 | |
|             if (identities == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("identities");
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Loop through the identities to determine the primary identity.
 | |
|             //
 | |
|             ClaimsIdentity selectedClaimsIdentity = null;
 | |
| 
 | |
|             foreach (ClaimsIdentity identity in identities)
 | |
|             {
 | |
|                 if (identity is WindowsIdentity)
 | |
|                 {
 | |
|                     //
 | |
|                     // If there is a WindowsIdentity, return that.
 | |
|                     //
 | |
|                     selectedClaimsIdentity = identity;
 | |
|                     break;
 | |
|                 }
 | |
|                 else if (identity.FindFirst(ClaimTypes.Rsa) != null)
 | |
|                 {
 | |
|                     //this is a RSA identity
 | |
|                     //it is the least preffered identity
 | |
|                     if (selectedClaimsIdentity == null)
 | |
|                     {
 | |
|                         selectedClaimsIdentity = identity;
 | |
|                     }
 | |
| 
 | |
|                     continue;
 | |
|                 }
 | |
|                 else if (selectedClaimsIdentity == null)
 | |
|                 {
 | |
|                     //
 | |
|                     // If no primary identity has been selected yet, choose the current identity.
 | |
|                     //
 | |
|                     selectedClaimsIdentity = identity;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return selectedClaimsIdentity;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the Issuer Claimset. This will return a DefaultClaimSet with just one claim 
 | |
|         /// whose ClaimType is http://schemas.microsoft.com/claims/identityclaim.
 | |
|         /// </summary>
 | |
|         public SysClaimSet Issuer
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _issuer;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
| 
 | |
|         #region IAuthorizationComponent Members
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Returns an Id for the ClaimsPrincipal.
 | |
|         /// </summary>
 | |
|         public string Id
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _id;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         #endregion
 | |
|     }
 | |
| 
 | |
| }
 |