Merge pull request #3886 from anderius/feature/newlines-in-saml

KEYCLOAK-4489 SAML encrypted assertion with newlines fails during parsing
This commit is contained in:
Stian Thorgersen 2017-03-09 08:29:55 +01:00 committed by GitHub
commit 5b4e3434bb
3 changed files with 70 additions and 2 deletions

View file

@ -41,7 +41,6 @@ import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException; import org.keycloak.saml.common.exceptions.ProcessingException;
import org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException; import org.keycloak.saml.common.exceptions.fed.IssueInstantMissingException;
import org.keycloak.saml.common.util.DocumentUtil; import org.keycloak.saml.common.util.DocumentUtil;
import org.keycloak.saml.common.util.StaxParserUtil;
import org.keycloak.saml.common.util.StaxUtil; import org.keycloak.saml.common.util.StaxUtil;
import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response; import org.keycloak.saml.processing.api.saml.v2.response.SAML2Response;
import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature; import org.keycloak.saml.processing.api.saml.v2.sig.SAML2Signature;
@ -560,7 +559,7 @@ public class AssertionUtil {
SAMLParser parser = new SAMLParser(); SAMLParser parser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement); JAXPValidationUtil.checkSchemaValidation(decryptedDocumentElement);
AssertionType assertion = (AssertionType) parser.parse(StaxParserUtil.getXMLEventReader(DocumentUtil AssertionType assertion = (AssertionType) parser.parse(parser.createEventReader(DocumentUtil
.getNodeAsStream(decryptedDocumentElement))); .getNodeAsStream(decryptedDocumentElement)));
responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion)); responseType.replaceAssertion(oldID, new ResponseType.RTChoiceType(assertion));

View file

