ShouldTrace() public static method

Ask the trace if a tracelevel is enabled. Use this if you want to determine if a message should be traced, before you build a complicated trace message.
public static ShouldTrace ( TraceEventType eventType ) : bool
eventType TraceEventType The tracelevel.
return bool
        private static XmlDocument GetDecodedSamlResponse(HttpContext context, Encoding encoding)
        {
            string base64 = context.Request.Params["SAMLResponse"];

            XmlDocument doc = new XmlDocument();

            doc.XmlResolver        = null;
            doc.PreserveWhitespace = true;
            string samlResponse = encoding.GetString(Convert.FromBase64String(base64));

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, "Decoded SAMLResponse", samlResponse);
            }

            doc.LoadXml(samlResponse);
            return(doc);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="Saml20SignonHandler"/> class.
        /// </summary>
        public Saml20SignonHandler()
        {
            _certificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate();

            // Read the proper redirect url from config
            try
            {
                RedirectUrl    = SAML20FederationConfig.GetConfig().ServiceProvider.SignOnEndpoint.RedirectUrl;
                ErrorBehaviour = SAML20FederationConfig.GetConfig().ServiceProvider.SignOnEndpoint.ErrorBehaviour.ToString();
            }
            catch (Exception e)
            {
                if (Trace.ShouldTrace(TraceEventType.Error))
                {
                    Trace.TraceData(TraceEventType.Error, e.ToString());
                }
            }
        }
Beispiel #3
0
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            //User is now logged in at IDP specified in tmp
            context.Session[IDPLoginSessionKey] = context.Session[IDPTempSessionKey];
            context.Session[IDPSessionIdKey]    = assertion.SessionIndex;
            context.Session[IDPNameIdFormat]    = assertion.Subject.Format;
            context.Session[IDPNameId]          = assertion.Subject.Value;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }

            string inResponseTo = "(unknown)";

            if (assertion.GetSubjectConfirmationData() != null && assertion.GetSubjectConfirmationData().InResponseTo != null)
            {
                inResponseTo = assertion.GetSubjectConfirmationData().InResponseTo;
            }

            string assuranceLevel = "(unknown)";

            foreach (var attribute in assertion.Attributes)
            {
                if (attribute.Name == "dk:gov:saml:attribute:AssuranceLevel" &&
                    attribute.AttributeValue != null &&
                    attribute.AttributeValue.Length > 0)
                {
                    assuranceLevel = attribute.AttributeValue[0];
                }
            }

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Subject: {0} NameIDFormat: {1}  Level of authentication: {2}  Session timeout in minutes: {3}", assertion.Subject.Value, assertion.Subject.Format, assuranceLevel, HttpContext.Current.Session.Timeout));


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
 public void Load(string base64AuthorisationsAttribute)
 {
     try
     {
         string             decoded        = Encoding.UTF8.GetString(Convert.FromBase64String(base64AuthorisationsAttribute));
         AuthorisationsType authorisations = Serialization.DeserializeFromXmlString <AuthorisationsType>(decoded);
         _autorisations = authorisations;
         _isLoaded      = true;
     }
     catch (Exception e)
     {
         _isLoaded = false;
         if (Trace.ShouldTrace(TraceEventType.Error))
         {
             Trace.TraceData(TraceEventType.Error, string.Format(Errors.DecodeFailed, base64AuthorisationsAttribute, e.Message));
         }
         throw new Saml20BRSException(Errors.DecodeFailedMsg, e);
     }
 }
Beispiel #5
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));
        }
