You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			419 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			419 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------
 | |
| namespace System.IdentityModel.Tokens
 | |
| {
 | |
|     using System.Collections.Generic;
 | |
|     using System.Diagnostics;
 | |
|     using System.IdentityModel.Configuration;
 | |
|     using System.IdentityModel.Diagnostics;
 | |
|     using System.IdentityModel.Selectors;
 | |
|     using System.Security.Claims;
 | |
|     using System.Security.Cryptography.X509Certificates;
 | |
|     using System.ServiceModel.Security;
 | |
|     using System.Text;
 | |
|     using System.Xml;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// Extends SecurityTokenRequirement by adding new properties which are
 | |
|     /// useful for issued tokens.
 | |
|     /// </summary>
 | |
|     public class SamlSecurityTokenRequirement
 | |
|     {
 | |
| 
 | |
|         //
 | |
|         // The below defaults will only be used if some verification properties are set in config and others are not
 | |
|         //
 | |
|         static X509RevocationMode DefaultRevocationMode = X509RevocationMode.Online;
 | |
|         static X509CertificateValidationMode DefaultValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
 | |
|         static StoreLocation DefaultStoreLocation = StoreLocation.LocalMachine;
 | |
| 
 | |
|         string _nameClaimType = ClaimsIdentity.DefaultNameClaimType;
 | |
|         string _roleClaimType = ClaimTypes.Role;
 | |
| 
 | |
|         bool _mapToWindows;
 | |
|         
 | |
|         X509CertificateValidator _certificateValidator;
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates an instance of <see cref="SamlSecurityTokenRequirement"/>
 | |
|         /// </summary>
 | |
|         public SamlSecurityTokenRequirement()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates an instance of <see cref="SamlSecurityTokenRequirement"/>
 | |
|         /// <param name="element">The XmlElement from which the instance is to be loaded.</param>
 | |
|         /// </summary>
 | |
|         public SamlSecurityTokenRequirement(XmlElement element)
 | |
|         {
 | |
|             if (element == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("element");
 | |
|             }
 | |
| 
 | |
|             if (element.LocalName != ConfigurationStrings.SamlSecurityTokenRequirement)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7000, ConfigurationStrings.SamlSecurityTokenRequirement, element.LocalName));
 | |
|             }
 | |
| 
 | |
|             bool foundCustomX509Validator = false;
 | |
|             X509RevocationMode revocationMode = DefaultRevocationMode;
 | |
|             X509CertificateValidationMode certificateValidationMode = DefaultValidationMode;
 | |
|             StoreLocation trustedStoreLocation = DefaultStoreLocation;
 | |
|             string customValidator = null;
 | |
| 
 | |
|             foreach (XmlAttribute attribute in element.Attributes)
 | |
|             {
 | |
|                 if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.MapToWindows))
 | |
|                 {
 | |
|                     bool outMapToWindows = false;
 | |
|                     if (!bool.TryParse(attribute.Value, out outMapToWindows))
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7022, attribute.Value));
 | |
|                     }
 | |
|                     this.MapToWindows = outMapToWindows;
 | |
|                 }                
 | |
|                 else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateValidator))
 | |
|                 {
 | |
|                     customValidator = attribute.Value.ToString();
 | |
|                 }
 | |
|                 else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateRevocationMode))
 | |
|                 {
 | |
|                     foundCustomX509Validator = true;
 | |
| 
 | |
|                     string revocationModeString = attribute.Value.ToString();
 | |
| 
 | |
|                     if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeNoCheck))
 | |
|                     {
 | |
|                         revocationMode = X509RevocationMode.NoCheck;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOffline))
 | |
|                     {
 | |
|                         revocationMode = X509RevocationMode.Offline;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(revocationModeString, ConfigurationStrings.X509RevocationModeOnline))
 | |
|                     {
 | |
|                         revocationMode = X509RevocationMode.Online;
 | |
|                     }
 | |
| 
 | |
|                     else
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName)));
 | |
|                     }
 | |
|                 }
 | |
|                 else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateValidationMode))
 | |
|                 {
 | |
|                     foundCustomX509Validator = true;
 | |
| 
 | |
|                     string validationModeString = attribute.Value.ToString();
 | |
| 
 | |
|                     if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeChainTrust))
 | |
|                     {
 | |
|                         certificateValidationMode = X509CertificateValidationMode.ChainTrust;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerOrChainTrust))
 | |
|                     {
 | |
|                         certificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModePeerTrust))
 | |
|                     {
 | |
|                         certificateValidationMode = X509CertificateValidationMode.PeerTrust;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeNone))
 | |
|                     {
 | |
|                         certificateValidationMode = X509CertificateValidationMode.None;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(validationModeString, ConfigurationStrings.X509CertificateValidationModeCustom))
 | |
