GNOME Bugzilla – Bug 322300
Schema Validation not correct
Last modified: 2005-12-16 10:45:29 UTC
Here is a fragment of schema used to validate a XML node. Considering the definition of <choice>, one of the element <BaseID>,<NameID> and <EncryptedID> must occur and occur only once. If none of them appear, it shouldn't pass the validation. But, the problem is that it do pass the validation using libxml2 v2.6.16. <element name="Subject" type="saml:SubjectType"/> <complexType name="SubjectType"> <choice> <sequence> <choice> <element ref="saml:BaseID"/> <element ref="saml:NameID"/> <element ref="saml:EncryptedID"/> </choice> <element ref="saml:SubjectConfirmation" minOccurs="0" maxOccurs="unbounded"/> </sequence> <element ref="saml:SubjectConfirmation" maxOccurs="unbounded"/> </choice> </complexType> ... </element>
2.6.16 is way too old, retry with 2.6.22 ! Then if you still have a problem provide the *full* schemas and instance reproducing the problem, not subsets. You won't get more feedback from us until both are reported back. Daniel
I have tried v2.6.22, it still can not work correctly. There're 3 issue: 1. The xmlSchemaParse() does not work properly if I don't download the schema and change the import "schemaLocation" to the local location. 2. xmlSchemaParse() can not handle <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>. After I comment all related sentences, it work correctly. 3. Considering the definition of <choice>, one of the element <BaseID>,<NameID> and <EncryptedID> must occur and occur only once. If none of them appear, it shouldn't pass the validation. But, the problem is that it do pass the validation Here is the schema: <?xml version="1.0" encoding="US-ASCII"?> <schema targetNamespace="urn:oasis:names:tc:SAML:2.0:assertion" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" elementFormDefault="unqualified" attributeFormDefault="unqualified" blockDefault="substitution" version="2.0"> <!-- <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core- 20020212/xmldsig-core-schema.xsd"/> <import namespace="http://www.w3.org/2001/04/xmlenc#" schemaLocation="http://www.w3.org/TR/2002/REC-xmlenc-core- 20021210/xenc-schema.xsd"/> --> <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" /> <import namespace="http://www.w3.org/2001/04/xmlenc#" schemaLocation="xenc- schema.xsd" /> <annotation> <documentation> Document identifier: saml-schema-assertion-2.0 Location: http://docs.oasis-open.org/security/saml/v2.0/ Revision history: V1.0 (November, 2002): Initial Standard Schema. V1.1 (September, 2003): Updates within the same V1.0 namespace. V2.0 (March, 2005): New assertion schema for SAML V2.0 namespace. </documentation> </annotation> <attributeGroup name="IDNameQualifiers"> <attribute name="NameQualifier" type="string" use="optional"/> <attribute name="SPNameQualifier" type="string" use="optional"/> </attributeGroup> <element name="BaseID" type="saml:BaseIDAbstractType"/> <complexType name="BaseIDAbstractType" abstract="true"> <attributeGroup ref="saml:IDNameQualifiers"/> </complexType> <element name="NameID" type="saml:NameIDType"/> <complexType name="NameIDType"> <simpleContent> <extension base="string"> <attributeGroup ref="saml:IDNameQualifiers"/> <attribute name="Format" type="anyURI" use="optional"/> <attribute name="SPProvidedID" type="string" use="optional"/> </extension> </simpleContent> </complexType> <complexType name="EncryptedElementType"> <sequence> <element ref="xenc:EncryptedData"/> <element ref="xenc:EncryptedKey" minOccurs="0" maxOccurs="unbounded"/> </sequence> </complexType> <element name="EncryptedID" type="saml:EncryptedElementType"/> <element name="Issuer" type="saml:NameIDType"/> <element name="AssertionIDRef" type="NCName"/> <element name="AssertionURIRef" type="anyURI"/> <element name="Assertion" type="saml:AssertionType"/> <complexType name="AssertionType"> <sequence> <element ref="saml:Issuer"/> <element ref="ds:Signature" minOccurs="0"/> <element ref="saml:Subject" minOccurs="0"/> <element ref="saml:Conditions" minOccurs="0"/> <element ref="saml:Advice" minOccurs="0"/> <choice minOccurs="0" maxOccurs="unbounded"> <element ref="saml:Statement"/> <element ref="saml:AuthnStatement"/> <element ref="saml:AuthzDecisionStatement"/> <element ref="saml:AttributeStatement"/> </choice> </sequence> <attribute name="Version" type="string" use="required"/> <attribute name="ID" type="ID" use="required"/> <attribute name="IssueInstant" type="dateTime" use="required"/> </complexType> <element name="Subject" type="saml:SubjectType"/> <complexType name="SubjectType"> <choice> <sequence> <choice> <element ref="saml:BaseID"/> <element ref="saml:NameID"/> <element ref="saml:EncryptedID"/> </choice> <element ref="saml:SubjectConfirmation" minOccurs="0" maxOccurs="unbounded"/> </sequence> <element ref="saml:SubjectConfirmation" maxOccurs="unbounded"/> </choice> </complexType> <element name="SubjectConfirmation" type="saml:SubjectConfirmationType"/> <complexType name="SubjectConfirmationType"> <sequence> <choice minOccurs="0"> <element ref="saml:BaseID"/> <element ref="saml:NameID"/> <element ref="saml:EncryptedID"/> </choice> <element ref="saml:SubjectConfirmationData" minOccurs="0"/> </sequence> <attribute name="Method" type="anyURI" use="required"/> </complexType> <element name="SubjectConfirmationData" type="saml:SubjectConfirmationDataType"/> <complexType name="SubjectConfirmationDataType" mixed="true"> <complexContent> <restriction base="anyType"> <sequence> <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </sequence> <attribute name="NotBefore" type="dateTime" use="optional"/> <attribute name="NotOnOrAfter" type="dateTime" use="optional"/> <attribute name="Recipient" type="anyURI" use="optional"/> <attribute name="InResponseTo" type="NCName" use="optional"/> <attribute name="Address" type="string" use="optional"/> <anyAttribute namespace="##other" processContents="lax"/> </restriction> </complexContent> </complexType> <complexType name="KeyInfoConfirmationDataType" mixed="false"> <complexContent> <restriction base="saml:SubjectConfirmationDataType"> <sequence> <element ref="ds:KeyInfo" maxOccurs="unbounded"/> </sequence> </restriction> </complexContent> </complexType> <element name="Conditions" type="saml:ConditionsType"/> <complexType name="ConditionsType"> <choice minOccurs="0" maxOccurs="unbounded"> <element ref="saml:Condition"/> <element ref="saml:AudienceRestriction"/> <element ref="saml:OneTimeUse"/> <element ref="saml:ProxyRestriction"/> </choice> <attribute name="NotBefore" type="dateTime" use="optional"/> <attribute name="NotOnOrAfter" type="dateTime" use="optional"/> </complexType> <element name="Condition" type="saml:ConditionAbstractType"/> <complexType name="ConditionAbstractType" abstract="true"/> <element name="AudienceRestriction" type="saml:AudienceRestrictionType"/> <complexType name="AudienceRestrictionType"> <complexContent> <extension base="saml:ConditionAbstractType"> <sequence> <element ref="saml:Audience" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> <element name="Audience" type="anyURI"/> <element name="OneTimeUse" type="saml:OneTimeUseType" /> <complexType name="OneTimeUseType"> <complexContent> <extension base="saml:ConditionAbstractType"/> </complexContent> </complexType> <element name="ProxyRestriction" type="saml:ProxyRestrictionType"/> <complexType name="ProxyRestrictionType"> <complexContent> <extension base="saml:ConditionAbstractType"> <sequence> <element ref="saml:Audience" minOccurs="0" maxOccurs="unbounded"/> </sequence> <attribute name="Count" type="nonNegativeInteger" use="optional"/> </extension> </complexContent> </complexType> <element name="Advice" type="saml:AdviceType"/> <complexType name="AdviceType"> <choice minOccurs="0" maxOccurs="unbounded"> <element ref="saml:AssertionIDRef"/> <element ref="saml:AssertionURIRef"/> <element ref="saml:Assertion"/> <element ref="saml:EncryptedAssertion"/> <!-- <any namespace="##other" processContents="lax"/> --> </choice> </complexType> <element name="EncryptedAssertion" type="saml:EncryptedElementType"/> <element name="Statement" type="saml:StatementAbstractType"/> <complexType name="StatementAbstractType" abstract="true"/> <element name="AuthnStatement" type="saml:AuthnStatementType"/> <complexType name="AuthnStatementType"> <complexContent> <extension base="saml:StatementAbstractType"> <sequence> <element ref="saml:SubjectLocality" minOccurs="0"/> <element ref="saml:AuthnContext"/> </sequence> <attribute name="AuthnInstant" type="dateTime" use="required"/> <attribute name="SessionIndex" type="string" use="optional"/> <attribute name="SessionNotOnOrAfter" type="dateTime" use="optional"/> </extension> </complexContent> </complexType> <element name="SubjectLocality" type="saml:SubjectLocalityType"/> <complexType name="SubjectLocalityType"> <attribute name="Address" type="string" use="optional"/> <attribute name="DNSName" type="string" use="optional"/> </complexType> <element name="AuthnContext" type="saml:AuthnContextType"/> <complexType name="AuthnContextType"> <sequence> <choice> <sequence> <element ref="saml:AuthnContextClassRef"/> <choice minOccurs="0"> <element ref="saml:AuthnContextDecl"/> <element ref="saml:AuthnContextDeclRef"/> </choice> </sequence> <choice> <element ref="saml:AuthnContextDecl"/> <element ref="saml:AuthnContextDeclRef"/> </choice> </choice> <element ref="saml:AuthenticatingAuthority" minOccurs="0" maxOccurs="unbounded"/> </sequence> </complexType> <element name="AuthnContextClassRef" type="anyURI"/> <element name="AuthnContextDeclRef" type="anyURI"/> <element name="AuthnContextDecl" type="anyType"/> <element name="AuthenticatingAuthority" type="anyURI"/> <element name="AuthzDecisionStatement" type="saml:AuthzDecisionStatementType"/> <complexType name="AuthzDecisionStatementType"> <complexContent> <extension base="saml:StatementAbstractType"> <sequence> <element ref="saml:Action" maxOccurs="unbounded"/> <element ref="saml:Evidence" minOccurs="0"/> </sequence> <attribute name="Resource" type="anyURI" use="required"/> <attribute name="Decision" type="saml:DecisionType" use="required"/> </extension> </complexContent> </complexType> <simpleType name="DecisionType"> <restriction base="string"> <enumeration value="Permit"/> <enumeration value="Deny"/> <enumeration value="Indeterminate"/> </restriction> </simpleType> <element name="Action" type="saml:ActionType"/> <complexType name="ActionType"> <simpleContent> <extension base="string"> <attribute name="Namespace" type="anyURI" use="required"/> </extension> </simpleContent> </complexType> <element name="Evidence" type="saml:EvidenceType"/> <complexType name="EvidenceType"> <choice maxOccurs="unbounded"> <element ref="saml:AssertionIDRef"/> <element ref="saml:AssertionURIRef"/> <element ref="saml:Assertion"/> <element ref="saml:EncryptedAssertion"/> </choice> </complexType> <element name="AttributeStatement" type="saml:AttributeStatementType"/> <complexType name="AttributeStatementType"> <complexContent> <extension base="saml:StatementAbstractType"> <choice maxOccurs="unbounded"> <element ref="saml:Attribute"/> <element ref="saml:EncryptedAttribute"/> </choice> </extension> </complexContent> </complexType> <element name="Attribute" type="saml:AttributeType"/> <complexType name="AttributeType"> <sequence> <element ref="saml:AttributeValue" minOccurs="0" maxOccurs="unbounded"/> </sequence> <attribute name="Name" type="string" use="required"/> <attribute name="NameFormat" type="anyURI" use="optional"/> <attribute name="FriendlyName" type="string" use="optional"/> <anyAttribute namespace="##other" processContents="lax"/> </complexType> <element name="AttributeValue" type="anyType" nillable="true"/> <element name="EncryptedAttribute" type="saml:EncryptedElementType"/> </schema> and here is the instance: <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Version="2.0" ID="_a75adf55-01d7- 40cc-929f-dbd8372ebdfc" IssueInstant="2005-10-27T12:00:00Z"> <saml:Issuer>www.idp.com</saml:Issuer> <saml:Subject> <!-- Missing NameID here --> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:3.0:cm:holder-of- key"> <saml:SubjectConfirmationData xsi:type="saml:KeyInfoConfirmationDataType"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIIDTzCCArigAwIBAgIBAjANBgkqhkiG9w0BAQQFADBuMQswCQYDVQQGEwJ DTjEL MAkGA1UECBMCU0gxCzAJBgNVBAcTAlNIMQ0wCwYDVQQKEwRpY2ZzMQwwCgYDVQQL EwNzZXMxCzAJBgNVBAMTAmNhMRswGQYJKoZIhvcNAQkBFgxjYS5pbnRlbC5jb20w HhcNMDUwODI1MDYxMTAxWhcNMTUwODIzMDYxMTAxWjBsMQswCQYDVQQGEwJDTjEL MAkGA1UECBMCU0gxDTALBgNVBAoTBGljZnMxDDAKBgNVBAsTA3NlczESMBAGA1UE AxMJbG9jYWxob3N0MR8wHQYJKoZIhvcNAQkBFhBjbGllbnQuaW50ZWwuY29tMIGf MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCToeOI4lYhi1o3YcB30J/NXYkObcxf /PKVDC01nnn1N/ c5MAM/4ReUYTvef52szhXZNCiWYMuu/Mm+edZ9qo77FQkDHGXC B+FfSLnwnhn6EQWxy5dLJR+KaxdJ6/lrzZJ9Hu4za2vwnZStXgvi0/g8BFHFhn2O BAZdgTuY1fC6HwIDAQABo4H+MIH7MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8W HU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTFTJVmlgr9 U/sgO4308W4h9iMD+TCBoAYDVR0jBIGYMIGVgBSdG0ggWC6AUPZ4fYttVRQ6eibn ZaFypHAwbjELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlNIMQswCQYDVQQHEwJTSDEN MAsGA1UEChMEaWNmczEMMAoGA1UECxMDc2VzMQswCQYDVQQDEwJjYTEbMBkGCSqG SIb3DQEJARYMY2EuaW50ZWwuY29tggkA5Vtq77wl5kkwDQYJKoZIhvcNAQEEBQAD gYEAczygyNh4EP/Gx73VZElWKOC/zSHkU4Uf/klyHH1rnr3Y0BV+hsP7D+cE20n+ 676G2FIKYrK8UP3C7A0M0yv4HEjOUBBNThlWDc7P0Y2dYQucNMfoGVYGg6s1WR/0 7DB8SNc6hQ/KOShzLMyq/py7ZBFMbZ0tAQE/nQuy5RhhLO8=</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </saml:SubjectConfirmationData> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2005-01-31T12:00:00Z" NotOnOrAfter="2005-01- 31T12:00:00Z"> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2005-01-31T12:00:00Z" SessionIndex="67775277772"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProte ctedTransport</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion>
Sorry that I make a mistake. xmlSchemaParse() can handle <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>. Please omit the 2nd question. But the 1st and 3rd issue still exist.
Can you reduce the problems ? Please do your part to show what is wrong, not why but what ! You reference external schemas which are not included in the bug report. The instance are cut and pasted instead of being added as attachment and are broken. And you raise an issue about a <choice> while the instance is like a thousand lines long. You must do your part to expose the bug, not just drop the data there and wait for a free analysis and bug fix ! To be as clear as possible, debugging this is gonna be done on our free time. If you make it hard, you will wait longer for a fix, if you make it near impossible to debug you will never get a fix. It is in your interest to reduce the problem ! So make a reduced exampled based on your initial fragment showing the problem with a reduced schemas and you will certainly get a fix quickly. Daniel
regarding 3) The following test-scenario includes an xs:choice as you describe it and is rejected correctly as invalid by xmllint. Thus, as Daniel wrote, we need a reduced scenario to see where a bug might occur. >xmllint --noout --schema bug322300.xsd bug322300.xml Element '{urn:test:foo}foo': Missing child element(s). Expected is one of ( {urn :test:foo}BaseID, {urn:test:foo}NameID, {urn:test:foo}EncryptedID ). bug322300.xml fails to validate bug322300.xml ------------- <?xml version="1.0"?> <foo xmlns="urn:test:foo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:test:foo bug322300.xsd"> </foo> bug322300.xsd ------------- <schema targetNamespace="urn:test:foo" xmlns:foo="urn:test:foo" xmlns="http://www.w3.org/2001/XMLSchema"> <element name="BaseID"/> <element name="NameID"/> <element name="EncryptedID"/> <element name="SubjectConfirmationData"/> <complexType name="Foo"> <sequence> <choice> <element ref="foo:BaseID"/> <element ref="foo:NameID"/> <element ref="foo:EncryptedID"/> </choice> <element ref="foo:SubjectConfirmationData" minOccurs="0"/> </sequence> </complexType> <element name="foo" type="foo:Foo"/> </schema>
Regarding 1) Is the imported schema file (e.g. "xmldsig-core-schema.xsd") located in the same folder as the importing schema file? If no than this might be the source of error, since the file names should be expanded using the file URI of the importing schema as the base. However, please produce a reduced test for this scenario as well; e.g. two schemas with only one element declaration each and an import.
Regarding 3) I think I found the reason for the behaviour of the validator you experience here. Actually I take the blame on me that I didn't see it at first glance. You have the following in your instance: <saml:Subject> <!-- Missing NameID here --> <saml:SubjectConfirmation Method="..."> ... If you look closely at the model defining this, you'll see that the <choice> you refer to is itself wrapped inside an other <choice>; we can choose between the <sequence> and <SubjectConfirmation>. So that's why the validator correctly does not fire an error here. <choice> <<< The outer choice. <sequence> <choice> <element ref="saml:BaseID"/> <element ref="saml:NameID"/> <element ref="saml:EncryptedID"/> </choice> <element ref="saml:SubjectConfirmation" minOccurs="0" maxOccurs="unbounded"/> </sequence> <element ref="saml:SubjectConfirmation" maxOccurs="unbounded"/> </choice> Thus 3) is not a bug.
Thanks a lot for your response! Really feel sorry about the inconvenience bring to you. For the 1st issue, I mean if I save the schema to be imported to my local disk and revise the following segment <!--================This is what originally defined in the schema======--> <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core- 20020212/xmldsig-core-schema.xsd"/> <import namespace="http://www.w3.org/2001/04/xmlenc#" schemaLocation="http://www.w3.org/TR/2002/REC-xmlenc-core- 20021210/xenc-schema.xsd"/> <!--================This is what originally defined in the schema======--> to the following segment <!--================This is what I revised=============================--> <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" /> <import namespace="http://www.w3.org/2001/04/xmlenc#" schemaLocation="xenc- schema.xsd" /> <!--================This is what I revised=============================--> it works correctly. But if we do not revise it, it can not parse the schema directly. It is related to the proxy issue. Now I add "xmlNanoHTTPScanProxy ("http://proxy01....");", it works well. Thanks again.
OK. Objections to close this bug as a notabug?