keycloak-aplcache

Details

diff --git a/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java b/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java
index 7e7daa5..f2fa845 100755
--- a/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java
+++ b/saml-core/src/main/java/org/keycloak/saml/common/parsers/AbstractParser.java
@@ -146,7 +146,7 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
             }
 
             private boolean valid(String str) {
-                return str != null && str.length() > 0;
+                return str != null && ! str.isEmpty();
             }
 
         });
diff --git a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SAMLParserUtil.java b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SAMLParserUtil.java
index b1ed278..a58cdd3 100755
--- a/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SAMLParserUtil.java
+++ b/saml-core/src/main/java/org/keycloak/saml/processing/core/parsers/util/SAMLParserUtil.java
@@ -308,6 +308,11 @@ public class SAMLParserUtil {
                     return parseNameIDType(xmlEventReader);
                 }
             } else if (xmlEvent instanceof EndElement) {
+                // consume the end element tag
+                EndElement end = StaxParserUtil.getNextEndElement(xmlEventReader);
+                String endElementTag = StaxParserUtil.getEndElementName(end);
+                if (! StaxParserUtil.matches(end, JBossSAMLConstants.ATTRIBUTE_VALUE.get()))
+                    throw logger.parserUnknownEndElement(endElementTag);
                 return "";
             }
 
diff --git a/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java b/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java
index 713a5bd..2f2157c 100644
--- a/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java
+++ b/saml-core/src/test/java/org/keycloak/saml/processing/core/parsers/saml/SAMLParserTest.java
@@ -200,4 +200,20 @@ public class SAMLParserTest {
             assertThat(parsedObject, instanceOf(EntityDescriptorType.class));
         }
     }
+
+    @Test
+    public void testEmptyAttributeValue() throws Exception {
+        try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4790-Empty-attribute-value.xml")) {
+            Object parsedObject = parser.parse(st);
+            assertThat(parsedObject, instanceOf(ResponseType.class));
+        }
+    }
+
+    @Test
+    public void testEmptyAttributeValueLast() throws Exception {
+        try (InputStream st = SAMLParserTest.class.getResourceAsStream("KEYCLOAK-4790-Empty-attribute-value-last.xml")) {
+            Object parsedObject = parser.parse(st);
+            assertThat(parsedObject, instanceOf(ResponseType.class));
+        }
+    }
 }
diff --git a/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value.xml b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value.xml
new file mode 100644
index 0000000..b4b03a1
--- /dev/null
+++ b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value.xml
@@ -0,0 +1,35 @@
+<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_d9e9e102-f048-48fb-a1a3-b5a82d9cd9c3" Version="2.0" 
+                IssueInstant="2017-04-24T12:50:14.645Z" Destination="https://y/auth/realms/administration/broker/saml/endpoint"
+                Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f2240010ds7f">
+    <saml:Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://x/</saml:Issuer>
+    <samlp:Status>
+        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+    </samlp:Status>
+    <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" ID="_0cceed2a-e409-4faa-a411-c647be748f2b" IssueInstant="2017-04-24T12:50:14.645Z" Version="2.0">
+        <Issuer>https://x/</Issuer>
+        <Subject>
+            <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">C=c,OU=ou</NameID>
+            <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+                <SubjectConfirmationData InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f224001057f" NotOnOrAfter="2017-04-24T12:55:14.645Z" Recipient="https://y/auth/realms/administration/broker/saml/endpoint"/>
+            </SubjectConfirmation>
+        </Subject>
+        <Conditions NotBefore="2017-04-24T12:45:14.380Z" NotOnOrAfter="2017-04-24T13:45:14.380Z">
+            <AudienceRestriction>
+                <Audience>https://x/auth/realms/administration</Audience>
+            </AudienceRestriction>
+        </Conditions>
+        <AttributeStatement>
+            <Attribute Name="urn:oid:0.9.2342.19200300.100.1.2" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
+                <AttributeValue/>
+            </Attribute>
+            <Attribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
+                <AttributeValue>aa</AttributeValue>
+            </Attribute>
+        </AttributeStatement>
+        <AuthnStatement AuthnInstant="2017-04-24T12:50:14.037Z" SessionIndex="_0cceed2a-e409-4faa-a411-c647be748f2b">
+            <AuthnContext>
+                <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:X509</AuthnContextClassRef>
+            </AuthnContext>
+        </AuthnStatement>
+    </Assertion>
+</samlp:Response>
diff --git a/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value-last.xml b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value-last.xml
new file mode 100644
index 0000000..efd56df
--- /dev/null
+++ b/saml-core/src/test/resources/org/keycloak/saml/processing/core/parsers/saml/KEYCLOAK-4790-Empty-attribute-value-last.xml
@@ -0,0 +1,35 @@
+<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_d9e9e102-f048-48fb-a1a3-b5a82d9cd9c3" Version="2.0" 
+                IssueInstant="2017-04-24T12:50:14.645Z" Destination="https://y/auth/realms/administration/broker/saml/endpoint"
+                Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f2240010ds7f">
+    <saml:Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://x/</saml:Issuer>
+    <samlp:Status>
+        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+    </samlp:Status>
+    <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" ID="_0cceed2a-e409-4faa-a411-c647be748f2b" IssueInstant="2017-04-24T12:50:14.645Z" Version="2.0">
+        <Issuer>https://x/</Issuer>
+        <Subject>
+            <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName">C=c,OU=ou</NameID>
+            <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+                <SubjectConfirmationData InResponseTo="ID_638a829f-7ad2-408e-b3e5-5f224001057f" NotOnOrAfter="2017-04-24T12:55:14.645Z" Recipient="https://y/auth/realms/administration/broker/saml/endpoint"/>
+            </SubjectConfirmation>
+        </Subject>
+        <Conditions NotBefore="2017-04-24T12:45:14.380Z" NotOnOrAfter="2017-04-24T13:45:14.380Z">
+            <AudienceRestriction>
+                <Audience>https://x/auth/realms/administration</Audience>
+            </AudienceRestriction>
+        </Conditions>
+        <AttributeStatement>
+            <Attribute Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
+                <AttributeValue>aa</AttributeValue>
+            </Attribute>
+            <Attribute Name="urn:oid:0.9.2342.19200300.100.1.2" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
+                <AttributeValue/>
+            </Attribute>
+        </AttributeStatement>
+        <AuthnStatement AuthnInstant="2017-04-24T12:50:14.037Z" SessionIndex="_0cceed2a-e409-4faa-a411-c647be748f2b">
+            <AuthnContext>
+                <AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:X509</AuthnContextClassRef>
+            </AuthnContext>
+        </AuthnStatement>
+    </Assertion>
+</samlp:Response>