예제 #1
0
        /// <summary>
        /// Checks the signature of the given ArtifactResponse and embedded
        /// AuthnResponse used for the Artifact profile.
        /// </summary>
        /// <param name="artifactResponse">ArtifactResponse object.</param>
        /// <seealso cref="ServiceProviderUtility.ValidateForArtifact"/>
        private void CheckSignature(ArtifactResponse artifactResponse)
        {
            AuthnResponse authnResponse = artifactResponse.AuthnResponse;

            IdentityProvider identityProvider = (IdentityProvider)this.IdentityProviders[authnResponse.Issuer];
            if (identityProvider == null)
            {
                throw new Saml2Exception(Resources.InvalidIssuer);
            }

            XmlElement artifactResponseSignature = (XmlElement)artifactResponse.XmlSignature;
            XmlElement responseSignature = (XmlElement)authnResponse.XmlResponseSignature;
            XmlElement assertionSignature = (XmlElement)authnResponse.XmlAssertionSignature;

            XmlElement validationSignature = null;
            string validationSignatureCert = null;
            string validationReferenceId = null;

            if (this.ServiceProvider.WantArtifactResponseSigned && artifactResponseSignature == null)
            {
                throw new Saml2Exception(Resources.AuthnResponseInvalidSignatureMissingOnArtifactResponse);
            }
            else if (this.ServiceProvider.WantPostResponseSigned && responseSignature == null && artifactResponseSignature == null)
            {
                throw new Saml2Exception(Resources.AuthnResponseInvalidSignatureMissingOnResponse);
            }
            else if (this.ServiceProvider.WantAssertionsSigned && assertionSignature == null && responseSignature == null && artifactResponseSignature == null)
            {
                throw new Saml2Exception(Resources.AuthnResponseInvalidSignatureMissing);
            }

            // pick the ArtifactResponse, Response or the Assertion for further validation...
            if (artifactResponseSignature != null)
            {
                validationSignature = artifactResponseSignature;
                validationSignatureCert = artifactResponse.SignatureCertificate;
                validationReferenceId = artifactResponse.Id;
            }
            else if (responseSignature != null)
            {
                validationSignature = responseSignature;
                validationSignatureCert = authnResponse.ResponseSignatureCertificate;
                validationReferenceId = authnResponse.Id;
            }
            else
            {
                validationSignature = assertionSignature;
                validationSignatureCert = authnResponse.AssertionSignatureCertificate;
                validationReferenceId = authnResponse.AssertionId;
            }

            if (validationSignatureCert != null)
            {
                string idpCert = Regex.Replace(identityProvider.EncodedSigningCertificate, @"\s", string.Empty);
                validationSignatureCert = Regex.Replace(validationSignatureCert, @"\s", string.Empty);
                if (idpCert != validationSignatureCert)
                {
                    throw new Saml2Exception(Resources.AuthnResponseInvalidSignatureCertsDontMatch);
                }
            }

            // check the signature of the xml document (optional for artifact)
            if (validationSignature != null)
            {
                Saml2Utils.ValidateSignedXml(
                                             identityProvider.SigningCertificate,
                                             (XmlDocument)artifactResponse.XmlDom,
                                             validationSignature,
                                             validationReferenceId);
            }
        }
