Esempio n. 1
0
            public void CanParseCreatedArtifact()
            {
                // Arrange
                var sourceIdUrl = "https://kleopatra.safewhere.local/Saml2ExtWeb/artifact.ashx";

                var sourceIdHash  = ArtifactUtil.GenerateSourceIdHash(sourceIdUrl);
                var messageHandle = ArtifactUtil.GenerateMessageHandle();

                short typeCode      = 4;
                short endpointIndex = 1;

                // Act
                var artifact = ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle);

                short parsedTypeCode      = -1;
                short parsedEndpointIndex = -1;
                var   parsedSourceIdHash  = new byte[20];
                var   parsedMessageHandle = new byte[20];

                var result = ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle);

                // Assert
                Assert.True(result, "Unable to parse artifact");
                Assert.True(typeCode == parsedTypeCode, "Original and parsed typeCode did not match");
                Assert.True(endpointIndex == parsedEndpointIndex, "Original and parsed endpointIndex did not match");

                Assert.Equal(sourceIdHash, parsedSourceIdHash);

                //Assert.Fail("Original and parsed sourceIdHash are not identical");

                Assert.Equal(messageHandle, parsedMessageHandle);
                //Assert.Fail("Original and parsed messageHandle are not identical");
            }
Esempio n. 2
0
        /// <summary>
        /// Resolves an artifact.
        /// </summary>
        /// <returns>A stream containing the artifact response from the IdP</returns>
        /// <param name="artifact">artifact from request ("SAMLart")</param>
        public Stream ResolveArtifact(string artifact, string relayState, Saml2Configuration config)
        {
            var idpEndPoint = DetermineIdp(artifact);

            if (idpEndPoint == null)
            {
                throw new InvalidOperationException(ErrorMessages.ArtifactResolveIdentityProviderUnknown);
            }

            var endpointIndex = ArtifactUtil.GetEndpointIndex(artifact);
            var endpointUrl   = idpEndPoint.Metadata.GetIDPARSEndpoint(endpointIndex);

            _logger.LogDebug(TraceMessages.ArtifactResolveForKnownIdentityProvider, artifact, idpEndPoint.Id, endpointUrl);

            var resolve = Saml20ArtifactResolve.GetDefault(config.ServiceProvider.Id);

            resolve.Artifact = artifact;

            var doc = resolve.GetXml();

            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            XmlSignatureUtils.SignDocument(doc, resolve.Id, config);

            var artifactResolveString = doc.OuterXml;

            _logger.LogDebug(TraceMessages.ArtifactResolved, artifactResolveString);

            return(GetResponse(endpointUrl, artifactResolveString, idpEndPoint.ArtifactResolution, relayState));
        }
        /// <summary>
        /// Resolves an artifact.
        /// </summary>
        /// <returns>A stream containing the artifact response from the IdP</returns>
        public Stream ResolveArtifact()
        {
            var artifact    = Context.Request.Params["SAMLart"];
            var idpEndPoint = DetermineIdp(artifact);

            if (idpEndPoint == null)
            {
                throw new InvalidOperationException(ErrorMessages.ArtifactResolveIdentityProviderUnknown);
            }

            var endpointIndex = ArtifactUtil.GetEndpointIndex(artifact);
            var endpointUrl   = idpEndPoint.Metadata.GetIDPARSEndpoint(endpointIndex);

            Logger.DebugFormat(TraceMessages.ArtifactResolveForKnownIdentityProvider, artifact, idpEndPoint.Id, endpointUrl);
            var config  = ConfigurationFactory.Instance.Configuration;
            var resolve = Saml20ArtifactResolve.GetDefault(config.ServiceProvider.Id);

            resolve.Artifact = artifact;

            var doc = resolve.GetXml();

            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            XmlSignatureUtils.SignDocument(doc, resolve.Id, config.ServiceProvider.SigningCertificate);

            var artifactResolveString = doc.OuterXml;

            Logger.DebugFormat(TraceMessages.ArtifactResolved, artifactResolveString);

            return(GetResponse(endpointUrl, artifactResolveString, idpEndPoint.ArtifactResolution));
        }
