Ejemplo n.º 1
0
        /// <summary>
        /// Decrpyts a security token from an XML EncryptedData
        /// </summary>
        /// <param name="reader">The encrypted token XML reader.</param>
        /// <returns>A byte array of the contents of the encrypted token</returns>
        internal byte[] DecryptToken(XmlReader reader)
        {
            Requires.NotNull(reader, "reader");
            Contract.Ensures(Contract.Result <byte[]>() != null);

            byte[] securityTokenData;
            string encryptionAlgorithm;
            SecurityKeyIdentifier keyIdentifier;
            bool isEmptyElement;

            ErrorUtilities.VerifyInternal(reader.IsStartElement(XmlEncryptionStrings.EncryptedData, XmlEncryptionStrings.Namespace), "Expected encrypted token starting XML element was not found.");
            reader.Read();             // get started

            // if it's not an encryption method, something is dreadfully wrong.
            InfoCardErrorUtilities.VerifyInfoCard(reader.IsStartElement(XmlEncryptionStrings.EncryptionMethod, XmlEncryptionStrings.Namespace), InfoCardStrings.EncryptionAlgorithmNotFound);

            // Looks good, let's grab the alg.
            isEmptyElement      = reader.IsEmptyElement;
            encryptionAlgorithm = reader.GetAttribute(XmlEncryptionStrings.Algorithm);
            reader.Read();

            if (!isEmptyElement)
            {
                while (reader.IsStartElement())
                {
                    reader.Skip();
                }
                reader.ReadEndElement();
            }

            // get the key identifier
            keyIdentifier = WSSecurityTokenSerializer.DefaultInstance.ReadKeyIdentifier(reader);

            // resolve the symmetric key
            SymmetricSecurityKey decryptingKey = (SymmetricSecurityKey)SecurityTokenResolver.CreateDefaultSecurityTokenResolver(this.tokens.AsReadOnly(), false).ResolveSecurityKey(keyIdentifier[0]);
            SymmetricAlgorithm   algorithm     = decryptingKey.GetSymmetricAlgorithm(encryptionAlgorithm);

            // dig for the security token data itself.
            reader.ReadStartElement(XmlEncryptionStrings.CipherData, XmlEncryptionStrings.Namespace);
            reader.ReadStartElement(XmlEncryptionStrings.CipherValue, XmlEncryptionStrings.Namespace);
            securityTokenData = Convert.FromBase64String(reader.ReadString());
            reader.ReadEndElement();             // CipherValue
            reader.ReadEndElement();             // CipherData
            reader.ReadEndElement();             // EncryptedData

            // decrypto-magic!
            int blockSizeBytes = algorithm.BlockSize / 8;

            byte[] iv = new byte[blockSizeBytes];
            Buffer.BlockCopy(securityTokenData, 0, iv, 0, iv.Length);
            algorithm.Padding = PaddingMode.ISO10126;
            algorithm.Mode    = CipherMode.CBC;
            ICryptoTransform decrTransform = algorithm.CreateDecryptor(algorithm.Key, iv);

            byte[] plainText = decrTransform.TransformFinalBlock(securityTokenData, iv.Length, securityTokenData.Length - iv.Length);
            decrTransform.Dispose();

            return(plainText);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Token Authentication.  Translates the decrypted data into a AuthContext.
        /// </summary>
        /// <param name="reader">The token XML reader.</param>
        /// <param name="audience">The audience that the token must be scoped for.
        /// Use <c>null</c> to indicate any audience is acceptable.</param>
        /// <returns>
        /// The authorization context carried by the token.
        /// </returns>
        internal static AuthorizationContext AuthenticateToken(XmlReader reader, Uri audience)
        {
            Contract.Ensures(Contract.Result <AuthorizationContext>() != null);

            // Extensibility Point:
            // in order to accept different token types, you would need to add additional
            // code to create an authenticationcontext from the security token.
            // This code only supports SamlSecurityToken objects.
            SamlSecurityToken token = WSSecurityTokenSerializer.DefaultInstance.ReadToken(reader, null) as SamlSecurityToken;

            if (null == token)
            {
                throw new InformationCardException("Unable to read security token");
            }

            if (null != token.SecurityKeys && token.SecurityKeys.Count > 0)
            {
                throw new InformationCardException("Token Security Keys Exist");
            }

            if (audience == null)
            {
                Logger.InfoCard.Warn("SAML token Audience checking will be skipped.");
            }
            else
            {
                if (token.Assertion.Conditions != null &&
                    token.Assertion.Conditions.Conditions != null)
                {
                    foreach (SamlCondition condition in token.Assertion.Conditions.Conditions)
                    {
                        SamlAudienceRestrictionCondition audienceCondition = condition as SamlAudienceRestrictionCondition;

                        if (audienceCondition != null)
                        {
                            Logger.InfoCard.DebugFormat("SAML token audience(s): {0}", audienceCondition.Audiences.ToStringDeferred());
                            bool match = audienceCondition.Audiences.Contains(audience);

                            if (!match && Logger.InfoCard.IsErrorEnabled)
                            {
                                Logger.InfoCard.ErrorFormat("Expected SAML token audience of {0} but found {1}.", audience.AbsoluteUri, audienceCondition.Audiences.Select(aud => aud.AbsoluteUri).ToStringDeferred());
                            }

                            // The token is invalid if any condition is not valid.
                            // An audience restriction condition is valid if any audience
                            // matches the Relying Party.
                            InfoCardErrorUtilities.VerifyInfoCard(match, InfoCardStrings.AudienceMismatch);
                        }
                    }
                }
            }
            var samlAuthenticator = new SamlSecurityTokenAuthenticator(
                new List <SecurityTokenAuthenticator>(
                    new SecurityTokenAuthenticator[] {
                new RsaSecurityTokenAuthenticator(),
                new X509SecurityTokenAuthenticator(),
            }),
                MaximumClockSkew);

            if (audience != null)
            {
                samlAuthenticator.AllowedAudienceUris.Add(audience.AbsoluteUri);
            }

            return(AuthorizationContext.CreateDefaultAuthorizationContext(samlAuthenticator.ValidateToken(token)));
        }