예제 #2
0
        /// <summary>
        /// Retrieve the ArtifactResponse object with the given SAMLv2 
        /// artifact.
        /// </summary>
        /// <param name="artifact">SAMLv2 artifact</param>
        /// <returns>ArtifactResponse object</returns>
        public ArtifactResponse GetArtifactResponse(Artifact artifact)
        {
            ArtifactResolve artifactResolve = new ArtifactResolve(this.ServiceProvider, artifact);
            ArtifactResponse artifactResponse = null;

            IdentityProvider idp = this.GetIdpFromArtifact(artifact);
            if (idp == null)
            {
                throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpNotDeterminedFromArtifact);
            }

            string artifactResolutionSvcLoc = idp.GetArtifactResolutionServiceLocation(Saml2Constants.HttpSoapProtocolBinding);
            if (artifactResolutionSvcLoc == null)
            {
                throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpArtifactResSvcLocNotDefined);
            }

            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                Uri artifactResolutionSvcUri = new Uri(artifactResolutionSvcLoc);
                request = (HttpWebRequest)WebRequest.Create(artifactResolutionSvcUri);
                XmlDocument artifactResolveXml = (XmlDocument)artifactResolve.XmlDom;

                if (idp.WantArtifactResolveSigned)
                {
                    if (string.IsNullOrEmpty(this.ServiceProvider.SigningCertificateAlias))
                    {
                        throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilitySignFailedNoCertAlias);
                    }
                    else
                    {
                        Saml2Utils.SignXml(
                            this.ServiceProvider.SigningCertificateAlias,
                            artifactResolveXml,
                            artifactResolve.Id,
                            true);
                    }
                }

                string soapMessage = Saml2Utils.CreateSoapMessage(artifactResolveXml.InnerXml);

                byte[] byteArray = Encoding.UTF8.GetBytes(soapMessage);
                request.ContentType = "text/xml";
                request.ContentLength = byteArray.Length;
                request.AllowAutoRedirect = false;
                request.Method = "POST";

                Stream requestStream = request.GetRequestStream();
                requestStream.Write(byteArray, 0, byteArray.Length);
                requestStream.Close();

                StringBuilder logMessage = new StringBuilder();
                logMessage.Append("ArtifactResolve:\r\n").Append(artifactResolveXml.OuterXml);
                FedletLogger.Info(logMessage.ToString());

                response = (HttpWebResponse)request.GetResponse();
                StreamReader streamReader = new StreamReader(response.GetResponseStream());
                string responseContent = streamReader.ReadToEnd();
                streamReader.Close();

                XmlDocument soapResponse = new XmlDocument();
                soapResponse.PreserveWhitespace = true;
                soapResponse.LoadXml(responseContent);

                XmlNamespaceManager soapNsMgr = new XmlNamespaceManager(soapResponse.NameTable);
                soapNsMgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
                soapNsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
                soapNsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
                soapNsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");

                XmlElement root = soapResponse.DocumentElement;
                XmlNode responseXml = root.SelectSingleNode("/soap:Envelope/soap:Body/samlp:ArtifactResponse", soapNsMgr);
                string artifactResponseXml = responseXml.OuterXml;

                artifactResponse = new ArtifactResponse(artifactResponseXml);

                if (artifactResolve.Id != artifactResponse.InResponseTo)
                {
                    throw new Saml2Exception(Resources.ArtifactResolutionInvalidInResponseTo);
                }
            }
            catch (WebException we)
            {
                throw new ServiceProviderUtilityException(Resources.ArtifactResolutionWebException, we);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return artifactResponse;
        }
 /// <summary>
 /// Validates the given ArtifactResponse object.
 /// </summary>
 /// <param name="artifactResponse">ArtifactResponse object.</param>
 /// <param name="authnRequests">
 /// Collection of previously sent authnRequests used to compare with
 /// the InResponseTo attribute (if present) of the embedded 
 /// AuthnResponse within the ArtifactResponse.
 /// </param>
 /// <see cref="ServiceProviderUtility.Validate(AuthnResponse, ICollection)"/>
 public void ValidateForArtifact(ArtifactResponse artifactResponse, ICollection authnRequests)
 {
     if (artifactResponse.XmlSignature == null && artifactResponse.AuthnResponse.isAssertionEncrypted())
     {
         artifactResponse.Decrypt(ServiceProvider);
         artifactResponse.AuthnResponse.Decrypt(ServiceProvider);
     }
     this.CheckSignature(artifactResponse);
     if (artifactResponse.AuthnResponse.isAssertionEncrypted())
     {
         artifactResponse.AuthnResponse.Decrypt(ServiceProvider);
     }
     this.Validate(artifactResponse.AuthnResponse, authnRequests);
 }