Esempio n. 4
0
        /// <summary>
        /// Handles all artifact creations and redirects.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="localEndpointIndex">Index of the local endpoint.</param>
        /// <param name="signedSamlMessage">The signed saml message.</param>
        /// <param name="relayState">The query string relay state value to add to the communication</param>
        private void ArtifactRedirect(IDPEndPointElement destination, Int16 localEndpointIndex, XmlDocument signedSamlMessage, string relayState)
        {
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();
            string sourceId = config.ServiceProvider.ID;

            byte[] sourceIdHash  = ArtifactUtil.GenerateSourceIdHash(sourceId);
            byte[] messageHandle = ArtifactUtil.GenerateMessageHandle();

            string artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle);

            _context.Cache.Insert(artifact, signedSamlMessage, null, DateTime.Now.AddMinutes(1), SamlCache.NoSlidingExpiration);

            string destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" +
                                    HttpUtility.UrlEncode(artifact);

            if (!string.IsNullOrEmpty(relayState))
            {
                destinationUrl += "&relayState=" + relayState;
            }

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.CreatedArtifact, artifact, signedSamlMessage.OuterXml));
            }

            _context.Response.Redirect(destinationUrl);
        }
        public void CreateError2()
        {
            Int16 typeCode      = 4;
            Int16 endpointIndex = 1;

            byte[] sourceIdHash  = new byte[20];
            byte[] messageHandle = new byte[19];

            ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle);
        }
Esempio n. 6
0
            public void ThrowsExceptionWhenSourceIdHashLengthMismatch()
            {
                // Arrange
                short typeCode      = 4;
                short endpointIndex = 1;
                var   sourceIdHash  = new byte[19];
                var   messageHandle = new byte[20];

                // Act
                Assert.Throws <ArgumentException>(() => ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle));
            }
        public void ParseError1()
        {
            Int16 parsedTypeCode      = -1;
            Int16 parsedEndpointIndex = -1;

            byte[] parsedSourceIdHash  = new byte[19];
            byte[] parsedMessageHandle = new byte[20];
            string artifact            = string.Empty;

            ArtifactUtil.ParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle);
        }
Esempio n. 8
0
            public void ThrowsExceptionWhenArtifactLengthMismatch()
            {
                // Arrange
                short parsedTypeCode      = -1;
                short parsedEndpointIndex = -1;
                var   parsedSourceIdHash  = new byte[20];
                var   parsedMessageHandle = new byte[20];
                var   artifact            = string.Empty;

                // Act
                Assert.Throws <ArgumentException>(() => ArtifactUtil.ParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle));
            }
        public void TryParseError3()
        {
            Int16 parsedTypeCode      = -1;
            Int16 parsedEndpointIndex = -1;

            byte[] parsedSourceIdHash  = new byte[20];
            byte[] parsedMessageHandle = new byte[20];
            string artifact            = string.Empty;

            bool result = ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle);

            Assert.That(!result, "TryParseArtifact did not fail as expected");
        }
Esempio n. 10
0
            public void ReturnsFalseOnMessageHandleLengthMismatch()
            {
                // Arrange
                short parsedTypeCode      = -1;
                short parsedEndpointIndex = -1;
                var   parsedSourceIdHash  = new byte[20];
                var   parsedMessageHandle = new byte[19];
                var   artifact            = string.Empty;

                // Act
                var result = ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex, ref parsedSourceIdHash, ref parsedMessageHandle);

                // Assert
                Assert.That(!result, "TryParseArtifact did not fail as expected");
            }
        public void ArtifactCreateParse()
        {
            string sourceIdUrl = "https://kleopatra.safewhere.local/Saml2ExtWeb/artifact.ashx";

            byte[] sourceIdHash = ArtifactUtil.GenerateSourceIdHash(sourceIdUrl);

            Assert.That(sourceIdHash.Length == 20, "Unexpected hash length");

            byte[] messageHandle = ArtifactUtil.GenerateMessageHandle();

            Assert.That(messageHandle.Length == 20, "Unexpected hash length");

            Int16 typeCode = 4;

            Int16 endpointIndex = 1;

            string artifact = ArtifactUtil.CreateArtifact(typeCode, endpointIndex, sourceIdHash, messageHandle);

            Int16 parsedTypeCode      = -1;
            Int16 parsedEndpointIndex = -1;

            byte[] parsedSourceIdHash  = new byte[20];
            byte[] parsedMessageHandle = new byte[20];

            Assert.That(
                ArtifactUtil.TryParseArtifact(artifact, ref parsedTypeCode, ref parsedEndpointIndex,
                                              ref parsedSourceIdHash, ref parsedMessageHandle), "Unable to parse artifact");

            Assert.That(typeCode == parsedTypeCode, "Original and parsed typeCode did not match");
            Assert.That(endpointIndex == parsedEndpointIndex, "Original and parsed endpointIndex did not match");

            for (int i = 0; i < 20; i++)
            {
                if (sourceIdHash[i] != parsedSourceIdHash[i])
                {
                    Assert.Fail("Original and parsed sourceIdHash are not identical");
                }
            }

            for (int i = 0; i < 20; i++)
            {
                if (messageHandle[i] != parsedMessageHandle[i])
                {
                    Assert.Fail("Original and parsed messageHandle are not identical");
                }
            }
        }