Beispiel #6
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));
        }
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            //User is now logged in at IDP specified in tmp
            context.Session[IDPLoginSessionKey] = context.Session[IDPTempSessionKey];
            context.Session[IDPSessionIdKey]    = assertion.SessionIndex;
            context.Session[IDPNameIdFormat]    = assertion.Subject.Format;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }
            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, "Subject: " + assertion.Subject.Value + " NameIDFormat: " + assertion.Subject.Format);


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Beispiel #8
0
        private void DoLogin(HttpContext context, Saml20Assertion assertion)
        {
            SessionFactory.SessionContext.AssociateUserIdWithCurrentSession(assertion.Subject.Value);
            SessionFactory.SessionContext.Current[SessionConstants.Saml20AssertionLite] = Saml20AssertionLite.ToLite(assertion);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.Login, assertion.Subject.Value, assertion.SessionIndex, assertion.Subject.Format));
            }

            string assuranceLevel = GetAssuranceLevel(assertion) ?? "(Unknown)";

            AuditLogging.logEntry(Direction.IN, Operation.LOGIN, string.Format("Subject: {0} NameIDFormat: {1}  Level of authentication: {2}  Session timeout in minutes: {3}", assertion.Subject.Value, assertion.Subject.Format, assuranceLevel, FederationConfig.GetConfig().SessionTimeout));


            foreach (IAction action in Actions.Actions.GetActions())
            {
                Trace.TraceMethodCalled(action.GetType(), "LoginAction()");

                action.LoginAction(this, context, assertion);

                Trace.TraceMethodDone(action.GetType(), "LoginAction()");
            }
        }
Beispiel #9
0
        /// <summary>
        /// Performs the attribute query against the specified IdP endpoint and adds the resulting attributes to Saml20Identity.Current.
        /// </summary>
        /// <param name="context">The http context.</param>
        /// <param name="endPoint">The IdP to perform the query against.</param>
        /// <param name="nameIdFormat">The nameid format.</param>
        public void PerformQuery(HttpContext context, IDPEndPoint endPoint, string nameIdFormat)
        {
            Trace.TraceMethodCalled(GetType(), "PerformQuery()");

            HttpSOAPBindingBuilder builder = new HttpSOAPBindingBuilder(context);

            NameID name = new NameID();

            name.Value  = Saml20Identity.Current.Name;
            name.Format = nameIdFormat;
            _attrQuery.Subject.Items = new object[] { name };

            _attrQuery.SamlAttribute = _attributes.ToArray();
            XmlDocument query = new XmlDocument();

            query.XmlResolver = null;
            query.LoadXml(Serialization.SerializeToXmlString(_attrQuery));

            var signingCertificate  = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endPoint.ShaHashingAlgorithm);
            var signatureProvider   = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);

            signatureProvider.SignAssertion(query, ID, signingCertificate);
            if (query.FirstChild is XmlDeclaration)
            {
                query.RemoveChild(query.FirstChild);
            }

            Stream s;

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendAttrQuery, endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml));
            }

            try
            {
                s = builder.GetResponse(endPoint.metadata.GetAttributeQueryEndpointLocation(), query.OuterXml,
                                        endPoint.AttributeQuery);
            }
            catch (Exception e)
            {
                Trace.TraceData(TraceEventType.Error, e.ToString());
                throw;
            }

            HttpSOAPBindingParser parser = new HttpSOAPBindingParser(s);

            Status status = parser.GetStatus();

            if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
            {
                Trace.TraceData(TraceEventType.Error,
                                string.Format(Tracing.AttrQueryStatusError, Serialization.SerializeToXmlString(status)));
                throw new Saml20Exception(status.StatusMessage);
            }

            bool isEncrypted;

            XmlElement xmlAssertion = Saml20SignonHandler.GetAssertion(parser.SamlMessage, out isEncrypted);

            if (isEncrypted)
            {
                Saml20EncryptedAssertion ass =
                    new Saml20EncryptedAssertion(
                        (RSA)FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey);
                ass.LoadXml(xmlAssertion);
                ass.Decrypt();
                xmlAssertion = ass.Assertion.DocumentElement;
            }

            Saml20Assertion assertion =
                new Saml20Assertion(xmlAssertion, null,
                                    AssertionProfile.Core, endPoint.QuirksMode);

            assertion.Validate(DateTime.UtcNow);

            if (Trace.ShouldTrace(TraceEventType.Information))
            {
                Trace.TraceData(TraceEventType.Information, string.Format(Tracing.AttrQueryAssertion, xmlAssertion == null ? string.Empty : xmlAssertion.OuterXml));
            }

            IEnumerable <string> validationFailures;

            if (!assertion.CheckSignature(Saml20SignonHandler.GetTrustedSigners(endPoint.metadata.Keys, endPoint, out validationFailures)))
            {
                Trace.TraceData(TraceEventType.Error, Resources.SignatureInvalid);
                throw new Saml20Exception(Resources.SignatureInvalid);
            }

            foreach (SamlAttribute attr in assertion.Attributes)
            {
                Saml20Identity.Current.AddAttributeFromQuery(attr.Name, attr);
            }
        }