|                     {
 | |
|                         certificateValidationMode = X509CertificateValidationMode.Custom;
 | |
|                     }
 | |
| 
 | |
|                     else
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName)));
 | |
|                     }
 | |
|                 }
 | |
|                 else if (StringComparer.OrdinalIgnoreCase.Equals(attribute.LocalName, ConfigurationStrings.IssuerCertificateTrustedStoreLocation))
 | |
|                 {
 | |
|                     foundCustomX509Validator = true;
 | |
| 
 | |
|                     string trustedStoreLocationString = attribute.Value.ToString();
 | |
| 
 | |
|                     if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationCurrentUser))
 | |
|                     {
 | |
|                         trustedStoreLocation = StoreLocation.CurrentUser;
 | |
|                     }
 | |
| 
 | |
|                     else if (StringComparer.OrdinalIgnoreCase.Equals(trustedStoreLocationString, ConfigurationStrings.X509TrustedStoreLocationLocalMachine))
 | |
|                     {
 | |
|                         trustedStoreLocation = StoreLocation.LocalMachine;
 | |
|                     }
 | |
| 
 | |
|                     else
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7011, attribute.LocalName, element.LocalName)));
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID7004, attribute.LocalName, element.LocalName)));
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             List<XmlElement> configElements = XmlUtil.GetXmlElements(element.ChildNodes);
 | |
| 
 | |
|             foreach (XmlElement childElement in configElements)
 | |
|             {
 | |
|                 if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.NameClaimType))
 | |
|                 {
 | |
|                     if (childElement.Attributes.Count != 1 || !StringComparer.Ordinal.Equals(childElement.Attributes[0].LocalName, ConfigurationStrings.Value))
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7001, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", element.LocalName, childElement.LocalName), ConfigurationStrings.Value));
 | |
|                     }
 | |
|                     this.NameClaimType = childElement.Attributes[0].Value;
 | |
|                 }
 | |
|                 else if (StringComparer.Ordinal.Equals(childElement.LocalName, ConfigurationStrings.RoleClaimType))
 | |
|                 {
 | |
|                     if (childElement.Attributes.Count != 1 || !StringComparer.Ordinal.Equals(childElement.Attributes[0].LocalName, ConfigurationStrings.Value))
 | |
|                     {
 | |
|                         throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7001, String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}/{1}", element.LocalName, childElement.LocalName), ConfigurationStrings.Value));
 | |
|                     }
 | |
|                     this.RoleClaimType = childElement.Attributes[0].Value;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7002, childElement.LocalName, ConfigurationStrings.SamlSecurityTokenRequirement));
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (certificateValidationMode == X509CertificateValidationMode.Custom)
 | |
|             {
 | |
|                 if (string.IsNullOrEmpty(customValidator))
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID7028));
 | |
|                 }
 | |
| 
 | |
|                 Type customValidatorType = Type.GetType(customValidator, true);
 | |
| 
 | |
|                 if (customValidatorType == null)
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.ID7007, customValidatorType));
 | |
|                 }
 | |
| 
 | |
|                 _certificateValidator = CustomTypeElement.Resolve<X509CertificateValidator>(new CustomTypeElement(customValidatorType));
 | |
|             }
 | |
|             else if (foundCustomX509Validator)
 | |
|             {
 | |
|                 _certificateValidator = X509Util.CreateCertificateValidator(certificateValidationMode, revocationMode, trustedStoreLocation);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets/sets the X509CertificateValidator associated with this token requirement
 | |
|         /// </summary>
 | |
|         public X509CertificateValidator CertificateValidator
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _certificateValidator;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 if (value == null)
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
 | |
|                 }
 | |
|                 _certificateValidator = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets or sets the Claim Type that will be used to generate the 
 | |
|         /// FederatedIdentity.Name property.
 | |
|         /// </summary>
 | |
|         public string NameClaimType
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _nameClaimType;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _nameClaimType = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the Claim Types that are used to generate the
 | |
|         /// FederatedIdentity.Roles property.
 | |
|         /// </summary>
 | |
|         public string RoleClaimType
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return _roleClaimType;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
|                 _roleClaimType = value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Determines if the token handler will attempt to map the SAML identity to a
 | |
|         /// Windows identity via the unique principal name (UPN) claim.
 | |
|         /// </summary>
 | |
|         public bool MapToWindows
 | |