Esempio n. 12
0
        /// <summary>
        /// Resolves an artifact.
        /// </summary>
        /// <returns>A stream containing the artifact response from the IdP</returns>
        public Stream ResolveArtifact()
        {
            Trace.TraceMethodCalled(GetType(), "ResolveArtifact()");

            string artifact = _context.Request.Params["SAMLart"];

            IDPEndPoint idpEndPoint = DetermineIdp(artifact);

            if (idpEndPoint == null)
            {
                throw new InvalidOperationException("Received artifact from unknown IDP.");
            }

            ushort endpointIndex = ArtifactUtil.GetEndpointIndex(artifact);

            string endpointUrl = idpEndPoint.metadata.GetARSEndpoint(endpointIndex);

            Saml20ArtifactResolve resolve = Saml20ArtifactResolve.GetDefault();

            resolve.Artifact = artifact;

            XmlDocument doc = resolve.GetXml();

            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            var signingCertificate  = FederationConfig.GetConfig().GetFirstValidCertificate();
            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(idpEndPoint.ShaHashingAlgorithm);
            var signatureProvider   = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);

            signatureProvider.SignAssertion(doc, resolve.ID, signingCertificate);

            string artifactResolveString = doc.OuterXml;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.ResolveArtifact, artifact, idpEndPoint.Id, endpointIndex, endpointUrl, artifactResolveString));
            }

            return(GetResponse(endpointUrl, artifactResolveString, idpEndPoint.ArtifactResolution));
        }
        /// <summary>
        /// Determines which IdP an artifact has been sent from.
        /// </summary>
        /// <param name="artifact">The artifact.</param>
        /// <returns>An IdP configuration element</returns>
        private IdentityProvider DetermineIdp(string artifact)
        {
            short typeCodeValue = -1;
            short endPointIndex = -1;
            var   sourceIdHash  = new byte[20];
            var   messageHandle = new byte[20];

            if (ArtifactUtil.TryParseArtifact(artifact, ref typeCodeValue, ref endPointIndex, ref sourceIdHash, ref messageHandle))
            {
                foreach (IdentityProvider ep in config.IdentityProviders)
                {
                    var hash = ArtifactUtil.GenerateSourceIdHash(ep.Id);
                    if (ByteArraysAreEqual(sourceIdHash, hash))
                    {
                        return(ep);
                    }
                }
            }

            return(null);
        }
Esempio n. 14
0
        /// <summary>
        /// Determines which IdP an artifact has been sent from.
        /// </summary>
        /// <param name="artifact">The artifact.</param>
        /// <returns>An IdP configuration element</returns>
        private IDPEndPoint DetermineIdp(string artifact)
        {
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();
            
            short typeCodeValue = -1;
            short endPointIndex = -1;
            byte[] sourceIdHash = new byte[20];
            byte[] messageHandle = new byte[20];

            if (ArtifactUtil.TryParseArtifact(artifact, ref typeCodeValue, ref endPointIndex, ref sourceIdHash, ref messageHandle))
            {
                foreach(IDPEndPoint ep in config.IDPEndPoints)
                {
                    byte[] hash = ArtifactUtil.GenerateSourceIdHash(ep.Id);
                    if (AreEqual(sourceIdHash, hash))
                        return ep;
                }
            }
            
            return null;
        }
