/// <summary> /// Initializes a new instance of the ArtifactResolve class. /// </summary> /// <param name="serviceProvider">Service Provider to issue this request</param> /// <param name="artifact">SAMLv2 Artifact</param> public ArtifactResolve(ServiceProvider serviceProvider, Artifact artifact) { this.xml = new XmlDocument(); this.xml.PreserveWhitespace = true; this.nsMgr = new XmlNamespaceManager(this.xml.NameTable); this.nsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"); this.nsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); this.Id = Saml2Utils.GenerateId(); this.IssueInstant = Saml2Utils.GenerateIssueInstant(); this.Issuer = serviceProvider.EntityId; this.Artifact = artifact; StringBuilder rawXml = new StringBuilder(); rawXml.Append("<samlp:ArtifactResolve"); rawXml.Append(" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\""); rawXml.Append(" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\""); rawXml.Append(" ID=\"" + this.Id + "\""); rawXml.Append(" Version=\"2.0\""); rawXml.Append(" IssueInstant=\"" + this.IssueInstant + "\""); rawXml.Append(">"); rawXml.Append(" <saml:Issuer>" + this.Issuer + "</saml:Issuer>"); rawXml.Append(" <samlp:Artifact>" + this.Artifact.ToString() + "</samlp:Artifact>"); rawXml.Append("</samlp:ArtifactResolve>"); this.xml.LoadXml(rawXml.ToString()); }
/// <summary> /// Initializes a new instance of the LogoutRequest class. /// </summary> /// <param name="identityProvider"> /// IdentityProvider of the LogoutRequest /// </param> /// <param name="serviceProvider"> /// ServiceProvider of the LogoutRequest /// </param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the LogoutRequest. /// </param> public LogoutRequest( IdentityProvider identityProvider, ServiceProvider serviceProvider, NameValueCollection parameters) { try { this.xml = new XmlDocument(); this.xml.PreserveWhitespace = true; this.nsMgr = new XmlNamespaceManager(this.xml.NameTable); this.nsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); this.nsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); this.nsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"); string sessionIndex = null; string subjectNameId = null; string binding = null; string destination = null; if (parameters != null) { sessionIndex = parameters[Saml2Constants.SessionIndex]; subjectNameId = parameters[Saml2Constants.SubjectNameId]; binding = parameters[Saml2Constants.Binding]; destination = parameters[Saml2Constants.Destination]; } if (String.IsNullOrEmpty(sessionIndex)) { throw new Saml2Exception(Resources.LogoutRequestSessionIndexNotDefined); } else if (String.IsNullOrEmpty(subjectNameId)) { throw new Saml2Exception(Resources.LogoutRequestSubjectNameIdNotDefined); } else if (serviceProvider == null) { throw new Saml2Exception(Resources.LogoutRequestServiceProviderIsNull); } else if (identityProvider == null) { throw new Saml2Exception(Resources.LogoutRequestIdentityProviderIsNull); } if (string.IsNullOrEmpty(destination)) { destination = identityProvider.GetSingleLogoutServiceLocation(binding); if (string.IsNullOrEmpty(destination)) { // default with HttpRedirect destination = identityProvider.GetSingleLogoutServiceLocation(Saml2Constants.HttpRedirectProtocolBinding); } } StringBuilder rawXml = new StringBuilder(); rawXml.Append("<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\""); rawXml.Append(" ID=\"" + Saml2Utils.GenerateId() + "\""); rawXml.Append(" Version=\"2.0\""); rawXml.Append(" IssueInstant=\"" + Saml2Utils.GenerateIssueInstant() + "\""); if (!String.IsNullOrEmpty(destination)) { rawXml.Append(" Destination=\"" + destination + "\""); } rawXml.Append(" >"); rawXml.Append(" <saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\""); rawXml.Append(" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\""); rawXml.Append(" NameQualifier=\"" + identityProvider.EntityId + "\">" + subjectNameId + "</saml:NameID> "); rawXml.Append(" <saml:SessionIndex xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" + sessionIndex + "</saml:SessionIndex>"); rawXml.Append(" <saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" + serviceProvider.EntityId + "</saml:Issuer>"); rawXml.Append("</samlp:LogoutRequest>"); this.xml.LoadXml(rawXml.ToString()); } catch (ArgumentNullException ane) { throw new Saml2Exception(Resources.LogoutRequestNullArgument, ane); } catch (XmlException xe) { throw new Saml2Exception(Resources.LogoutRequestXmlException, xe); } }
/// <summary> /// Internal method to load configuration information and metadata /// for the hosted service provider and associated identity providers. /// </summary> /// <param name="homeFolder">Home folder containing configuration and metadata.</param> private void Initialize(string homeFolder) { DirectoryInfo dirInfo = new DirectoryInfo(homeFolder); if (!dirInfo.Exists) { throw new ServiceProviderUtilityException(Resources.ServiceProviderUtilityHomeFolderNotFound); } this.homeFolder = homeFolder; // Load the metadata for this service provider. this.ServiceProvider = new ServiceProvider(this.homeFolder); // Load the configuration for one or more circle of trusts. this.CircleOfTrusts = new Hashtable(); this.InitializeCircleOfTrusts(); // Load metadata for one or more identity providers. this.IdentityProviders = new Hashtable(); this.InitializeIdentityProviders(); }
/// <summary> /// Initializes a new instance of the LogoutResponse class based on /// the complimentary logout request. /// </summary> /// <param name="identityProvider"> /// IdentityProvider of the LogoutResponse /// </param> /// <param name="serviceProvider"> /// ServiceProvider of the LogoutResponse /// </param> /// <param name="logoutRequest"> /// Logout request that requires this response /// </param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the LogoutResponse. /// </param> public LogoutResponse( IdentityProvider identityProvider, ServiceProvider serviceProvider, LogoutRequest logoutRequest, NameValueCollection parameters) { if (identityProvider == null) { throw new Saml2Exception(Resources.LogoutResponseIdentityProviderIsNull); } else if (serviceProvider == null) { throw new Saml2Exception(Resources.LogoutResponseServiceProviderIsNull); } else if (logoutRequest == null) { throw new Saml2Exception(Resources.LogoutResponseLogoutRequestIsNull); } if (parameters == null) { parameters = new NameValueCollection(); } string inResponseToValue = logoutRequest.Id; string issuerValue = serviceProvider.EntityId; string binding = parameters[Saml2Constants.Binding]; if (string.IsNullOrEmpty(binding)) { binding = Saml2Constants.HttpPostProtocolBinding; } string idpSvcResponseLocation = null; if (binding != Saml2Constants.HttpSoapProtocolBinding) { idpSvcResponseLocation = identityProvider.GetSingleLogoutServiceResponseLocation(binding); } this.xml = new XmlDocument(); this.xml.PreserveWhitespace = true; this.nsMgr = new XmlNamespaceManager(this.xml.NameTable); this.nsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"); this.nsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); StringBuilder rawXml = new StringBuilder(); rawXml.Append("<samlp:LogoutResponse xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" "); rawXml.Append(" ID=\"" + Saml2Utils.GenerateId() + "\" Version=\"2.0\" "); rawXml.Append(" IssueInstant=\"" + Saml2Utils.GenerateIssueInstant() + "\" "); if (idpSvcResponseLocation != null) { rawXml.Append(" Destination=\"" + idpSvcResponseLocation + "\" "); } rawXml.Append(" InResponseTo=\"" + inResponseToValue + "\">"); rawXml.Append(" <saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" + issuerValue + "</saml:Issuer>"); rawXml.Append(" <samlp:Status xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">"); rawXml.Append(" <samlp:StatusCode "); rawXml.Append(" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" "); rawXml.Append(" Value=\"" + Saml2Constants.Success + "\">"); rawXml.Append(" </samlp:StatusCode>"); rawXml.Append(" </samlp:Status>"); rawXml.Append("</samlp:LogoutResponse>"); this.xml.LoadXml(rawXml.ToString()); }
/// <summary> /// Initializes a new instance of the AuthnRequest class. /// </summary> /// <param name="identityProvider"> /// IdentityProvider to receive the AuthnRequest /// </param> /// <param name="serviceProvider"> /// ServiceProvider to issue the AuthnRequest /// </param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the AuthnRequest. /// </param> public AuthnRequest(IdentityProvider identityProvider, ServiceProvider serviceProvider, NameValueCollection parameters) { this.xml = new XmlDocument(); this.xml.PreserveWhitespace = true; this.nsMgr = new XmlNamespaceManager(this.xml.NameTable); this.nsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); this.nsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"); this.Id = Saml2Utils.GenerateId(); this.IssueInstant = Saml2Utils.GenerateIssueInstant(); this.Issuer = serviceProvider.EntityId; if (parameters != null) { this.AllowCreate = Saml2Utils.GetBoolean(parameters[Saml2Constants.AllowCreate]); this.AssertionConsumerServiceIndex = parameters[Saml2Constants.AssertionConsumerServiceIndex]; this.Binding = parameters[Saml2Constants.Binding]; this.Consent = parameters[Saml2Constants.Consent]; this.Destination = parameters[Saml2Constants.Destination]; this.ForceAuthn = Saml2Utils.GetBoolean(parameters[Saml2Constants.ForceAuthn]); this.IsPassive = Saml2Utils.GetBoolean(parameters[Saml2Constants.IsPassive]); } string assertionConsumerSvcUrl = null; if (!String.IsNullOrEmpty(this.Binding)) { if (!String.IsNullOrEmpty(this.AssertionConsumerServiceIndex)) { // find assertion consumer service location by binding and index. assertionConsumerSvcUrl = serviceProvider.GetAssertionConsumerServiceLocation(this.Binding, this.AssertionConsumerServiceIndex); } else { // find assertion consumer service location by binding only, using first found. assertionConsumerSvcUrl = serviceProvider.GetAssertionConsumerServiceLocation(this.Binding); } } // neither index nor binding, throw exception if (String.IsNullOrEmpty(this.AssertionConsumerServiceIndex) && String.IsNullOrEmpty(assertionConsumerSvcUrl)) { throw new Saml2Exception(Resources.AuthnRequestAssertionConsumerServiceNotDefined); } // If destination not specified, use SSO location by binding if (string.IsNullOrEmpty(this.Destination)) { this.Destination = identityProvider.GetSingleSignOnServiceLocation(parameters[Saml2Constants.RequestBinding]); if (string.IsNullOrEmpty(this.Destination)) { // default to HttpRedirect this.Destination = identityProvider.GetSingleSignOnServiceLocation(Saml2Constants.HttpRedirectProtocolBinding); } } // Get RequestedAuthnContext if parameters are available... RequestedAuthnContext reqAuthnContext = GetRequestedAuthnContext(serviceProvider, parameters); // Generate the XML for the AuthnRequest... StringBuilder rawXml = new StringBuilder(); rawXml.Append("<samlp:AuthnRequest "); rawXml.Append(" xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\""); rawXml.Append(" ID=\"" + this.Id + "\""); rawXml.Append(" Version=\"2.0\""); rawXml.Append(" IssueInstant=\"" + this.IssueInstant + "\""); rawXml.Append(" IsPassive=\"" + this.IsPassive + "\""); rawXml.Append(" ForceAuthn=\"" + this.ForceAuthn + "\""); if (!String.IsNullOrEmpty(this.Consent)) { rawXml.Append(" Consent=\"" + this.Consent + "\""); } if (!String.IsNullOrEmpty(this.Destination)) { rawXml.Append(" Destination=\"" + this.Destination + "\""); } if (!String.IsNullOrEmpty(assertionConsumerSvcUrl)) { rawXml.Append(" ProtocolBinding=\"" + this.Binding + "\""); rawXml.Append(" AssertionConsumerServiceURL=\"" + assertionConsumerSvcUrl + "\""); } else { rawXml.Append(" AssertionConsumerIndex=\"" + this.AssertionConsumerServiceIndex + "\""); } rawXml.Append(">"); rawXml.Append("<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">" + serviceProvider.EntityId + "</saml:Issuer>"); if (reqAuthnContext != null) { rawXml.Append(reqAuthnContext.GenerateXmlString()); } rawXml.Append("<samlp:NameIdPolicy AllowCreate=\"" + this.AllowCreate + "\" />"); rawXml.Append("</samlp:AuthnRequest>"); this.xml.LoadXml(rawXml.ToString()); }
/// <summary> /// Getst the RequestedAuthnContext element based on supplied /// parameters for the given service provider. /// <seealso cref="Saml2Constants.AuthnContextClassRef"/> /// <seealso cref="Saml2Constants.AuthnContextDeclRef"/> /// <seealso cref="Saml2Constants.AuthLevel"/> /// </summary> /// <param name="serviceProvider"> /// Service Provider generating the RequestedAuthnContext. /// </param> /// <param name="parameters"> /// NameValueCollection containing necessary parameters for /// constructing the RequetedAuthnContext. /// </param> /// <returns>RequestedAuthContext object or null if parameters are not present.</returns> private static RequestedAuthnContext GetRequestedAuthnContext(ServiceProvider serviceProvider, NameValueCollection parameters) { RequestedAuthnContext reqAuthnContext = null; if (!String.IsNullOrEmpty(parameters[Saml2Constants.AuthnContextClassRef]) || !String.IsNullOrEmpty(parameters[Saml2Constants.AuthnContextDeclRef]) || !String.IsNullOrEmpty(parameters[Saml2Constants.AuthLevel])) { reqAuthnContext = new RequestedAuthnContext(); ArrayList classRefs = new ArrayList(); ArrayList declRefs = new ArrayList(); char[] separators = { '|' }; if (!String.IsNullOrEmpty(parameters[Saml2Constants.AuthnContextClassRef])) { classRefs.AddRange(parameters[Saml2Constants.AuthnContextClassRef].Split(separators)); } if (!String.IsNullOrEmpty(parameters[Saml2Constants.AuthnContextDeclRef])) { declRefs.AddRange(parameters[Saml2Constants.AuthnContextDeclRef].Split(separators)); } if (!String.IsNullOrEmpty(parameters[Saml2Constants.AuthLevel])) { int authLevel = Convert.ToInt32(parameters[Saml2Constants.AuthLevel], CultureInfo.InvariantCulture); classRefs.Add(serviceProvider.GetAuthnContextClassRefFromAuthLevel(authLevel)); } reqAuthnContext.SetAuthnContextClassRef(classRefs); reqAuthnContext.SetAuthnContextDeclRef(declRefs); if (!String.IsNullOrEmpty(parameters[Saml2Constants.AuthComparison])) { reqAuthnContext.Comparison = parameters[Saml2Constants.AuthComparison]; } } return reqAuthnContext; }
/// <summary> /// Recursively decrypts the received SAML response. /// </summary> /// <param name="serviceProvider">ServiceProvider instance, so we can extract /// information about the SP configuration.</param> public void Decrypt(ServiceProvider serviceProvider) { try { FedletEncryptedXml encXml = new FedletEncryptedXml(xml, serviceProvider); encXml.DecryptDocument(); Normalize(); } catch (CryptographicException ce) { throw new Saml2Exception(Resources.DecryptionFailed, ce); } }
/// <summary> /// Initializes a new instance of the AttributeQueryRequest class. /// </summary> /// <param name="identityProvider"> /// IdentityProvider of the AttributeQueryRequest /// </param> /// <param name="serviceProvider"> /// ServiceProvider of the AttributeQueryRequest /// </param> /// <param name="parameters"> /// NameValueCollection of varying parameters for use in the /// construction of the AttributeQueryRequest. /// </param> /// <param name="attributes"> /// List of SamlAttribute to query /// </param> public AttributeQueryRequest(IdentityProvider identityProvider, ServiceProvider serviceProvider, NameValueCollection parameters, List<SamlAttribute> attributes) { try { this.xml = new XmlDocument(); this.xml.PreserveWhitespace = true; this.X509SubjectName = false; this.nsMgr = new XmlNamespaceManager(this.xml.NameTable); this.nsMgr.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#"); this.nsMgr.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion"); this.nsMgr.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol"); string subjectNameId = null; if (parameters != null) { subjectNameId = parameters[Saml2Constants.SubjectNameId]; this.X509SubjectName = Saml2Utils.GetBoolean(parameters[Saml2Constants.X509SubjectName]); } if (string.IsNullOrWhiteSpace(subjectNameId)) { throw new Saml2Exception(Resources.AttributeQueryRequestSubjectNameIdNotDefined); } else if (serviceProvider == null) { throw new Saml2Exception(Resources.AttributeQueryRequestServiceProviderIsNull); } else if (identityProvider == null) { throw new Saml2Exception(Resources.AttributeQueryRequestIdentityProviderIsNull); } else if (attributes == null || attributes.Count == 0) { throw new Saml2Exception(Resources.AttributeQueryRequestIsEmpty); } StringBuilder rawXml = new StringBuilder(); rawXml.Append("<samlp:AttributeQuery xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\""); rawXml.Append(" ID=\"" + Saml2Utils.GenerateId() + "\""); rawXml.Append(" Version=\"2.0\""); rawXml.Append(" IssueInstant=\"" + Saml2Utils.GenerateIssueInstant() + "\">"); rawXml.Append("<saml:Issuer>" + serviceProvider.EntityId + "</saml:Issuer>"); rawXml.Append("<saml:Subject>"); rawXml.Append("<saml:NameID"); if (this.X509SubjectName) { rawXml.Append(" Format=\"urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName\""); } else { rawXml.Append(" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\""); } rawXml.Append(" SPNameQualifier=\"" + serviceProvider.EntityId + "\""); rawXml.Append(" NameQualifier=\"" + identityProvider.EntityId + "\">" + subjectNameId + "</saml:NameID>"); rawXml.Append("</saml:Subject>"); foreach (SamlAttribute attr in attributes) { if (attr != null) { rawXml.Append(attr.ToString()); } } rawXml.Append("</samlp:AttributeQuery>"); this.xml.LoadXml(rawXml.ToString()); } catch (ArgumentNullException ane) { throw new Saml2Exception(Resources.AttributeQueryRequestNullArgument, ane); } catch (XmlException xe) { throw new Saml2Exception(Resources.AttributeQueryRequestXmlException, xe); } }
public FedletEncryptedXml(XmlDocument doc, ServiceProvider sp) : base(doc) { serviceProvider = sp; }
/// <summary> /// Decrypts the authnResponse, then modifies the artifactresponse too. /// </summary> /// <param name="serviceProvider">ServiceProvider instance, so we can extract /// information about the SP configuration.</param> public void Decrypt(ServiceProvider serviceProvider) { authnResponse.Decrypt(serviceProvider); XmlNode node = xml.SelectSingleNode("//samlp:Response", nsMgr).ParentNode; node.InnerXml = ((XmlNode)authnResponse.XmlDom).InnerXml; }
/// <summary> /// Signs the specified xml document with the certificate found in /// the local machine matching the provided friendly name and /// referring to the specified target reference ID. /// </summary> /// <param name="certFriendlyName"> /// Friendly Name of the X509Certificate to be retrieved /// from the LocalMachine keystore and used to sign the xml document. /// Be sure to have appropriate permissions set on the keystore. /// </param> /// <param name="xmlDoc"> /// XML document to be signed. /// </param> /// <param name="targetReferenceId"> /// Reference element that will be specified as signed. /// </param> /// <param name="includePublicKey"> /// Flag to determine whether to include the public key in the /// signed xml. /// </param> /// <param name="signatureSigningAlgorithm"> /// The algorithm used to sign the xml. /// </param> /// <param name="digestAlgorithm"> /// The method used to create the message digest. /// </param> /// <param name="serviceProviderInstance"> /// ServiceProvider instance for retreaving Signature transform /// and canonicalization method /// </param> public static void SignXml(string certFriendlyName, IXPathNavigable xmlDoc, string targetReferenceId, bool includePublicKey, string signatureSigningAlgorithm, string digestAlgorithm, ServiceProvider serviceProviderInstance) { if (string.IsNullOrEmpty(certFriendlyName)) { throw new Saml2Exception(Resources.SignedXmlInvalidCertFriendlyName); } if (xmlDoc == null) { throw new Saml2Exception(Resources.SignedXmlInvalidXml); } if (string.IsNullOrEmpty(targetReferenceId)) { throw new Saml2Exception(Resources.SignedXmlInvalidTargetRefId); } X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName); if (cert == null) { throw new Saml2Exception(Resources.SignedXmlCertNotFound); } XmlDocument xml = (XmlDocument)xmlDoc; SignedXml signedXml = new SignedXml(xml); var cspParams = new CspParameters(24) { KeyContainerName = "XML_DISG_RSA_KEY" }; var key = new RSACryptoServiceProvider(cspParams); key.FromXmlString(cert.PrivateKey.ToXmlString(true)); signedXml.SigningKey = key; if (includePublicKey) { KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; } Reference reference = new Reference(); reference.Uri = "#" + targetReferenceId; //Read the transform type, signature digest and canonicalization method from sp-extended.xml string transformType = serviceProviderInstance.SignatureTransformMethod; string canonicalizationMethodType = serviceProviderInstance.CanonicalizationMethod; Transform sigTransform; //Implement the gathered data switch (transformType) { case "XmlDsigExcC14NTransform": sigTransform = new XmlDsigExcC14NTransform(); break; case "XmlDsigExcC14NWithCommentsTransform": sigTransform = new XmlDsigExcC14NWithCommentsTransform(); break; default: sigTransform = new XmlDsigEnvelopedSignatureTransform(); break; } if (canonicalizationMethodType != null && (canonicalizationMethodType == SignedXml.XmlDsigExcC14NTransformUrl || canonicalizationMethodType == SignedXml.XmlDsigExcC14NWithCommentsTransformUrl)) { signedXml.Signature.SignedInfo.CanonicalizationMethod = canonicalizationMethodType; } reference.AddTransform(sigTransform); bool bIsUsingExtendedAlgorithms = false; if (!String.IsNullOrEmpty(digestAlgorithm)) { reference.DigestMethod = digestAlgorithm; if (!digestAlgorithm.ToLowerInvariant().Contains("xmldsig#sha1")) { bIsUsingExtendedAlgorithms = true; } } signedXml.AddReference(reference); if (!String.IsNullOrEmpty(signatureSigningAlgorithm)) { signedXml.SignedInfo.SignatureMethod = signatureSigningAlgorithm; if (!signatureSigningAlgorithm.ToLowerInvariant().Contains("-sha1")) { bIsUsingExtendedAlgorithms = true; } } if (bIsUsingExtendedAlgorithms && !FedletSignedSignatureSupportSingleton.IsInitialised) { throw new Saml2Exception(Resources.ExtendedAlgorithmsUnavailable); } signedXml.ComputeSignature(); XmlElement xmlSignature = signedXml.GetXml(); XmlNamespaceManager nsMgr = new XmlNamespaceManager(xml.NameTable); nsMgr.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl); nsMgr.AddNamespace("saml", Saml2Constants.NamespaceSamlAssertion); nsMgr.AddNamespace("samlp", Saml2Constants.NamespaceSamlProtocol); XmlNode issuerNode = xml.DocumentElement.SelectSingleNode("saml:Issuer", nsMgr); if (issuerNode != null) { xml.DocumentElement.InsertAfter(xmlSignature, issuerNode); } else { // Insert as a child to the target reference id XmlNode targetNode = xml.DocumentElement.SelectSingleNode("//*[@ID='" + targetReferenceId + "']", nsMgr); targetNode.PrependChild(xmlSignature); } }
/// <summary> /// Signs the specified xml document with the certificate found in /// the local machine matching the provided friendly name and /// referring to the specified target reference ID. /// </summary> /// <param name="certFriendlyName"> /// Friendly Name of the X509Certificate to be retrieved /// from the LocalMachine keystore and used to sign the xml document. /// Be sure to have appropriate permissions set on the keystore. /// </param> /// <param name="xmlDoc"> /// XML document to be signed. /// </param> /// <param name="targetReferenceId"> /// Reference element that will be specified as signed. /// </param> /// <param name="includePublicKey"> /// Flag to determine whether to include the public key in the /// signed xml. /// </param> /// <param name="serviceProviderInstance"> /// ServiceProvider instance for retreaving Signature transform /// and canonicalization method /// </param> public static void SignXml(string certFriendlyName, IXPathNavigable xmlDoc, string targetReferenceId, bool includePublicKey, ServiceProvider serviceProviderInstance) { if (string.IsNullOrEmpty(certFriendlyName)) { throw new Saml2Exception(Resources.SignedXmlInvalidCertFriendlyName); } if (xmlDoc == null) { throw new Saml2Exception(Resources.SignedXmlInvalidXml); } if (string.IsNullOrEmpty(targetReferenceId)) { throw new Saml2Exception(Resources.SignedXmlInvalidTargetRefId); } X509Certificate2 cert = FedletCertificateFactory.GetCertificateByFriendlyName(certFriendlyName); if (cert == null) { throw new Saml2Exception(Resources.SignedXmlCertNotFound); } XmlDocument xml = (XmlDocument)xmlDoc; SignedXml signedXml = new SignedXml(xml); signedXml.SigningKey = cert.PrivateKey; if (includePublicKey) { KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new KeyInfoX509Data(cert)); signedXml.KeyInfo = keyInfo; } Reference reference = new Reference(); reference.Uri = "#" + targetReferenceId; //Read the transform type and canonicalization method from sp-extended.xml string transformType = serviceProviderInstance.SignatureTransformMethod; string canonicalizationMethodType = serviceProviderInstance.CanonicalizationMethod; Transform sigTransform; //Implement the gathered data switch(transformType){ case "XmlDsigExcC14NTransform": sigTransform = new XmlDsigExcC14NTransform(); break; case "XmlDsigExcC14NWithCommentsTransform": sigTransform = new XmlDsigExcC14NWithCommentsTransform(); break; default: sigTransform = new XmlDsigEnvelopedSignatureTransform(); break; } if (canonicalizationMethodType != null && (canonicalizationMethodType == SignedXml.XmlDsigExcC14NTransformUrl || canonicalizationMethodType == SignedXml.XmlDsigExcC14NWithCommentsTransformUrl)) { signedXml.Signature.SignedInfo.CanonicalizationMethod = canonicalizationMethodType; } reference.AddTransform(sigTransform); signedXml.AddReference(reference); signedXml.ComputeSignature(); XmlElement xmlSignature = signedXml.GetXml(); XmlNamespaceManager nsMgr = new XmlNamespaceManager(xml.NameTable); nsMgr.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl); nsMgr.AddNamespace("saml", Saml2Constants.NamespaceSamlAssertion); nsMgr.AddNamespace("samlp", Saml2Constants.NamespaceSamlProtocol); XmlNode issuerNode = xml.DocumentElement.SelectSingleNode("saml:Issuer", nsMgr); if (issuerNode != null) { xml.DocumentElement.InsertAfter(xmlSignature, issuerNode); } else { // Insert as a child to the target reference id XmlNode targetNode = xml.DocumentElement.SelectSingleNode("//*[@ID='" + targetReferenceId + "']", nsMgr); targetNode.PrependChild(xmlSignature); } }
private static Scoping GetScoping(ServiceProvider serviceProvider) { Scoping scoping = null; if (serviceProvider.ScopingProxyCount > 0) { scoping = new Scoping(); ArrayList idpEntry = new ArrayList(); idpEntry.AddRange(serviceProvider.ScopingIDPList); scoping.SetIDPEntry(idpEntry); } return scoping; }