예제 #4
0
 /// <summary>
 /// Validates the given ArtifactResponse object.
 /// </summary>
 /// <param name="artifactResponse">ArtifactResponse object.</param>
 /// <param name="authnRequests">
 /// Collection of previously sent authnRequests used to compare with
 /// the InResponseTo attribute (if present) of the embedded 
 /// AuthnResponse within the ArtifactResponse.
 /// </param>
 /// <see cref="ServiceProviderUtility.Validate(AuthnResponse, ICollection)"/>
 public void ValidateForArtifact(ArtifactResponse artifactResponse, ICollection authnRequests)
 {
     this.CheckSignature(artifactResponse);
     this.Validate(artifactResponse.AuthnResponse, authnRequests);
 }
        /// <summary>
        /// Retrieve the ArtifactResponse object with the given SAMLv2 
        /// artifact.
        /// </summary>
        /// <param name="artifact">SAMLv2 artifact</param>
        /// <returns>ArtifactResponse object</returns>
        public ArtifactResponse GetArtifactResponse(Artifact artifact)
        {
            ArtifactResolve artifactResolve = new ArtifactResolve(this.ServiceProvider, artifact);
            ArtifactResponse artifactResponse = null;

            IdentityProvider idp = this.GetIdpFromArtifact(artifact);
            if (idp == null)
            {
                throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpNotDeterminedFromArtifact);
            }

            string artifactResolutionSvcLoc = idp.GetArtifactResolutionServiceLocation(Saml2Constants.HttpSoapProtocolBinding);
            if (artifactResolutionSvcLoc == null)
            {
                throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityIdpArtifactResSvcLocNotDefined);
            }

            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                Uri artifactResolutionSvcUri = new Uri(artifactResolutionSvcLoc);
                if (artifactResolutionSvcUri.Scheme == "https")
                {
                    System.Net.ServicePointManager.ServerCertificateValidationCallback +=
                    delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                    System.Security.Cryptography.X509Certificates.X509Chain chain,
                    System.Net.Security.SslPolicyErrors sslPolicyErrors)
                    {
                        if (ServiceProvider.TrustAllCerts
                            || sslPolicyErrors.HasFlag(System.Net.Security.SslPolicyErrors.None))
                            {
                                return true;
                            }

                        StringBuilder logErrorMessage = new StringBuilder();
                        logErrorMessage.Append("SSLPolicyError: ").Append(sslPolicyErrors);
                        FedletLogger.Error(logErrorMessage.ToString());
                        return false;
                    };
                }

                request = (HttpWebRequest)WebRequest.Create(artifactResolutionSvcUri);

                string authCertAlias = ConfigurationManager.AppSettings[Saml2Constants.MutualAuthCertAlias];
                if (artifactResolutionSvcUri.Scheme == "https" && !string.IsNullOrWhiteSpace(authCertAlias))
                {
                    X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(authCertAlias);
                    if (cert != null)
                    {
                        request.ClientCertificates.Add(cert);
                    }
                }

                XmlDocument artifactResolveXml = (XmlDocument)artifactResolve.XmlDom;

                if (idp.WantArtifactResolveSigned)
                {
                    if (string.IsNullOrEmpty(this.ServiceProvider.SigningCertificateAlias))
                    {
                        throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilitySignFailedNoCertAlias);
                    }
                    else
                    {
                        Saml2Utils.SignXml(
                            this.ServiceProvider.SigningCertificateAlias,
                            artifactResolveXml,
                            artifactResolve.Id,
                            true,
                            this.ServiceProvider);
                    }
                }

                string soapMessage = Saml2Utils.CreateSoapMessage(artifactResolveXml.InnerXml);

                byte[] byteArray = Encoding.UTF8.GetBytes(soapMessage);
                request.ContentType = "text/xml";
                request.ContentLength = byteArray.Length;
                request.AllowAutoRedirect = false;
                request.Method = "POST";

                Stream requestStream = request.GetRequestStream();
                requestStream.Write(byteArray, 0, byteArray.Length);
                requestStream.Close();

                StringBuilder logMessage = new StringBuilder();
                logMessage.Append("ArtifactResolve:\r\n").Append(artifactResolveXml.OuterXml);
                FedletLogger.Info(logMessage.ToString());

                response = (HttpWebResponse)request.GetResponse();
                StreamReader streamReader = new StreamReader(response.GetResponseStream());
                string responseContent = streamReader.ReadToEnd();
                streamReader.Close();

                XmlDocument soapResponse = new XmlDocument();
                soapResponse.PreserveWhitespace = true;
                soapResponse.LoadXml(responseContent);

                XmlNamespaceManager soapNsMgr = new XmlNamespaceManager(soapResponse.NameTable);
                soapNsMgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
                soapNsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
                soapNsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
                soapNsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");

                XmlElement root = soapResponse.DocumentElement;
                XmlNode responseXml = root.SelectSingleNode("/soap:Envelope/soap:Body/samlp:ArtifactResponse", soapNsMgr);
                string artifactResponseXml = responseXml.OuterXml;

                artifactResponse = new ArtifactResponse(artifactResponseXml);

                if (artifactResolve.Id != artifactResponse.InResponseTo)
                {
                    throw new Saml2Exception(Resources.ArtifactResolutionInvalidInResponseTo);
                }
            }
            catch (WebException we)
            {
                throw new ServiceProviderUtilityException(Resources.ArtifactResolutionWebException, we);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return artifactResponse;
        }