You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			253 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------------------------
 | |
| //     Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------------------------
 | |
| 
 | |
| namespace System.IdentityModel.Tokens
 | |
| {
 | |
|     using System.Collections.Generic;
 | |
|     using System.Collections.ObjectModel;
 | |
|     using System.Runtime;
 | |
|     using System.Security.Claims;
 | |
|     using System.Security.Cryptography;
 | |
|     using System.Xml;
 | |
| 
 | |
|     /// <summary>
 | |
|     /// SecurityTokenHandler for RsaSecurityTokens. 
 | |
|     /// </summary>
 | |
|     public class RsaSecurityTokenHandler : SecurityTokenHandler
 | |
|     {
 | |
|         static string[] _tokenTypeIdentifiers = new string[] { SecurityTokenTypes.Rsa };
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Creates an instance of <see cref="RsaSecurityTokenHandler"/>
 | |
|         /// </summary>
 | |
|         public RsaSecurityTokenHandler()
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Checks the reader if this is a representation of an RsaSecurityToken.
 | |
|         /// </summary>
 | |
|         /// <param name="reader">XmlReader over the incoming SecurityToken.</param>
 | |
|         /// <returns>'True' if the reader points to an RsaSecurityToken, false otherwise.</returns>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'reader' is null.</exception>
 | |
|         public override bool CanReadToken(XmlReader reader)
 | |
|         {
 | |
|             if (reader == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
 | |
|             }
 | |
| 
 | |
|             return reader.IsStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the settings that indicate if the token handler can validate tokens.
 | |
|         /// Returns true by default.
 | |
|         /// </summary>
 | |
|         public override bool CanValidateToken
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets a boolean indicating if the handler can write tokens.
 | |
|         /// Returns true by default.
 | |
|         /// </summary>
 | |
|         public override bool CanWriteToken
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the RSA Security Token type as defined in WS-Security Token profile.
 | |
|         /// </summary>
 | |
|         public override string[] GetTokenTypeIdentifiers()
 | |
|         {
 | |
|             return _tokenTypeIdentifiers;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Deserializes an RSA security token from XML.
 | |
|         /// </summary>
 | |
|         /// <param name="reader">An XML reader positioned at the start of the token</param>
 | |
|         /// <returns>An instance of <see cref="RsaSecurityToken"/>.</returns>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'reader' is null.</exception>
 | |
|         /// <exception cref="XmlException">The 'reader' is not positioned at a RSA token. 
 | |
|         /// or the SecurityContextToken cannot be read.</exception>
 | |
|         public override SecurityToken ReadToken(XmlReader reader)
 | |
|         {
 | |
|             if (null == reader)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
 | |
|             }
 | |
| 
 | |
|             XmlDictionaryReader dicReader = XmlDictionaryReader.CreateDictionaryReader(reader);
 | |
| 
 | |
|             if (!dicReader.IsStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace))
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 | |
|                     new XmlException(
 | |
|                         SR.GetString(
 | |
|                         SR.ID4065,
 | |
|                         XmlSignatureConstants.Elements.KeyInfo,
 | |
|                         XmlSignatureConstants.Namespace,
 | |
|                         dicReader.LocalName,
 | |
|                         dicReader.NamespaceURI)));
 | |
|             }
 | |
| 
 | |
|             dicReader.ReadStartElement();
 | |
| 
 | |
|             if (!dicReader.IsStartElement(XmlSignatureConstants.Elements.KeyValue, XmlSignatureConstants.Namespace))
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
 | |
|                     new XmlException(
 | |
|                         SR.GetString(
 | |
|                         SR.ID4065,
 | |
|                         XmlSignatureConstants.Elements.KeyValue,
 | |
|                         XmlSignatureConstants.Namespace,
 | |
|                         dicReader.LocalName,
 | |
|                         dicReader.NamespaceURI)));
 | |
|             }
 | |
| 
 | |
|             dicReader.ReadStartElement();
 | |
| 
 | |
|             RSA rsa = new RSACryptoServiceProvider();
 | |
|             rsa.FromXmlString(dicReader.ReadOuterXml());
 | |
| 
 | |
|             dicReader.ReadEndElement(); //</KeyValue>
 | |
|             dicReader.ReadEndElement(); //</KeyInfo>
 | |
| 
 | |
|             return new RsaSecurityToken(rsa);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Gets the System.Type of the SecurityToken that this token handler handles.
 | |
|         /// Return type of <see cref="RsaSecurityToken"/> by default.
 | |
|         /// </summary>
 | |
|         public override Type TokenType
 | |
