From dd45e938564249a5e6897bd92dd29808d8990868 Mon Sep 17 00:00:00 2001 From: rudolf Date: Fri, 24 Oct 2003 08:34:56 +0000 Subject: MOA-ID version 1.1 (initial) git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@19 d688527b-c9ab-4aba-bd8d-4036d912da1d --- .../CreateXMLSignatureResponseValidator.java | 106 ++++++++++++++ .../id/auth/validator/IdentityLinkValidator.java | 156 +++++++++++++++++++++ .../moa/id/auth/validator/ValidateException.java | 35 +++++ .../VerifyXMLSignatureResponseValidator.java | 124 ++++++++++++++++ 4 files changed, 421 insertions(+) create mode 100644 id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java create mode 100644 id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java create mode 100644 id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java create mode 100644 id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java (limited to 'id.server/src/at/gv/egovernment/moa/id/auth/validator') diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java new file mode 100644 index 000000000..e596e79a4 --- /dev/null +++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/CreateXMLSignatureResponseValidator.java @@ -0,0 +1,106 @@ +package at.gv.egovernment.moa.id.auth.validator; + +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.data.SAMLAttribute; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * + * This class is used to validate an {@link CreateXMLSignatureResponse} + * returned by the security layer. + * This class implements the Singleton pattern. + * @author Stefan Knirsch + * @version $Id$ + */ +public class CreateXMLSignatureResponseValidator { + + /** Xpath prefix for reaching SecurityLayer 1.0 Namespaces */ + private static final String SAML = Constants.SAML_PREFIX + ":"; + /** Xpath prefix for reaching XML-DSIG Namespaces */ + private static final String DSIG = Constants.DSIG_PREFIX + ":"; + /** Xpath expression to the SAML:Assertion element */ + private static final String ROOT = SAML + "Assertion"; + /** Xpath expression to the SAML:NameIdentifier element */ + private static final String SAML_SUBJECT_NAME_IDENTIFIER_XPATH = + SAML + "AttributeStatement/" + SAML + "Subject/" + + SAML + "NameIdentifier"; + /** Xpath expression to the SAML:Attribute element */ + private static final String SAML_ATTRIBUTE_XPATH = + ROOT + "/" + SAML + "AttributeStatement/" + SAML + "Attribute"; + /** Xpath expression to the SAML:AttributeValue element */ + private static final String SAML_ATTRIBUTE_VALUE_XPATH = + SAML + "AttributeValue"; + + + /** Singleton instance. null, if none has been created. */ + private static CreateXMLSignatureResponseValidator instance; + + /** + * Constructor for a singleton CreateXMLSignatureResponseValidator. + * @return an instance of CreateXMLSignatureResponseValidator + * @throws ValidateException if no instance can be created + */ + public static synchronized CreateXMLSignatureResponseValidator getInstance() + throws ValidateException { + if (instance == null) { + instance = new CreateXMLSignatureResponseValidator(); + } + return instance; + } + + + /** + * The Method validate is used for validating an explicit {@link CreateXMLSignatureResponse} + * @param createXMLSignatureResponse + * @param gbTarget + * @param oaURL + * @throws ValidateException + */ + public void validate(CreateXMLSignatureResponse createXMLSignatureResponse, String gbTarget, String oaURL) + throws ValidateException { + + // A3.056: more then one /saml:Assertion/saml:AttributeStatement/saml:Subject/saml:NameIdentifier + + XPathUtils.selectNodeList(createXMLSignatureResponse.getSamlAssertion(),SAML_SUBJECT_NAME_IDENTIFIER_XPATH); + + SAMLAttribute[] samlattributes = createXMLSignatureResponse.getSamlAttributes(); + boolean foundOA = false; + boolean foundGB = false; + for (int i = 0; i < samlattributes.length; i++) + { + if (samlattributes[i].getName().equals("Geschäftsbereich")) + if (samlattributes[i].getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) + + { + foundGB = true; + if (!gbTarget.equals(samlattributes[i].getValue())) + { + throw new ValidateException("validator.13", null); + } + } + else throw new ValidateException("validator.12", null); + if (samlattributes[i].getName().equals("OA")) + if (samlattributes[i].getNamespace().equals("http://reference.e-government.gv.at/namespace/moa/20020822#")) + { + foundOA = true; + if (!oaURL.equals(samlattributes[i].getValue())) // CHECKS für die AttributeVALUES fehlen noch + { + throw new ValidateException("validator.16", new Object[] {":gefunden wurde '" + oaURL + "', erwartet wurde '" + samlattributes[i].getValue()}); + } + + } + else throw new ValidateException("validator.15", null); + } + if (!foundOA) throw new ValidateException("validator.14", null); + if (!foundGB) throw new ValidateException("validator.11", null); + + //Check if dsig:Signature exists + Element dsigSignature = (Element) XPathUtils.selectSingleNode(createXMLSignatureResponse.getSamlAssertion(),DSIG + "Signature"); + if (dsigSignature==null) throw new ValidateException("validator.05", null); + + + } +} diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java new file mode 100644 index 000000000..42e3e946f --- /dev/null +++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/IdentityLinkValidator.java @@ -0,0 +1,156 @@ +package at.gv.egovernment.moa.id.auth.validator; + +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import at.gv.egovernment.moa.id.auth.data.IdentityLink; +import at.gv.egovernment.moa.util.Constants; +import at.gv.egovernment.moa.util.XPathUtils; + +/** + * + * This class is used to validate an {@link IdentityLink} + * returned by the security layer + * + * @author Stefan Knirsch + * @version $Id$ + */ +public class IdentityLinkValidator implements Constants { + + // + // XPath namespace prefix shortcuts + // + /** Xpath prefix for reaching PersonData Namespaces */ + private static final String PDATA = PD_PREFIX + ":"; + /** Xpath prefix for reaching SAML Namespaces */ + private static final String SAML = SAML_PREFIX + ":"; + /** Xpath prefix for reaching XML-DSIG Namespaces */ + private static final String DSIG = DSIG_PREFIX + ":"; + /** Xpath prefix for reaching ECDSA Namespaces */ + private static final String ECDSA = ECDSA_PREFIX + ":"; + /** Xpath expression to the root element */ + private static final String ROOT = "/" + SAML + "Assertion/"; + /** Xpath expression to the SAML:SubjectConfirmationData element */ + private static final String SAML_SUBJECT_CONFIRMATION_DATA_XPATH = + ROOT + + SAML + + "AttributeStatement/" + + SAML + + "Subject/" + + SAML + + "SubjectConfirmation/" + + SAML + + "SubjectConfirmationData"; +/** Xpath expression to the PersonData:Person element */ + private static final String PERSON_XPATH = + SAML_SUBJECT_CONFIRMATION_DATA_XPATH + "/" + PDATA + "Person"; + /** Xpath expression to the SAML:Attribute element */ + private static final String ATTRIBUTE_XPATH = + ROOT + SAML + "AttributeStatement/" + SAML + "Attribute"; + /** Xpath expression to the SAML:AttributeName attribute */ + private static final String ATTRIBUTE_NAME_XPATH = + ROOT + SAML + "AttributeStatement/" + SAML + "Attribute/@AttributeName"; + /** Xpath expression to the SAML:AttributeNamespace attribute */ + private static final String ATTRIBUTE_NAMESPACE_XPATH = + ROOT + + SAML + + "AttributeStatement/" + + SAML + + "Attribute/@AttributeNamespace"; + /** Xpath expression to the SAML:AttributeValue element */ + private static final String ATTRIBUTE_VALUE_XPATH = + ROOT + + SAML + + "AttributeStatement/" + + SAML + + "Attribute/" + + SAML + + "AttributeValue"; + + /** Singleton instance. null, if none has been created. */ + private static IdentityLinkValidator instance; + + /** + * Constructor for a singleton IdentityLinkValidator. + * @return a new IdentityLinkValidator instance + * @throws ValidateException if no instance can be created + */ + public static synchronized IdentityLinkValidator getInstance() + throws ValidateException { + if (instance == null) { + instance = new IdentityLinkValidator(); + } + return instance; + } + + /** + * Method validate. Validates the {@link IdentityLink} + * @param identityLink The identityLink to validate + * @throws ValidateException on any validation error + */ + public void validate(IdentityLink identityLink) throws ValidateException { + + //Search the SAML:ASSERTION Object (A2.054) + if (identityLink.getSamlAssertion() == null) + throw new ValidateException("validator.00", null); + + // Check how many saml:Assertion/saml:AttributeStatement/ + // saml:Subject/ saml:SubjectConfirmation/ + // saml:SubjectConfirmationData/pr:Person of type + // PhysicalPersonType exist (A2.056) + NodeList nl = + XPathUtils.selectNodeList(identityLink.getSamlAssertion(), PERSON_XPATH); + // If we have just one Person-Element we don't need to check the attributes + int counterPhysicalPersonType = 0; + if (nl.getLength() > 1) + for (int i = 0; i < nl.getLength(); i++) { + String xsiType = + ((Element) nl.item(i)) + .getAttributeNodeNS( + "http://www.w3.org/2001/XMLSchema-instance", + "type") + .getNodeValue(); + // We have to check if xsiType contains "PhysicalPersonType" + // An equal-check will fail because of the Namespace-prefix of the attribute value + if (xsiType.indexOf("PhysicalPersonType") > -1) + counterPhysicalPersonType++; + } + if (counterPhysicalPersonType > 1) + throw new ValidateException("validator.01", null); + + //Check the SAML:ATTRIBUTES + nl = XPathUtils.selectNodeList(identityLink.getSamlAssertion(), ATTRIBUTE_XPATH); + for (int i = 0; i < nl.getLength(); i++) { + String attributeName = + XPathUtils.getAttributeValue( + (Element) nl.item(i), + "@AttributeName", + null); + String attributeNS = + XPathUtils.getAttributeValue( + (Element) nl.item(i), + "@AttributeNamespace", + null); + if (attributeName.equals("CitizenPublicKey")) { + if (attributeNS.equals("http://www.buergerkarte.at/namespaces/personenbindung/20020506#")) { + Element attributeValue = + (Element) XPathUtils.selectSingleNode((Element) nl.item(i),SAML + "AttributeValue/" + DSIG + "RSAKeyValue"); + if (attributeValue==null) + attributeValue = + (Element) XPathUtils.selectSingleNode((Element)nl.item(i), SAML + "AttributeValue/" + ECDSA + "ECDSAKeyValue"); + if (attributeValue == null) + throw new ValidateException("validator.02", null); + } + else + throw new ValidateException("validator.03", null); + } + else + throw new ValidateException("validator.04", null); + } + + //Check if dsig:Signature exists + Element dsigSignature = (Element) XPathUtils.selectSingleNode(identityLink.getSamlAssertion(),ROOT + DSIG + "Signature"); + if (dsigSignature==null) throw new ValidateException("validator.05", null); + } + +} diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java new file mode 100644 index 000000000..a6685fca8 --- /dev/null +++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/ValidateException.java @@ -0,0 +1,35 @@ +package at.gv.egovernment.moa.id.auth.validator; + +import at.gv.egovernment.moa.id.MOAIDException; + +/** + * Exception thrown while validating an incoming XML structure + * + * @author Paul Ivancsics + * @version $Id$ + */ +public class ValidateException extends MOAIDException { + + /** + * Constructor for ValidateException. + * @param messageId + * @param parameters + */ + public ValidateException(String messageId, Object[] parameters) { + super(messageId, parameters); + } + + /** + * Constructor for ValidateException. + * @param messageId + * @param parameters + * @param wrapped + */ + public ValidateException( + String messageId, + Object[] parameters, + Throwable wrapped) { + super(messageId, parameters, wrapped); + } + +} diff --git a/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java b/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java new file mode 100644 index 000000000..a238d28cb --- /dev/null +++ b/id.server/src/at/gv/egovernment/moa/id/auth/validator/VerifyXMLSignatureResponseValidator.java @@ -0,0 +1,124 @@ +package at.gv.egovernment.moa.id.auth.validator; + +import java.security.PublicKey; +import java.security.interfaces.RSAPublicKey; + +import iaik.asn1.structures.Name; +import iaik.utils.RFC2253NameParserException; +import iaik.x509.X509Certificate; + +import at.gv.egovernment.moa.id.auth.data.IdentityLink; +import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; + +/** + * This class is used to validate an {@link VerifyXMLSignatureResponse} + * returned by MOA-SPSS + * + * @author Stefan Knirsch + * @version $Id$ + */ +public class VerifyXMLSignatureResponseValidator { + + /** Identification string for checking identity link */ + public static final String CHECK_IDENTITY_LINK = "IdentityLink"; + /** Identification string for checking authentication block */ + public static final String CHECK_AUTH_BLOCK = "AuthBlock"; + + /** Singleton instance. null, if none has been created. */ + private static VerifyXMLSignatureResponseValidator instance; + + /** + * Constructor for a singleton VerifyXMLSignatureResponseValidator. + */ + public static synchronized VerifyXMLSignatureResponseValidator getInstance() + throws ValidateException { + if (instance == null) { + instance = new VerifyXMLSignatureResponseValidator(); + } + return instance; + } + + /** + * Validates a {@link VerifyXMLSignatureResponse} returned by MOA-SPSS. + * + * @param verifyXMLSignatureResponse the <VerifyXMLSignatureResponse> + * @param identityLinkSignersSubjectDNNames subject names configured + * @param whatToCheck is used to identify whether the identityLink or the Auth-Block is validated + * @throws ValidateException on any validation error + */ + public void validate( + VerifyXMLSignatureResponse verifyXMLSignatureResponse, + String[] identityLinkSignersSubjectDNNames, String whatToCheck) + throws ValidateException { + + if (verifyXMLSignatureResponse.getSignatureCheckCode() != 0) + throw new ValidateException("validator.06", null); + if (verifyXMLSignatureResponse.getCertificateCheckCode() != 0) + if (whatToCheck.equals(CHECK_IDENTITY_LINK)) + throw new ValidateException("validator.07", null); + else + throw new ValidateException("validator.19", null); + if (verifyXMLSignatureResponse.isXmlDSIGManigest()) + if (verifyXMLSignatureResponse.getXmlDSIGManifestCheckCode() != 0) + throw new ValidateException("validator.08", null); + //Check whether the returned X509 SubjectName is in the MOA-ID configuration or not + if (identityLinkSignersSubjectDNNames != null) { + String subjectDN = ""; + X509Certificate x509Cert = verifyXMLSignatureResponse.getX509certificate(); + try { + subjectDN = ((Name) x509Cert.getSubjectDN()).getRFC2253String(); + } + catch (RFC2253NameParserException e) { + throw new ValidateException("validator.17", null); + } + boolean found = false; + for (int i = 0; i < identityLinkSignersSubjectDNNames.length; i++) { + if (identityLinkSignersSubjectDNNames[i].equals(subjectDN)) + found = true; + } + if (!found) + throw new ValidateException( + "validator.18", + new Object[] { subjectDN }); + } + } + + /** + * Method validateCertificate. + * @param vsr is the VerifyXMLSignatureResponse + * @param idl + * @throws ValidateException + */ + public void validateCertificate( + VerifyXMLSignatureResponse verifyXMLSignatureResponse, + IdentityLink idl) + throws ValidateException { + + X509Certificate x509Response = verifyXMLSignatureResponse.getX509certificate(); + PublicKey[] pubKeysIdentityLink = (PublicKey[]) idl.getPublicKey(); + + RSAPublicKey pubKeyResponse = (RSAPublicKey) x509Response.getPublicKey(); + + boolean found = false; + for (int i = 0; i < pubKeysIdentityLink.length; i++) { + if (idl.getPublicKey()[i] + instanceof java.security.interfaces.RSAPublicKey) { + /* for (int j = 0; + j < idl.getPublicKey()[i].getClass().getInterfaces().length; + j++) { + if (idl.getPublicKey()[i].getClass().getInterfaces()[j].getName() + .equals("java.security.interfaces.RSAPublicKey")) {*/ + RSAPublicKey rsakey = (RSAPublicKey) pubKeysIdentityLink[i]; + if (rsakey.getModulus().equals(pubKeyResponse.getModulus()) + && rsakey.getPublicExponent().equals( + pubKeyResponse.getPublicExponent())) + found = true; + } + + } + + if (!found) + throw new ValidateException("validator.09", null); + } + +} -- cgit v1.2.3