Beispiel #10
0
        private void TransferClient(IDPEndPoint endpoint, HttpContext context)
        {
            Trace.TraceMethodCalled(GetType(), "TransferClient()");

            Saml20LogoutRequest request = Saml20LogoutRequest.GetDefault();

            AuditLogging.AssertionId = request.ID;
            AuditLogging.IdpId       = endpoint.Id;

            // Determine which endpoint to use from the configuration file or the endpoint metadata.
            IDPEndPointElement destination =
                DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());

            request.Destination = destination.Url;

            request.SubjectToLogOut.Format = Saml20PrincipalCache.GetSaml20AssertionLite().Subject.Format;

            var shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(endpoint.ShaHashingAlgorithm);

            if (destination.Binding == SAMLBinding.POST)
            {
                HttpPostBindingBuilder builder = new HttpPostBindingBuilder(destination);
                request.Destination           = destination.Url;
                request.Reason                = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = Saml20PrincipalCache.GetSaml20AssertionLite().Subject.Value;
                request.SessionIndex          = Saml20PrincipalCache.GetSaml20AssertionLite().SessionIndex;
                XmlDocument requestDocument    = request.GetXml();
                var         signingCertificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
                var         signatureProvider  = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);
                signatureProvider.SignAssertion(requestDocument, request.ID, signingCertificate);
                builder.Request = requestDocument.OuterXml;

                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "POST", endpoint.Id, requestDocument.OuterXml));
                }

                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: POST");
                builder.GetPage().ProcessRequest(context);
                context.Response.End();
                return;
            }

            if (destination.Binding == SAMLBinding.REDIRECT)
            {
                HttpRedirectBindingBuilder builder = new HttpRedirectBindingBuilder();
                builder.signingKey            = FederationConfig.GetConfig().SigningCertificate.GetCertificate().PrivateKey;
                request.Destination           = destination.Url;
                request.Reason                = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = Saml20PrincipalCache.GetSaml20AssertionLite().Subject.Value;
                request.SessionIndex          = Saml20PrincipalCache.GetSaml20AssertionLite().SessionIndex;
                builder.Request               = request.GetXml().OuterXml;
                builder.ShaHashingAlgorithm   = shaHashingAlgorithm;

                string redirectUrl = destination.Url + "?" + builder.ToQuery();

                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "REDIRECT", endpoint.Id, redirectUrl));
                }

                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Binding: Redirect");
                context.Response.Redirect(redirectUrl, true);
                return;
            }

            if (destination.Binding == SAMLBinding.ARTIFACT)
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.SendLogoutRequest, "ARTIFACT", endpoint.Id, string.Empty));
                }

                request.Destination           = destination.Url;
                request.Reason                = Saml20Constants.Reasons.User;
                request.SubjectToLogOut.Value = Saml20PrincipalCache.GetSaml20AssertionLite().Subject.Value;
                request.SessionIndex          = Saml20PrincipalCache.GetSaml20AssertionLite().SessionIndex;

                HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);
                AuditLogging.logEntry(Direction.OUT, Operation.LOGOUTREQUEST, "Method: Artifact");
                builder.RedirectFromLogout(endpoint, destination, request, Guid.NewGuid().ToString("N"));
            }

            HandleError(context, Resources.BindingError);
        }