|         {
 | |
|             get { return typeof(RsaSecurityToken); }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Validates a <see cref="RsaSecurityToken"/>.
 | |
|         /// </summary>
 | |
|         /// <param name="token">The <see cref="RsaSecurityToken"/> to validate.</param>
 | |
|         /// <returns>A <see cref="ReadOnlyCollection{T}"/> of <see cref="ClaimsIdentity"/> representing the identities contained in the token.</returns>
 | |
|         /// <exception cref="ArgumentNullException">The parameter 'token' is null.</exception>
 | |
|         /// <exception cref="ArgumentException">The token is not assignable from <see cref="RsaSecurityToken"/>.</exception>
 | |
|         /// <exception cref="InvalidOperationException">Configuration <see cref="SecurityTokenHandlerConfiguration"/>is null.</exception>        
 | |
|         public override ReadOnlyCollection<ClaimsIdentity> ValidateToken(SecurityToken token)
 | |
|         {
 | |
|             if (token == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
 | |
|             }
 | |
| 
 | |
|             RsaSecurityToken rsaToken = (RsaSecurityToken)token;
 | |
|             if (rsaToken == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(RsaSecurityToken)));
 | |
|             }
 | |
| 
 | |
|             if (this.Configuration == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
 | |
|             }
 | |
| 
 | |
|             try
 | |
|             {
 | |
| 
 | |
|                 // Export the Public Key of the RSA as a Claim. 
 | |
|                 ClaimsIdentity identity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Rsa, rsaToken.Rsa.ToXmlString(false), ClaimValueTypes.RsaKeyValue, ClaimsIdentity.DefaultIssuer) }, AuthenticationTypes.Signature);
 | |
| 
 | |
|                 identity.AddClaim(new Claim(ClaimTypes.AuthenticationInstant, XmlConvert.ToString(DateTime.UtcNow, DateTimeFormats.Generated), ClaimValueTypes.DateTime));
 | |
|                 identity.AddClaim(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Signature));
 | |
| 
 | |
|                 if (this.Configuration.SaveBootstrapContext)
 | |
|                 {
 | |
|                     identity.BootstrapContext = new BootstrapContext(token, this);
 | |
|                 }
 | |
| 
 | |
|                 this.TraceTokenValidationSuccess(token);
 | |
| 
 | |
|                 List<ClaimsIdentity> identities = new List<ClaimsIdentity>(1);
 | |
|                 identities.Add(identity);
 | |
|                 return identities.AsReadOnly();
 | |
|             }
 | |
|             catch (Exception e)
 | |
|             {
 | |
|                 if (Fx.IsFatal(e))
 | |
|                 {
 | |
|                     throw;
 | |
|                 }
 | |
| 
 | |
|                 this.TraceTokenValidationFailure(token, e.Message);
 | |
|                 throw e;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Serializes an RSA security token to XML.
 | |
|         /// </summary>
 | |
|         /// <param name="writer">The XML writer.</param>
 | |
|         /// <param name="token">An RSA security token.</param>
 | |
|         /// <exception cref="ArgumentNullException">The input argument 'writer' is null.</exception>
 | |
|         /// <exception cref="InvalidOperationException">The input argument 'token' is either null or not of type
 | |
|         /// <see cref="RsaSecurityToken"/>.</exception>
 | |
|         public override void WriteToken(XmlWriter writer, SecurityToken token)
 | |
|         {
 | |
|             if (writer == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
 | |
|             }
 | |
| 
 | |
|             if (token == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("token");
 | |
|             }
 | |
| 
 | |
|             RsaSecurityToken rsaToken = token as RsaSecurityToken;
 | |
| 
 | |
|             if (rsaToken == null)
 | |
|             {
 | |
|                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token", SR.GetString(SR.ID0018, typeof(RsaSecurityToken)));
 | |
|             }
 | |
| 
 | |
|             RSAParameters rsaParams = rsaToken.Rsa.ExportParameters(false);
 | |
| 
 | |
|             writer.WriteStartElement(XmlSignatureConstants.Elements.KeyInfo, XmlSignatureConstants.Namespace);
 | |
|             writer.WriteStartElement(XmlSignatureConstants.Elements.KeyValue, XmlSignatureConstants.Namespace);
 | |
| 
 | |
|             //
 | |
|             // RSA.ToXmlString shouldn't be used here because it doesn't write namespaces.  The modulus and exponent are written manually.
 | |
|             //
 | |
|             writer.WriteStartElement(XmlSignatureConstants.Elements.RsaKeyValue, XmlSignatureConstants.Namespace);
 | |
| 
 | |
|             writer.WriteStartElement(XmlSignatureConstants.Elements.Modulus, XmlSignatureConstants.Namespace);
 | |
| 
 | |
|             byte[] modulus = rsaParams.Modulus;
 | |
|             writer.WriteBase64(modulus, 0, modulus.Length);
 | |
|             writer.WriteEndElement(); // </modulus>
 | |
| 
 | |
|             writer.WriteStartElement(XmlSignatureConstants.Elements.Exponent, XmlSignatureConstants.Namespace);
 | |
| 
 | |
|             byte[] exponent = rsaParams.Exponent;
 | |
|             writer.WriteBase64(exponent, 0, exponent.Length);
 | |
|             writer.WriteEndElement(); // </exponent>
 | |
| 
 | |
|             writer.WriteEndElement(); // </RsaKeyValue>
 | |
|             writer.WriteEndElement(); // </KeyValue>
 | |
|             writer.WriteEndElement(); // </KeyInfo>
 | |
| 
 | |
|         }
 | |
|     }
 | |
| }
 |