Esempio n. 15
0
        /// <summary>
        /// Resolves an artifact.
        /// </summary>
        /// <returns>A stream containing the artifact response from the IdP</returns>
        public Stream ResolveArtifact()
        {
            Trace.TraceMethodCalled(GetType(), "ResolveArtifact()");

            string artifact = _context.Request.Params["SAMLart"];

            IDPEndPoint idpEndPoint = DetermineIdp(artifact);

            if (idpEndPoint == null)
            {
                throw new InvalidOperationException("Received artifact from unknown IDP.");
            }

            ushort endpointIndex = ArtifactUtil.GetEndpointIndex(artifact);

            string endpointUrl = idpEndPoint.metadata.GetARSEndpoint(endpointIndex);

            Saml20ArtifactResolve resolve = Saml20ArtifactResolve.GetDefault();

            resolve.Artifact = artifact;

            XmlDocument doc = resolve.GetXml();

            if (doc.FirstChild is XmlDeclaration)
            {
                doc.RemoveChild(doc.FirstChild);
            }

            XmlSignatureUtils.SignDocument(doc, resolve.ID);

            string artifactResolveString = doc.OuterXml;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.ResolveArtifact, artifact, idpEndPoint.Id, endpointIndex, endpointUrl, artifactResolveString));
            }

            return(GetResponse(endpointUrl, artifactResolveString, idpEndPoint.ArtifactResolution));
        }
        /// <summary>
        /// Handles all artifact creations and redirects.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="localEndpointIndex">Index of the local endpoint.</param>
        /// <param name="signedSamlMessage">The signed SAML message.</param>
        /// <param name="relayState">The query string relay state value to add to the communication</param>
        private void ArtifactRedirect(IdentityProviderEndpoint destination, short localEndpointIndex, XmlDocument signedSamlMessage, string relayState)
        {
            Logger.DebugFormat(TraceMessages.ArtifactRedirectReceived, signedSamlMessage.OuterXml);

            var sourceId      = config.ServiceProvider.Id;
            var sourceIdHash  = ArtifactUtil.GenerateSourceIdHash(sourceId);
            var messageHandle = ArtifactUtil.GenerateMessageHandle();

            var artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle);

            Context.Cache.Insert(artifact, signedSamlMessage, null, DateTime.Now.AddMinutes(1), Cache.NoSlidingExpiration);

            var destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + HttpUtility.UrlEncode(artifact);

            if (!string.IsNullOrEmpty(relayState))
            {
                destinationUrl += "&relayState=" + relayState;
            }

            Logger.DebugFormat(TraceMessages.ArtifactCreated, artifact);

            Context.Response.Redirect(destinationUrl);
        }
Esempio n. 17
0
        /// <summary>
        /// Handles all artifact creations and redirects.
        /// </summary>
        /// <param name="destination">The destination.</param>
        /// <param name="localEndpointIndex">Index of the local endpoint.</param>
        /// <param name="signedSamlMessage">The signed SAML message.</param>
        /// <param name="relayState">The query string relay state value to add to the communication</param>
        private void ArtifactRedirect(IdentityProviderEndpoint destination, short localEndpointIndex, XmlDocument signedSamlMessage, string relayState, Action <string, object> cacheInsert)
        {
            _logger.LogDebug(TraceMessages.ArtifactRedirectReceived, signedSamlMessage.OuterXml);

            var sourceId      = config.ServiceProvider.Id;
            var sourceIdHash  = ArtifactUtil.GenerateSourceIdHash(sourceId);
            var messageHandle = ArtifactUtil.GenerateMessageHandle();

            var artifact = ArtifactUtil.CreateArtifact(HttpArtifactBindingConstants.ArtifactTypeCode, localEndpointIndex, sourceIdHash, messageHandle);

            cacheInsert(artifact, signedSamlMessage);

            var destinationUrl = destination.Url + "?" + HttpArtifactBindingConstants.ArtifactQueryStringName + "=" + Uri.EscapeDataString(artifact);

            if (!string.IsNullOrEmpty(relayState))
            {
                destinationUrl += "&relayState=" + relayState;
            }

            _logger.LogDebug(TraceMessages.ArtifactCreated, artifact);

            redirect(destinationUrl);
        }