|         {
 | |
|             get { return _mapToWindows; }
 | |
|             set { _mapToWindows = value; }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Checks if Audience Enforcement checks are required for the given token 
 | |
|         /// based on this SamlSecurityTokenRequirement settings.
 | |
|         /// </summary>
 | |
|         /// <param name="audienceUriMode">
 | |
|         /// The <see cref="AudienceUriMode"/> defining the audience requirement.
 | |
|         /// </param>
 | |
|         /// <param name="token">The Security token to be tested for Audience 
 | |
|         /// Enforcement.</param>
 | |
|         /// <returns>True if Audience Enforcement should be applied.</returns>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'token' is null.</exception>
 | |
|         public virtual bool ShouldEnforceAudienceRestriction(AudienceUriMode audienceUriMode, SecurityToken token)
 | |
|         {
 | |
|             if (null == token)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
 | |
|             }
 | |
| 
 | |
|             //
 | |
|             // Use AudienceUriMode to determine whether the audience 
 | |
|             // should be enforced
 | |
|             //
 | |
|             switch (audienceUriMode)
 | |
|             {
 | |
|                 case AudienceUriMode.Always:
 | |
|                     return true;
 | |
| 
 | |
|                 case AudienceUriMode.Never:
 | |
|                     return false;
 | |
| 
 | |
|                 case AudienceUriMode.BearerKeyOnly:
 | |
| #pragma warning suppress 56506
 | |
|                     return (null == token.SecurityKeys || 0 == token.SecurityKeys.Count);
 | |
| 
 | |
|                 default:
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4025, audienceUriMode)));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Checks the given list of Audience URIs with the AllowedAudienceUri list.
 | |
|         /// </summary>
 | |
|         /// <param name="allowedAudienceUris">Collection of AudienceUris.</param>
 | |
|         /// <param name="tokenAudiences">Collection of audience URIs the token applies to.</param>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'allowedAudienceUris' is null.</exception>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'tokenAudiences' is null.</exception>
 | |
|         /// <exception cref="AudienceUriValidationFailedException">Either the input argument 'tokenAudiences' or the configured
 | |
|         /// 'AudienceUris' collection is empty.</exception>
 | |
|         public virtual void ValidateAudienceRestriction(IList<Uri> allowedAudienceUris, IList<Uri> tokenAudiences)
 | |
|         {
 | |
|             if (null == allowedAudienceUris)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("allowedAudienceUris");
 | |
|             }
 | |
| 
 | |
|             if (null == tokenAudiences)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenAudiences");
 | |
|             }
 | |
| 
 | |
|             if (0 == tokenAudiences.Count)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AudienceUriValidationFailedException(
 | |
|                     SR.GetString(SR.ID1036)));
 | |
|             }
 | |
| 
 | |
|             if (0 == allowedAudienceUris.Count)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AudienceUriValidationFailedException(
 | |
|                     SR.GetString(SR.ID1043)));
 | |
|             }
 | |
| 
 | |
|             bool found = false;
 | |
|             foreach (Uri audience in tokenAudiences)
 | |
|             {
 | |
|                 if (audience != null)
 | |
|                 {
 | |
|                     // Strip off any query string or fragment. This is necessary because the 
 | |
|                     // CardSpace uses the raw Request-URI to form the audience when issuing 
 | |
|                     // tokens for personal cards, but we clearly don't want things like the 
 | |
|                     // ReturnUrl parameter affecting the audience matching.
 | |
|                     Uri audienceLeftPart;
 | |
|                     if (audience.IsAbsoluteUri)
 | |
|                     {
 | |
|                         audienceLeftPart = new Uri(audience.GetLeftPart(UriPartial.Path));
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         Uri baseUri = new Uri("http://www.example.com");
 | |
|                         Uri resolved = new Uri(baseUri, audience);
 | |
|                         audienceLeftPart = baseUri.MakeRelativeUri(new Uri(resolved.GetLeftPart(UriPartial.Path)));
 | |
|                     }
 | |
| 
 | |
|                     if (allowedAudienceUris.Contains(audienceLeftPart))
 | |
|                     {
 | |
|                         found = true;
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!found)
 | |
|             {
 | |
| #pragma warning suppress 56506
 | |
|                 if (1 == tokenAudiences.Count || null != tokenAudiences[0])
 | |
|                 {
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AudienceUriValidationFailedException(
 | |
|                         SR.GetString(SR.ID1038, tokenAudiences[0].OriginalString)));
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     StringBuilder sb = new StringBuilder(SR.GetString(SR.ID8007));
 | |
|                     bool first = true;
 | |
| 
 | |
|                     foreach (Uri a in tokenAudiences)
 | |
|                     {
 | |
|                         if (a != null)
 | |
|                         {
 | |
|                             if (first)
 | |
|                             {
 | |
|                                 first = false;
 | |
|                             }
 | |
|                             else
 | |
|                             {
 | |
|                                 sb.Append(", ");
 | |
|                             }
 | |
| 
 | |
|                             sb.Append(a.OriginalString);
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     TraceUtility.TraceString(TraceEventType.Error, sb.ToString());
 | |
| 
 | |
|                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AudienceUriValidationFailedException(SR.GetString(SR.ID1037)));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 |