Beispiel #11
0
        private void HandleSOAP(HttpContext context, Stream inputStream)
        {
            Trace.TraceMethodCalled(GetType(), "HandleSOAP");

            HttpArtifactBindingParser  parser  = new HttpArtifactBindingParser(inputStream);
            HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);

            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            IDPEndPoint idp = RetrieveIDPConfiguration(parser.Issuer);
            var         shaHashingAlgorithm = SignatureProviderFactory.ValidateShaHashingAlgorithm(idp.ShaHashingAlgorithm);

            AuditLogging.IdpId = idp.Id;


            if (parser.IsArtifactResolve())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResolveIn);

                if (!parser.CheckSamlMessageSignature(idp.metadata.Keys))
                {
                    HandleError(context, "Invalid Saml message signature");
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, "Signature could not be verified", parser.SamlMessage);
                }
                AuditLogging.AssertionId = parser.ArtifactResolve.ID;
                AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, "", parser.SamlMessage);
                builder.RespondToArtifactResolve(idp, parser.ArtifactResolve);
            }
            else if (parser.IsArtifactResponse())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResponseIn);

                Status status = parser.ArtifactResponse.Status;
                if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unexpected status code for artifact response: {0}, expected 'Success', msg: {1}", status.StatusCode.Value, parser.SamlMessage));
                    HandleError(context, status);
                    return;
                }

                if (parser.ArtifactResponse.Any.LocalName == LogoutRequest.ELEMENT_NAME)
                {
                    if (Trace.ShouldTrace(TraceEventType.Information))
                    {
                        Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.ArtifactResponse.Any.OuterXml));
                    }

                    //Send logoutresponse via artifact
                    Saml20LogoutResponse response = new Saml20LogoutResponse();
                    response.Issuer = config.ServiceProvider.ID;
                    LogoutRequest req = Serialization.DeserializeFromXmlString <LogoutRequest>(parser.ArtifactResponse.Any.OuterXml);
                    response.StatusCode   = Saml20Constants.StatusCodes.Success;
                    response.InResponseTo = req.ID;
                    IDPEndPointElement destination =
                        DetermineEndpointConfiguration(SAMLBinding.REDIRECT, idp.SLOEndpoint, idp.metadata.SLOEndpoints());

                    builder.RedirectFromLogout(idp, destination, response);
                }
                else if (parser.ArtifactResponse.Any.LocalName == LogoutResponse.ELEMENT_NAME)
                {
                    DoLogout(context);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported payload message in ArtifactResponse: {0}, msg: {1}", parser.ArtifactResponse.Any.LocalName, parser.SamlMessage));
                    HandleError(context,
                                string.Format("Unsupported payload message in ArtifactResponse: {0}",
                                              parser.ArtifactResponse.Any.LocalName));
                }
            }
            else if (parser.IsLogoutReqest())
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.SamlMessage.OuterXml));
                }

                Saml20LogoutResponse response = new Saml20LogoutResponse();

                if (!parser.IsSigned())
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Signature not present in SOAP logout request, msg: " + parser.SamlMessage.OuterXml);
                    response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                }

                if (idp.metadata == null)
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Cannot find metadata for IdP: " + parser.Issuer);
                    // Not able to process the request as we do not know the IdP.
                    response.StatusCode = Saml20Constants.StatusCodes.NoAvailableIDP;
                }
                else
                {
                    Saml20MetadataDocument metadata = idp.metadata;

                    if (!parser.CheckSignature(metadata.GetKeys(KeyTypes.signing)))
                    {
                        AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. Invalid signature SOAP logout, msg: " + parser.SamlMessage.OuterXml);
                        response.StatusCode = Saml20Constants.StatusCodes.RequestDenied;
                    }
                }

                if (parser.GetNameID() != null && !string.IsNullOrEmpty(parser.GetNameID().Value))
                {
                    DoSoapLogout(context, parser.GetNameID().Value);
                }
                else
                {
                    AuditLogging.logEntry(Direction.IN, Operation.LOGOUTREQUEST, "Request has been denied. No user ID was supplied in SOAP logout request, msg: " + parser.SamlMessage.OuterXml);
                    response.StatusCode = Saml20Constants.StatusCodes.NoAuthnContext;
                }

                LogoutRequest req = parser.LogoutRequest;

                //Build the response object
                response.Issuer       = config.ServiceProvider.ID;
                response.StatusCode   = Saml20Constants.StatusCodes.Success;
                response.InResponseTo = req.ID;
                XmlDocument doc = response.GetXml();
                var         signingCertificate = FederationConfig.GetConfig().SigningCertificate.GetCertificate();
                var         signatureProvider  = SignatureProviderFactory.CreateFromShaHashingAlgorithmName(shaHashingAlgorithm);
                signatureProvider.SignAssertion(doc, response.ID, signingCertificate);
                if (doc.FirstChild is XmlDeclaration)
                {
                    doc.RemoveChild(doc.FirstChild);
                }

                builder.SendResponseMessage(doc.OuterXml);
            }
            else
            {
                Status s = parser.GetStatus();
                if (s != null)
                {
                    HandleError(context, s);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported SamlMessage element: {0}, msg: {1}", parser.SamlMessageName, parser.SamlMessage));
                    HandleError(context, string.Format("Unsupported SamlMessage element: {0}", parser.SamlMessageName));
                }
            }
        }
        /// <summary>
        /// Validates the Assertion's conditions
        /// Audience restrictions processing rules are:
        ///  - Within a single audience restriction condition in the assertion, the service must be configured
        ///    with an audience-list that contains at least one of the restrictions in the assertion ("OR" filter)
        ///  - When multiple audience restrictions are present within the same assertion, all individual audience
        ///    restriction conditions must be met ("AND" filter)
        /// </summary>
        private void ValidateConditions(Assertion assertion)
        {
            // Conditions are not required
            if (assertion.Conditions == null)
            {
                return;
            }

            bool oneTimeUseSeen        = false;
            bool proxyRestrictionsSeen = false;

            ValidateConditionsInterval(assertion.Conditions);

            foreach (ConditionAbstract cat in assertion.Conditions.Items)
            {
                if (cat is OneTimeUse)
                {
                    if (oneTimeUseSeen)
                    {
                        throw new Saml20FormatException("Assertion contained more than one condition of type OneTimeUse");
                    }
                    oneTimeUseSeen = true;
                    continue;
                }

                if (cat is ProxyRestriction)
                {
                    if (proxyRestrictionsSeen)
                    {
                        throw new Saml20FormatException("Assertion contained more than one condition of type ProxyRestriction");
                    }
                    proxyRestrictionsSeen = true;

                    ProxyRestriction proxyRestriction = (ProxyRestriction)cat;
                    if (!String.IsNullOrEmpty(proxyRestriction.Count))
                    {
                        uint res;
                        if (!UInt32.TryParse(proxyRestriction.Count, out res))
                        {
                            throw new Saml20FormatException("Count attribute of ProxyRestriction MUST BE a non-negative integer");
                        }
                    }

                    if (proxyRestriction.Audience != null)
                    {
                        foreach (string audience in proxyRestriction.Audience)
                        {
                            if (!Uri.IsWellFormedUriString(audience, UriKind.Absolute))
                            {
                                throw new Saml20FormatException("ProxyRestriction Audience MUST BE a wellformed uri");
                            }
                        }
                    }
                }

                // AudienceRestriction processing goes here (section 2.5.1.4 of [SAML2.0std])
                if (cat is AudienceRestriction)
                {
                    // No audience restrictions? No problems...
                    AudienceRestriction audienceRestriction = (AudienceRestriction)cat;
                    if (audienceRestriction.Audience == null || audienceRestriction.Audience.Count == 0)
                    {
                        continue;
                    }

                    // If there are no allowed audience uris configured for the service, the assertion is not
                    // valid for this service
                    if (_allowedAudienceUris == null || _allowedAudienceUris.Count < 1)
                    {
                        throw new Saml20FormatException("The service is not configured to meet any audience restrictions");
                    }

                    string match = null;
                    foreach (string audience in audienceRestriction.Audience)
                    {
                        //In QuirksMode this validation is omitted
                        if (!_quirksMode)
                        {
                            // The given audience value MUST BE a valid URI
                            if (!Uri.IsWellFormedUriString(audience, UriKind.Absolute))
                            {
                                throw new Saml20FormatException("Audience element has value which is not a wellformed absolute uri");
                            }
                        }

                        match =
                            _allowedAudienceUris.Find(
                                delegate(string allowedUri) { return(allowedUri.Equals(audience)); });
                        if (match != null)
                        {
                            break;
                        }
                    }

                    if (Trace.ShouldTrace(TraceEventType.Verbose))
                    {
                        string intended = "Intended uris: " + Environment.NewLine + String.Join(Environment.NewLine, audienceRestriction.Audience.ToArray());
                        string allowed  = "Allowed uris: " + Environment.NewLine + String.Join(Environment.NewLine, _allowedAudienceUris.ToArray());
                        Trace.TraceData(TraceEventType.Verbose, Trace.CreateTraceString(GetType(), "ValidateConditions"), intended, allowed);
                    }

                    if (match == null)
                    {
                        throw new Saml20FormatException("The service is not configured to meet the given audience restrictions");
                    }
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Handles the selection of an IDP. If only one IDP is found, the user is automatically redirected to it.
        /// If several are found, and nothing indicates to which one the user should be sent, this method returns null.
        /// </summary>
        public IDPEndPoint RetrieveIDP(HttpContext context)
        {
            SAML20FederationConfig config = SAML20FederationConfig.GetConfig();

            //If idpChoice is set, use it value
            if (!string.IsNullOrEmpty(context.Request.Params[IDPChoiceParameterName]))
            {
                AuditLogging.logEntry(Direction.IN, Operation.DISCOVER,
                                      "Using IDPChoiceParamater: " + context.Request.Params[IDPChoiceParameterName]);
                IDPEndPoint endPoint = config.FindEndPoint(context.Request.Params[IDPChoiceParameterName]);
                if (endPoint != null)
                {
                    return(endPoint);
                }
            }

            //If we have a common domain cookie, use it's value
            //It must have been returned from the local common domain cookie reader endpoint.
            if (!string.IsNullOrEmpty(context.Request.QueryString["_saml_idp"]))
            {
                CommonDomainCookie cdc = new CommonDomainCookie(context.Request.QueryString["_saml_idp"]);
                if (cdc.IsSet)
                {
                    IDPEndPoint endPoint = config.FindEndPoint(cdc.PreferredIDP);
                    if (endPoint != null)
                    {
                        if (Trace.ShouldTrace(TraceEventType.Information))
                        {
                            Trace.TraceData(TraceEventType.Information, "IDP read from Common Domain Cookie: " + cdc.PreferredIDP);
                        }

                        return(endPoint);
                    }

                    AuditLogging.logEntry(Direction.IN, Operation.DISCOVER, "Invalid IdP in Common Domain Cookie, IdP not found in list of IdPs: " + cdc.PreferredIDP);
                }
            }

            //If there is only one configured IDPEndPoint lets just use that
            if (config.IDPEndPoints.Count == 1 && config.IDPEndPoints[0].metadata != null)
            {
                AuditLogging.logEntry(Direction.IN, Operation.DISCOVER, "No IdP selected in Common Domain Cookie, using default IdP: " + config.IDPEndPoints[0].Name);
                return(config.IDPEndPoints[0]);
            }

            // If one of the endpoints are marked with default, use that one
            var defaultIdp = config.Endpoints.IDPEndPoints.Find(idp => idp.Default);

            if (defaultIdp != null)
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, "Using IdP marked as default: " + defaultIdp.Id);
                }

                return(defaultIdp);
            }

            // In case an Idp selection url has been configured, redirect to that one.
            if (!string.IsNullOrEmpty(config.Endpoints.idpSelectionUrl))
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, "Redirecting to idpSelectionUrl for selection of IDP: " + config.Endpoints.idpSelectionUrl);
                }

                context.Response.Redirect(config.Endpoints.idpSelectionUrl);
            }

            // If an IDPSelectionEvent handler is present, request the handler for an IDP endpoint to use.
            var idpEndpoint = IDPSelectionUtil.InvokeIDPSelectionEventHandler(config.Endpoints);

            if (idpEndpoint != null)
            {
                return(idpEndpoint);
            }

            return(null);
        }
        private void HandleSOAP(HttpContext context, Stream inputStream)
        {
            Trace.TraceMethodCalled(GetType(), "HandleSOAP");

            HttpArtifactBindingParser  parser  = new HttpArtifactBindingParser(inputStream);
            HttpArtifactBindingBuilder builder = new HttpArtifactBindingBuilder(context);
            SAML20FederationConfig     config  = SAML20FederationConfig.GetConfig();

            IDPEndPoint idp = RetrieveIDPConfiguration(parser.Issuer);

            AuditLogging.IdpId = idp.Id;


            if (parser.IsArtifactResolve())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResolveIn);

                if (!parser.CheckSamlMessageSignature(idp.metadata.Keys))
                {
                    HandleError(context, "Invalid Saml message signature");
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, "Signature could not be verified", parser.SamlMessage);
                }
                AuditLogging.AssertionId = parser.ArtifactResolve.ID;
                AuditLogging.logEntry(Direction.IN, Operation.ARTIFACTRESOLVE, "", parser.SamlMessage);
                builder.RespondToArtifactResolve(parser.ArtifactResolve);
            }
            else if (parser.IsArtifactResponse())
            {
                Trace.TraceData(TraceEventType.Information, Tracing.ArtifactResponseIn);

                Status status = parser.ArtifactResponse.Status;
                if (status.StatusCode.Value != Saml20Constants.StatusCodes.Success)
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unexpected status code for artifact response: {0}, expected 'Success', msg: {1}", status.StatusCode.Value, parser.SamlMessage));
                    HandleError(context, status);
                    return;
                }

                if (parser.ArtifactResponse.Any.LocalName == LogoutRequest.ELEMENT_NAME)
                {
                    if (Trace.ShouldTrace(TraceEventType.Information))
                    {
                        Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.ArtifactResponse.Any.OuterXml));
                    }

                    //Send logoutresponse via artifact
                    Saml20LogoutResponse response = new Saml20LogoutResponse();
                    response.Issuer = config.ServiceProvider.ID;
                    LogoutRequest req = Serialization.DeserializeFromXmlString <LogoutRequest>(parser.ArtifactResponse.Any.OuterXml);
                    response.StatusCode   = Saml20Constants.StatusCodes.Success;
                    response.InResponseTo = req.ID;
                    IDPEndPoint        endpoint    = RetrieveIDPConfiguration(context.Session[IDPLoginSessionKey].ToString());
                    IDPEndPointElement destination =
                        DetermineEndpointConfiguration(SAMLBinding.REDIRECT, endpoint.SLOEndpoint, endpoint.metadata.SLOEndpoints());

                    builder.RedirectFromLogout(destination, response);
                }
                else if (parser.ArtifactResponse.Any.LocalName == LogoutResponse.ELEMENT_NAME)
                {
                    DoLogout(context);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported payload message in ArtifactResponse: {0}, msg: {1}", parser.ArtifactResponse.Any.LocalName, parser.SamlMessage));
                    HandleError(context,
                                string.Format("Unsupported payload message in ArtifactResponse: {0}",
                                              parser.ArtifactResponse.Any.LocalName));
                }
            }
            else if (parser.IsLogoutReqest())
            {
                if (Trace.ShouldTrace(TraceEventType.Information))
                {
                    Trace.TraceData(TraceEventType.Information, string.Format(Tracing.LogoutRequest, parser.SamlMessage.OuterXml));
                }

                LogoutRequest req = parser.LogoutRequest;

                //Build the response object
                Saml20LogoutResponse response = new Saml20LogoutResponse();
                response.Issuer = config.ServiceProvider.ID;
                //response.Destination = destination.Url;
                response.StatusCode   = Saml20Constants.StatusCodes.Success;
                response.InResponseTo = req.ID;
                XmlDocument doc = response.GetXml();
                XmlSignatureUtils.SignDocument(doc, response.ID);
                if (doc.FirstChild is XmlDeclaration)
                {
                    doc.RemoveChild(doc.FirstChild);
                }

                builder.SendResponseMessage(doc.OuterXml);
            }
            else
            {
                Status s = parser.GetStatus();
                if (s != null)
                {
                    HandleError(context, s);
                }
                else
                {
                    AuditLogging.logEntry(Direction.UNDEFINED, Operation.ARTIFACTRESOLVE, string.Format("Unsupported SamlMessage element: {0}, msg: {1}", parser.SamlMessageName, parser.SamlMessage));
                    HandleError(context, string.Format("Unsupported SamlMessage element: {0}", parser.SamlMessageName));
                }
            }
        }