@ -16,11 +16,16 @@
*/ */
package org.keycloak.saml.processing.core.parsers.saml; package org.keycloak.saml.processing.core.parsers.saml;
import org.keycloak.common.util.Base64;
import org.keycloak.common.util.DerUtils;
import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.AssertionType;
import org.keycloak.dom.saml.v2.assertion.NameIDType; import org.keycloak.dom.saml.v2.assertion.NameIDType;
import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType; import org.keycloak.dom.saml.v2.metadata.EntityDescriptorType;
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
import java.io.InputStream; import java.io.InputStream;
import java.security.PrivateKey;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -35,12 +40,22 @@ import org.w3c.dom.Element;
/** /**
* Test class for SAML parser. * Test class for SAML parser.
* *
* To create SAML XML for use in the test, use for instance https://www.samltool.com, {@link #PRIVATE_KEY} and
* {@link #PUBLIC_CERT}.
*
* TODO: Add further tests. * TODO: Add further tests.
* *
* @author hmlnarik * @author hmlnarik
*/ */
public class SAMLParserTest { public class SAMLParserTest {
private static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOJDgeiUFOERg6N2qUeLjkE7HDzg4h2m4hMG8WDYLhuAm6k2pq+1SkRDvisD67y2AvXXFz069Vw5TMDnpbmGpigEbdr+YT7As+YpVhxI1nSwTzzEAuL2Ywun1FNfOFAeBt6hzQ/veJ+rc3D3BSgjeY/yiZNen36T3BD8pi3HojErAgMBAAECgYBWmtpVqKCZSXfmkJvYy70GkNaNItLJ4L+14rlvhS+YzVBHo6iHps+nc3qNwnFwCQb3DH5TrIaP50rOp5wSeEyOWk7fOJeAwM4Vsc3d+av/Iu/WwNDyAFW3gGO19YvccfGvEbToMPtppOt47UDK26xfibCwUFwEGg0hGc0gcVQWMQJBAPl8YnETSjI0wZuaSdkUp2/FtHEAZa1yFPtPx7CVCpUG53frKOAx2t0N7AQ2vQUNPqOas8gDGr5O5J+l9tjOD0MCQQDoK+asMuMnSClm/RZRFIckcToFwjfgNQY/AKN31k705jJr+3+er3VlODL7dpnF0X2mVDjiXIp4hH9K0qfW+TP5AkAQOIMaAPwQ+Zcg684jXBFq1freYf06YrF0iYJdO8N9Xv6LsHFu6i7lsnMG7xwpCOxqrLNFrNX/S5fXvW2oOPWLAkEAiTu547tIjaWX42ph0JdDsoTC+Tht8rck9ASam3Evxo5y62UDcHbh+2yWphDaoBVOIgzSeuqcZtRasY2G7AjtcQJAEiXYeHB5+lancDDkBhH8KKdl1+FORRB9kJ4gxTwrjLwprWFjdatMb3O+xJGss+KnVUa/THRa5CRX4pHh93711Q==";
/**
* The public certificate that corresponds to {@link #PRIVATE_KEY}.
*/
private static final String PUBLIC_CERT = "MIICXjCCAcegAwIBAgIBADANBgkqhkiG9w0BAQ0FADBLMQswCQYDVQQGEwJubzERMA8GA1UECAwIVmVzdGZvbGQxEzARBgNVBAoMCkV4YW1wbGVPcmcxFDASBgNVBAMMC2V4YW1wbGUub3JnMCAXDTE3MDIyNzEwNTY0MFoYDzIxMTcwMjAzMTA1NjQwWjBLMQswCQYDVQQGEwJubzERMA8GA1UECAwIVmVzdGZvbGQxEzARBgNVBAoMCkV4YW1wbGVPcmcxFDASBgNVBAMMC2V4YW1wbGUub3JnMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiQ4HolBThEYOjdqlHi45BOxw84OIdpuITBvFg2C4bgJupNqavtUpEQ74rA+u8tgL11xc9OvVcOUzA56W5hqYoBG3a/mE+wLPmKVYcSNZ0sE88xALi9mMLp9RTXzhQHgbeoc0P73ifq3Nw9wUoI3mP8omTXp9+k9wQ/KYtx6IxKwIDAQABo1AwTjAdBgNVHQ4EFgQUzWjvSL0O2V2B2N9G1qARQiVgv3QwHwYDVR0jBBgwFoAUzWjvSL0O2V2B2N9G1qARQiVgv3QwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOBgQBgvKTTcLGlF0KvnIGxkzdaFeYewQtsQZHgnUt+JGKge0CyUU+QPVFhrH19b7fjKeykq/avm/2hku4mKaPyRYpvU9Gm+ARz67rs/vr0ZgJFk00TGI6ssGhdFd7iCptuIh5lEvWk1hD5LzThOI3isq0gK2tTbhafQOkKa45IwbOQ8Q==";
private SAMLParser parser; private SAMLParser parser;
@Before @Before
@ -74,6 +89,28 @@ public class SAMLParserTest {
} }
} }
@Test
public void testSaml20EncryptedAssertionWithNewlines() throws Exception {
try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4489-encrypted-assertion-with-newlines.xml")) {
Object parsedObject = parser.parse(st);
assertThat(parsedObject, instanceOf(ResponseType.class));
ResponseType resp = (ResponseType) parsedObject;
assertThat(resp.getAssertions().size(), is(1));
ResponseType.RTChoiceType rtChoiceType = resp.getAssertions().get(0);
assertNull(rtChoiceType.getAssertion());
assertNotNull(rtChoiceType.getEncryptedAssertion());
PrivateKey privateKey = DerUtils.decodePrivateKey(Base64.decode(PRIVATE_KEY));
ResponseType rtWithDecryptedAssertion = AssertionUtil.decryptAssertion(resp, privateKey);
rtChoiceType = rtWithDecryptedAssertion.getAssertions().get(0);
assertNotNull(rtChoiceType.getAssertion());
assertNull(rtChoiceType.getEncryptedAssertion());
}
}
@Test @Test
public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception { public void testSaml20EncryptedAssertionsSignedTwoExtensionsReceivedWithRedirectBinding() throws Exception {
Element el; Element el;

View file

@ -0,0 +1,32 @@
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z"
Destination="http://sp.example.com/demo1/index.php?acs"
InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
<saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:EncryptedAssertion>
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"/>
<xenc:CipherData>
<xenc:CipherValue>
BpU+yCD3m1WdIGDfKnMOplsAzVZd/1cJZwu7l8/Rc/pMXxrYBR4m5WGxyKr+YwJoV3n1+CtYzrsklRN3Ck3Z7seRQf3bluWIvruVSS5k7HpTtZmyY/k0/Y0oTRr8z6YJ8MzL9veyM9EVcwIBFZypPN5ep+HDgz06QV0LAlFkGlQ=
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</dsig:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>
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
</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</saml:EncryptedAssertion>
</samlp:Response>