Exemplo n.º 1
0
        public void CreateSignatureWithoutSpecifyingDigest(EnvelopedSignatureTheoryData theoryData)
        {
            var context = TestUtilities.WriteHeader($"{this}.CreateSignatureWithoutSpecifyingDigest", theoryData);

            try
            {
                using (var buffer = new MemoryStream())
                {
                    var writer = new EnvelopedSignatureWriter(XmlWriter.Create(buffer), theoryData.SigningCredentials, theoryData.ReferenceId);
                    writer.WriteStartElement("EntityDescriptor", "urn:oasis:names:tc:SAML:2.0:metadata");
                    writer.WriteAttributeString("entityID", "issuer");
                    writer.WriteEndElement();

                    // read and verify signatures
                    EnvelopedSignatureReader envelopedReader = new EnvelopedSignatureReader(XmlUtilities.CreateDictionaryReader(Encoding.UTF8.GetString(buffer.ToArray())));
                    while (envelopedReader.Read())
                    {
                        ;
                    }

                    envelopedReader.Signature.Verify(theoryData.SigningCredentials.Key, theoryData.SigningCredentials.Key.CryptoProviderFactory);
                    theoryData.ExpectedException.ProcessNoException(context);
                }
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
        /// <summary>
        /// This gets called on the relying party on deserialization.
        ///
        /// The token looks like this
        ///     <MyDecisionToken Id="someId here">
        ///         <Decision>True</Decision>
        ///         <Key>key bytes</Key>
        ///         <Signature>...</Signature>
        ///     </MyDecisionToken>
        /// This sample is expecting the token in the right format. Omit some xml validation for simplicity.
        /// </summary>
        /// <param name="reader">The xml reader.</param>
        /// <returns>The security token.</returns>
        /// <exception cref="InvalidOperationException">When the token cannot be read.</exception>
        public override SecurityToken ReadToken(XmlReader reader)
        {
            Console.WriteLine("CustomTokenHandler.ReadToken called");
            if (!CanReadToken(reader))
            {
                throw new InvalidOperationException("Reader must be positioned at the beginning of the DecisionToken. ");
            }

            EnvelopedSignatureReader envReader = new EnvelopedSignatureReader(reader, WSSecurityTokenSerializer.DefaultInstance);

            // Read the Id attribute
            string id = envReader.GetAttribute(Id);

            envReader.Read();
            envReader.MoveToContent();

            // Read the Decision element
            string decision = envReader.ReadElementContentAsString(Decision, TokenNamespace);

            Console.WriteLine("- decision read: {0}", decision);

            // Read the Key element
            byte[] key = Convert.FromBase64String(envReader.ReadElementString(Key, TokenNamespace));

            envReader.ReadEndElement();

            return(new MyDecisionToken(Convert.ToBoolean(decision), envReader.SigningCredentials, key, id));
        }
Exemplo n.º 3
0
        public void Constructor(EnvelopedSignatureTheoryData theoryData)
        {
            TestUtilities.WriteHeader($"{this}.Constructor", theoryData);
            try
            {
                var envelopedReader = new EnvelopedSignatureReader(theoryData.XmlReader);
                while (envelopedReader.Read())
                {
                    ;
                }

                if (theoryData.ExpectSignature)
                {
                    if (envelopedReader.Signature == null)
                    {
                        Assert.False(true, "theoryData.ExpectSignature == true && envelopedReader.ExpectSignature == null");
                    }

                    envelopedReader.Signature.Verify(theoryData.SecurityKey, theoryData.SecurityKey.CryptoProviderFactory);
                }

                theoryData.ExpectedException.ProcessNoException();
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Captures the XML source data from an EnvelopedSignatureReader.
        /// </summary>
        /// <remarks>
        /// The EnvelopedSignatureReader that was used to read the data for this
        /// assertion should be passed to this method after the &lt;/Assertion>
        /// element has been read. This method will preserve the raw XML data
        /// that was read, including the signature, so that it may be re-emitted
        /// without changes and without the need to re-sign the data. See
        /// CanWriteSourceData and WriteSourceData.
        /// </remarks>
        /// <param name="reader"></param>
        internal virtual void CaptureSourceData(EnvelopedSignatureReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            this.sourceData = reader.XmlTokens;
        }
Exemplo n.º 5
0
        public override SecurityToken ReadToken(string tokenString)
        {
            var assertion = new Saml2Assertion(new Saml2NameIdentifier("__TemporaryIssuer__"));

            var wrappedSerializer = new WrappedSerializer(this, assertion);

            var sr = new StringReader(_samlXml);

            using (var reader1 = XmlReader.Create(sr))
            {
                var reader2 = new EnvelopedSignatureReader(reader1,
                                                           wrappedSerializer,
                                                           Configuration.IssuerTokenResolver,
                                                           false,
                                                           false, false);

                if (!reader2.ReadToFollowing("Signature", "http://www.w3.org/2000/09/xmldsig#") || !reader2.TryReadSignature())
                {
                    throw new FederatedAuthenticationException("Cannot find token signature",
                                                               FederatedAuthenticationErrorCode.WrongFormat);
                }

                if (!reader2.ReadToFollowing("Assertion", "urn:oasis:names:tc:SAML:2.0:assertion"))
                {
                    throw new FederatedAuthenticationException("Cannot find token assertion",
                                                               FederatedAuthenticationErrorCode.WrongFormat);
                }

                assertion = ReadAssertion(reader2);

                try
                {
                    while (reader2.Read())
                    {
                        //
                    }
                }
                catch (CryptographicException cryptographicExceptione)
                {
                    throw new FederatedAuthenticationException(cryptographicExceptione.Message,
                                                               FederatedAuthenticationErrorCode.NotTrustedIssuer,
                                                               cryptographicExceptione);
                }

                assertion.SigningCredentials = reader2.SigningCredentials;

                var           keys = ResolveSecurityKeys(assertion, Configuration.ServiceTokenResolver);
                SecurityToken token;
                TryResolveIssuerToken(assertion, Configuration.IssuerTokenResolver, out token);
                return(new Saml2SecurityToken(assertion, keys, token));
            }
        }
        public void ReadXmlElements(EnvelopedSignatureTheoryData theoryData)
        {
            TestUtilities.WriteHeader($"{this}.ReadXmlElements", theoryData);
            var context = new CompareContext($"{this}.ReadXmlElements : {theoryData.TestId}.");

            try
            {
                XmlReader reader = XmlUtilities.CreateDictionaryReader(theoryData.Xml);

                EnvelopedSignatureReader envelopedReader;
                if (theoryData.XmlElementReader == null)
                {
                    envelopedReader = new EnvelopedSignatureReader(reader);
                }
                else
                {
                    envelopedReader = new EnvelopedSignatureReader(reader, theoryData.XmlElementReader);
                }

                while (envelopedReader.Read())
                {
                    ;
                }

                if (theoryData.XmlElementReader != null)
                {
                    foreach (var item in theoryData.XmlElementReader.Items)
                    {
                        if (item is SamlSecurityToken samlToken)
                        {
                            samlToken.Assertion.Signature.Verify(theoryData.TokenSecurityKey);
                        }

                        if (item is Saml2SecurityToken saml2Token)
                        {
                            saml2Token.Assertion.Signature.Verify(theoryData.TokenSecurityKey);
                        }
                    }
                }

                if (envelopedReader.Signature != null)
                {
                    envelopedReader.Signature.Verify(theoryData.SecurityKey, theoryData.SecurityKey.CryptoProviderFactory);
                }
            }
            catch (Exception ex)
            {
                theoryData.ExpectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
 public static void ForEachChild(this XmlDictionaryReader reader, Func <XmlDictionaryReader, bool> tryRead, out Signature signature)
 {
     using (var signatureReader = new EnvelopedSignatureReader(reader))
     {
         if (!signatureReader.IsEmptyElement && reader.Read())
         {
             while (signatureReader.IsStartElement())
             {
                 if (!tryRead(signatureReader))
                 {
                     signatureReader.ReadOuterXml();
                 }
             }
         }
         signatureReader.Read();
         signature = signatureReader.Signature;
     }
 }
Exemplo n.º 8
0
        public void RoundTripSamlPSignatureAfterAssertion()
        {
            var context = new CompareContext($"{this}.RoundTripSamlPSignatureAfterAssertion");
            ExpectedException expectedException = ExpectedException.NoExceptionExpected;
            var samlpTokenKey = KeyingMaterial.RsaSigningCreds_4096_Public.Key;
            var samlpTokenSigningCredentials = KeyingMaterial.RsaSigningCreds_4096;
            var samlpKey = KeyingMaterial.RsaSigningCreds_2048_Public.Key;
            var samlpSigningCredentials = KeyingMaterial.RsaSigningCreds_2048;

            try
            {
                // write samlp
                var settings = new XmlWriterSettings
                {
                    Encoding = new UTF8Encoding(false)
                };
                var buffer = new MemoryStream();
                var esw    = new EnvelopedSignatureWriter(XmlWriter.Create(buffer, settings), samlpSigningCredentials, "id-uAOhNLe7abGB6WGPk");
                esw.WriteStartElement("ns0", "Response", "urn:oasis:names:tc:SAML:2.0:protocol");

                esw.WriteAttributeString("ns1", "urn:oasis:names:tc:SAML:2.0:assertion");
                esw.WriteAttributeString("ns2", "http://www.w3.org/2000/09/xmldsig#");
                esw.WriteAttributeString("Destination", "https://tnia.eidentita.cz/fpsts/processRequest.aspx");
                esw.WriteAttributeString("ID", "id-uAOhNLe7abGB6WGPk");
                esw.WriteAttributeString("InResponseTo", "ida5714d006fcc430c92aacf34ab30b166");
                esw.WriteAttributeString("IssueInstant", "2019-04-08T10:30:49Z");
                esw.WriteAttributeString("Version", "2.0");
                esw.WriteStartElement("ns1", "Issuer");
                esw.WriteAttributeString("Format", "urn:oasis:names:tc:SAML:2.0:nameid-format:entity");
                esw.WriteString("https://mojeid.regtest.nic.cz/saml/idp.xml");
                esw.WriteEndElement();
                esw.WriteStartElement("ns0", "Status", null);
                esw.WriteStartElement("ns0", "StatusCode", null);
                esw.WriteAttributeString("Value", "urn:oasis:names:tc:SAML:2.0:status:Success");
                esw.WriteEndElement();
                esw.WriteEndElement();
                Saml2Serializer samlSerializer = new Saml2Serializer();
                Saml2Assertion  assertion      = CreateAssertion(samlpTokenSigningCredentials);
                samlSerializer.WriteAssertion(esw, assertion);
                esw.WriteSignature();
                esw.WriteEndElement();
                var xml = Encoding.UTF8.GetString(buffer.ToArray());

                // read samlp and verify signatures
                XmlReader         reader       = XmlUtilities.CreateDictionaryReader(xml);
                IXmlElementReader tokenReaders = new TokenReaders(new List <SecurityTokenHandler> {
                    new Saml2SecurityTokenHandler()
                });
                EnvelopedSignatureReader envelopedReader = new EnvelopedSignatureReader(reader, tokenReaders);

                while (envelopedReader.Read())
                {
                    ;
                }

                foreach (var item in tokenReaders.Items)
                {
                    if (item is Saml2SecurityToken samlToken)
                    {
                        samlToken.Assertion.Signature.Verify(samlpTokenKey);
                    }
                }

                envelopedReader.Signature.Verify(samlpKey, samlpKey.CryptoProviderFactory);
                expectedException.ProcessNoException(context);
            }
            catch (Exception ex)
            {
                expectedException.ProcessException(ex, context);
            }

            TestUtilities.AssertFailIfErrors(context);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Reads a &lt;saml:Assertion> element.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2Assertion"/> element.</param>
        /// <exception cref="ArgumentNullException">if <paramref name="reader"/> is null.</exception>
        /// <exception cref="NotSupportedException">if assertion is encrypted.</exception>
        /// <exception cref="Saml2SecurityTokenReadException">If <paramref name="reader"/> is not positioned at a Saml2Assertion.</exception>
        /// <exception cref="Saml2SecurityTokenReadException">If Version is not '2.0'.</exception>
        /// <exception cref="Saml2SecurityTokenReadException">If 'Id' is missing.</exception>>
        /// <exception cref="Saml2SecurityTokenReadException">If 'IssueInstant' is missing.</exception>>
        /// <exception cref="Saml2SecurityTokenReadException">If no statements are found.</exception>>
        /// <returns>A <see cref="Saml2Assertion"/> instance.</returns>
        public override Saml2Assertion ReadAssertion(XmlReader reader)
        {
            XmlUtil.CheckReaderOnEntry(reader, Saml2Constants.Elements.Assertion, Saml2Constants.Namespace);

            if (reader.IsStartElement(Saml2Constants.Elements.EncryptedAssertion, Saml2Constants.Namespace))
            {
                var encrypted = new XmlDocument();
                encrypted.PreserveWhitespace = true;
                encrypted.Load(reader);
                XmlElement decrypted = null;
                foreach (var cert in DecryptionCertificates)
                {
                    try
                    {
                        decrypted = encrypted.DocumentElement.Decrypt(cert.PrivateKey);
                        break;
                    }
                    catch (CryptographicException)
                    {
                    }
                }

                if (decrypted == null)
                {
                    throw new InvalidOperationException(
                              "Encrypted assertion could not be decrypted using any available decryption certificate");
                }

                reader = new XmlNodeReader(decrypted);
            }

            var envelopeReader = new EnvelopedSignatureReader(reader);
            var assertion      = new Saml2Assertion(new Saml2NameIdentifier("__TemporaryIssuer__"));

            try
            {
                // @xsi:type
                XmlUtil.ValidateXsiType(envelopeReader, Saml2Constants.Types.AssertionType, Saml2Constants.Namespace);

                // @Version - required - must be "2.0"
                string version = envelopeReader.GetAttribute(Saml2Constants.Attributes.Version);
                if (string.IsNullOrEmpty(version))
                {
                    throw LogReadException(LogMessages.IDX13106, Saml2Constants.Elements.Assertion, Saml2Constants.Attributes.Version);
                }

                if (!StringComparer.Ordinal.Equals(Saml2Constants.Version, version))
                {
                    throw LogReadException(LogMessages.IDX13137, version);
                }

                // @ID - required
                string value = envelopeReader.GetAttribute(Saml2Constants.Attributes.ID);
                if (string.IsNullOrEmpty(value))
                {
                    throw LogReadException(LogMessages.IDX13106, Saml2Constants.Elements.Assertion, Saml2Constants.Attributes.ID);
                }

                assertion.Id = new Saml2Id(value);

                // @IssueInstant - required
                value = envelopeReader.GetAttribute(Saml2Constants.Attributes.IssueInstant);
                if (string.IsNullOrEmpty(value))
                {
                    throw LogReadException(LogMessages.IDX13106, Saml2Constants.Elements.Assertion, Saml2Constants.Attributes.IssueInstant);
                }

                assertion.IssueInstant = DateTime.ParseExact(value, Saml2Constants.AcceptedDateTimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).ToUniversalTime();

                // will move to next element
                // <ds:Signature> 0-1 read by EnvelopedSignatureReader
                envelopeReader.Read();

                // <Issuer> 1
                assertion.Issuer = ReadIssuer(envelopeReader);

                // <Subject> 0-1
                if (envelopeReader.IsStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace))
                {
                    assertion.Subject = ReadSubject(envelopeReader);
                }

                // <Conditions> 0-1
                if (envelopeReader.IsStartElement(Saml2Constants.Elements.Conditions, Saml2Constants.Namespace))
                {
                    assertion.Conditions = ReadConditions(envelopeReader);
                }

                // <Advice> 0-1
                if (envelopeReader.IsStartElement(Saml2Constants.Elements.Advice, Saml2Constants.Namespace))
                {
                    assertion.Advice = ReadAdvice(envelopeReader);
                }

                // <Statement|AuthnStatement|AuthzDecisionStatement|AttributeStatement>, 0-OO
                while (envelopeReader.IsStartElement())
                {
                    Saml2Statement statement;

                    if (envelopeReader.IsStartElement(Saml2Constants.Elements.Statement, Saml2Constants.Namespace))
                    {
                        statement = ReadStatement(envelopeReader);
                    }
                    else if (envelopeReader.IsStartElement(Saml2Constants.Elements.AttributeStatement, Saml2Constants.Namespace))
                    {
                        statement = ReadAttributeStatement(envelopeReader);
                    }
                    else if (envelopeReader.IsStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace))
                    {
                        if (IgnoreAuthenticationContext)
                        {
                            envelopeReader.Skip();
                            continue;
                        }
                        statement = ReadAuthenticationStatement(envelopeReader);
                    }
                    else if (envelopeReader.IsStartElement(Saml2Constants.Elements.AuthzDecisionStatement, Saml2Constants.Namespace))
                    {
                        statement = ReadAuthorizationDecisionStatement(envelopeReader);
                    }
                    else
                    {
                        break;
                    }

                    assertion.Statements.Add(statement);
                }

                envelopeReader.ReadEndElement();
                if (assertion.Subject == null)
                {
                    // An assertion with no statements MUST contain a <Subject> element. [Saml2Core, line 585]
                    if (0 == assertion.Statements.Count)
                    {
                        throw LogReadException(LogMessages.IDX13108, Saml2Constants.Elements.Assertion);
                    }

                    // Furthermore, the built-in statement types all require the presence of a subject.
                    // [Saml2Core, lines 1050, 1168, 1280]
                    foreach (Saml2Statement statement in assertion.Statements)
                    {
                        if (statement is Saml2AuthenticationStatement ||
                            statement is Saml2AttributeStatement ||
                            statement is Saml2AuthorizationDecisionStatement)
                        {
                            throw LogReadException(LogMessages.IDX13109, Saml2Constants.Elements.Assertion);
                        }
                    }
                }

                // attach signedXml for validation of signature
                assertion.Signature = envelopeReader.Signature;
                return(assertion);
            }
            catch (Exception ex)
            {
                if (ex is Saml2SecurityTokenReadException)
                {
                    throw;
                }

                throw LogReadException(LogMessages.IDX13102, ex, Saml2Constants.Elements.Assertion, ex);
            }
        }
        /// <summary>
        /// Reads the &lt;saml:Assertion> element.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2Assertion"/> element.</param>
        /// <returns>A <see cref="Saml2Assertion"/> instance.</returns>
        protected virtual Saml2Assertion ReadAssertion(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            if (this.Configuration.IssuerTokenResolver == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4275));
            }

            if (this.Configuration.ServiceTokenResolver == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4276));
            }

            XmlDictionaryReader plaintextReader = XmlDictionaryReader.CreateDictionaryReader(reader);

            Saml2Assertion assertion = new Saml2Assertion(new Saml2NameIdentifier("__TemporaryIssuer__"));

            // If it's an EncryptedAssertion, we need to retrieve the plaintext 
            // and repoint our reader
            if (reader.IsStartElement(Saml2Constants.Elements.EncryptedAssertion, Saml2Constants.Namespace))
            {
                EncryptingCredentials encryptingCredentials = null;
                plaintextReader = CreatePlaintextReaderFromEncryptedData(
                                    plaintextReader,
                                    Configuration.ServiceTokenResolver,
                                    this.KeyInfoSerializer,
                                    assertion.ExternalEncryptedKeys,
                                    out encryptingCredentials);

                assertion.EncryptingCredentials = encryptingCredentials;
            }

            // Throw if wrong element
            if (!plaintextReader.IsStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace))
            {
                plaintextReader.ReadStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace);
            }

            // disallow empty
            if (plaintextReader.IsEmptyElement)
            {
#pragma warning suppress 56504 // bogus - thinks plaintextReader.LocalName, plaintextReader.NamespaceURI need validation
                throw DiagnosticUtility.ThrowHelperXml(plaintextReader, SR.GetString(SR.ID3061, plaintextReader.LocalName, plaintextReader.NamespaceURI));
            }

            // Construct a wrapped serializer so that the EnvelopedSignatureReader's 
            // attempt to read the <ds:KeyInfo> will hit our ReadKeyInfo virtual.
            WrappedSerializer wrappedSerializer = new WrappedSerializer(this, assertion);

            // SAML supports enveloped signature, so we need to wrap our reader.
            // We do not dispose this reader, since as a delegating reader it would
            // dispose the inner reader, which we don't properly own.
            EnvelopedSignatureReader realReader = new EnvelopedSignatureReader(plaintextReader, wrappedSerializer, this.Configuration.IssuerTokenResolver, false, false, false);
            try
            {
                // Process @attributes
                string value;

                // @xsi:type
                XmlUtil.ValidateXsiType(realReader, Saml2Constants.Types.AssertionType, Saml2Constants.Namespace);

                // @Version - required - must be "2.0"
                string version = realReader.GetAttribute(Saml2Constants.Attributes.Version);
                if (string.IsNullOrEmpty(version))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Version, Saml2Constants.Elements.Assertion));
                }

                if (!StringComparer.Ordinal.Equals(assertion.Version, version))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID4100, version));
                }

                // @ID - required
                value = realReader.GetAttribute(Saml2Constants.Attributes.ID);
                if (string.IsNullOrEmpty(value))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.ID, Saml2Constants.Elements.Assertion));
                }

                assertion.Id = new Saml2Id(value);

                // @IssueInstant - required
                value = realReader.GetAttribute(Saml2Constants.Attributes.IssueInstant);
                if (string.IsNullOrEmpty(value))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.IssueInstant, Saml2Constants.Elements.Assertion));
                }

                assertion.IssueInstant = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted);

                // Process <elements>
                realReader.Read();

                // <Issuer> 1
                assertion.Issuer = this.ReadIssuer(realReader);

                // <ds:Signature> 0-1
                realReader.TryReadSignature();

                // <Subject> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace))
                {
                    assertion.Subject = this.ReadSubject(realReader);
                }

                // <Conditions> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Conditions, Saml2Constants.Namespace))
                {
                    assertion.Conditions = this.ReadConditions(realReader);
                }

                // <Advice> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Advice, Saml2Constants.Namespace))
                {
                    assertion.Advice = this.ReadAdvice(realReader);
                }

                // <Statement|AuthnStatement|AuthzDecisionStatement|AttributeStatement>, 0-OO
                while (realReader.IsStartElement())
                {
                    Saml2Statement statement;

                    if (realReader.IsStartElement(Saml2Constants.Elements.Statement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AttributeStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAttributeStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAuthenticationStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AuthzDecisionStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAuthorizationDecisionStatement(realReader);
                    }
                    else
                    {
                        break;
                    }

                    assertion.Statements.Add(statement);
                }

                realReader.ReadEndElement();

                if (null == assertion.Subject)
                {
                    // An assertion with no statements MUST contain a <Subject> element. [Saml2Core, line 585]
                    if (0 == assertion.Statements.Count)
                    {
                        throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4106));
                    }

                    // Furthermore, the built-in statement types all require the presence of a subject.
                    // [Saml2Core, lines 1050, 1168, 1280]
                    foreach (Saml2Statement statement in assertion.Statements)
                    {
                        if (statement is Saml2AuthenticationStatement
                            || statement is Saml2AttributeStatement
                            || statement is Saml2AuthorizationDecisionStatement)
                        {
                            throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4119));
                        }
                    }
                }

                // Reading the end element will complete the signature; 
                // capture the signing creds
                assertion.SigningCredentials = realReader.SigningCredentials;

                // Save the captured on-the-wire data, which can then be used
                // to re-emit this assertion, preserving the same signature.
                assertion.CaptureSourceData(realReader);

                return assertion;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(realReader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Captures the XML source data from an EnvelopedSignatureReader. 
        /// </summary>
        /// <remarks>
        /// The EnvelopedSignatureReader that was used to read the data for this
        /// assertion should be passed to this method after the &lt;/Assertion>
        /// element has been read. This method will preserve the raw XML data
        /// that was read, including the signature, so that it may be re-emitted
        /// without changes and without the need to re-sign the data. See 
        /// CanWriteSourceData and WriteSourceData.
        /// </remarks>
        /// <param name="reader"><see cref="EnvelopedSignatureReader"/> that contains the data for the assertion.</param>
        internal virtual void CaptureSourceData(EnvelopedSignatureReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            this.sourceData = reader.XmlTokens;
        }
        /// <summary>
        /// Read saml:Assertion element from the given reader.
        /// </summary>
        /// <param name="reader">XmlReader to deserialize the Assertion from.</param>
        /// <returns>SamlAssertion</returns>
        /// <exception cref="ArgumentNullException">The parameter 'reader' is null.</exception>
        /// <exception cref="XmlException">The XmlReader is not positioned at a saml:Assertion element or the Assertion
        /// contains unknown child elements.</exception>
        protected virtual SamlAssertion ReadAssertion(XmlReader reader)
        {
            if (reader == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            if (this.Configuration.IssuerTokenResolver == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4275));
            }

            SamlAssertion assertion = new SamlAssertion();

            EnvelopedSignatureReader wrappedReader = new EnvelopedSignatureReader(reader, new WrappedSerializer(this, assertion), this.Configuration.IssuerTokenResolver, false, true, false);


            if (!wrappedReader.IsStartElement(SamlConstants.ElementNames.Assertion, SamlConstants.Namespace))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4065, SamlConstants.ElementNames.Assertion, SamlConstants.Namespace, wrappedReader.LocalName, wrappedReader.NamespaceURI)));
            }

            string attributeValue = wrappedReader.GetAttribute(SamlConstants.AttributeNames.MajorVersion, null);
            if (string.IsNullOrEmpty(attributeValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4075, SamlConstants.AttributeNames.MajorVersion)));
            }

            int majorVersion = XmlConvert.ToInt32(attributeValue);

            attributeValue = wrappedReader.GetAttribute(SamlConstants.AttributeNames.MinorVersion, null);
            if (string.IsNullOrEmpty(attributeValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4075, SamlConstants.AttributeNames.MinorVersion)));
            }

            int minorVersion = XmlConvert.ToInt32(attributeValue);

            if ((majorVersion != SamlConstants.MajorVersionValue) || (minorVersion != SamlConstants.MinorVersionValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4076, majorVersion, minorVersion, SamlConstants.MajorVersionValue, SamlConstants.MinorVersionValue)));
            }

            attributeValue = wrappedReader.GetAttribute(SamlConstants.AttributeNames.AssertionId, null);
            if (string.IsNullOrEmpty(attributeValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4075, SamlConstants.AttributeNames.AssertionId)));
            }

            if (!XmlUtil.IsValidXmlIDValue(attributeValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4077, attributeValue)));
            }

            assertion.AssertionId = attributeValue;

            attributeValue = wrappedReader.GetAttribute(SamlConstants.AttributeNames.Issuer, null);
            if (string.IsNullOrEmpty(attributeValue))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4075, SamlConstants.AttributeNames.Issuer)));
            }

            assertion.Issuer = attributeValue;

            attributeValue = wrappedReader.GetAttribute(SamlConstants.AttributeNames.IssueInstant, null);
            if (!string.IsNullOrEmpty(attributeValue))
            {
                assertion.IssueInstant = DateTime.ParseExact(
                    attributeValue, DateTimeFormats.Accepted, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None).ToUniversalTime();
            }

            wrappedReader.MoveToContent();
            wrappedReader.Read();

            if (wrappedReader.IsStartElement(SamlConstants.ElementNames.Conditions, SamlConstants.Namespace))
            {
                assertion.Conditions = ReadConditions(wrappedReader);
            }

            if (wrappedReader.IsStartElement(SamlConstants.ElementNames.Advice, SamlConstants.Namespace))
            {
                assertion.Advice = ReadAdvice(wrappedReader);
            }

            while (wrappedReader.IsStartElement())
            {
                assertion.Statements.Add(ReadStatement(wrappedReader));
            }

            if (assertion.Statements.Count == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.ID4078)));
            }

            wrappedReader.MoveToContent();
            wrappedReader.ReadEndElement();

            // Reading the end element will complete the signature; 
            // capture the signing creds
            assertion.SigningCredentials = wrappedReader.SigningCredentials;

            // Save the captured on-the-wire data, which can then be used
            // to re-emit this assertion, preserving the same signature.
            assertion.CaptureSourceData(wrappedReader);

            return assertion;
        }