/*******************************************************************************
* Copyright 2014 Federal Chancellery Austria
* MOA-ID has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
******************************************************************************/
/*
* Copyright 2003 Federal Chancellery Austria
* MOA-ID has been developed in a cooperation between BRZ, the Federal
* Chancellery Austria - ICT staff unit, and Graz University of Technology.
*
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
* http://www.osor.eu/eupl/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
* This product combines work with different licenses. See the "NOTICE" text
* file for details on the various modules and licenses.
* The "NOTICE" text file is part of the distribution. Any derivative works
* that you distribute must include a readable copy of the "NOTICE" text file.
*/
package at.gv.egiz.eaaf.core.impl.idp.auth.data;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.springframework.util.Base64Utils;
import org.w3c.dom.Element;
import org.w3c.dom.traversal.NodeIterator;
import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants;
import at.gv.egiz.eaaf.core.api.idp.auth.data.IIdentityLink;
import at.gv.egiz.eaaf.core.exceptions.EAAFParserException;
import at.gv.egiz.eaaf.core.impl.utils.DOMUtils;
import at.gv.egiz.eaaf.core.impl.utils.XPathUtils;
/**
* Parses MDS from an identity link <saml:Assertion>
*
* This IDL parser extract NO key information!
*/
public class SimpleIdentityLinkAssertionParser {
//
// XPath namespace prefix shortcuts
//
/** Xpath prefix for reaching PersonData Namespaces */
private static final String PDATA = XMLNamespaceConstants.PD_PREFIX + ":";
/** Xpath prefix for reaching SAML Namespaces */
private static final String SAML = XMLNamespaceConstants.SAML_PREFIX + ":";
/** Xpath prefix for reaching XML-DSIG Namespaces */
private static final String DSIG = XMLNamespaceConstants.DSIG_PREFIX + ":";
/** Xpath prefix for reaching ECDS Namespaces */
private static final String ECDSA = XMLNamespaceConstants.ECDSA_PREFIX + ":";
/** Xpath expression to the root element */
private static final String ROOT = "";
/** Xpath expression to the SAMLSubjectConfirmationData element */
private static final String SAML_SUBJECT_CONFIRMATION_DATA_XPATH =
ROOT
+ SAML
+ "AttributeStatement/"
+ SAML
+ "Subject/"
+ SAML
+ "SubjectConfirmation/"
+ SAML
+ "SubjectConfirmationData";
/** Xpath expression to the PersonData element */
private static final String PERSON_XPATH =
SAML_SUBJECT_CONFIRMATION_DATA_XPATH
+ "/"
+ PDATA
+ "Person";
/** Xpath expression to the PersonData GivenName element */
public static final String PERSON_GIVEN_NAME_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "Name/"
+ PDATA
+ "GivenName";
/** Xpath expression to the PersonData FamilyName element */
public static final String PERSON_FAMILY_NAME_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "Name/"
+ PDATA
+ "FamilyName";
/** Xpath expression to the PersonData DateOfBirth element */
public static final String PERSON_DATE_OF_BIRTH_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "DateOfBirth";
/** Xpath expression to the Identification element */
private static final String PERSON_IDENT_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "Identification";
/** Xpath expression to the Identification Value element */
public static final String PERSON_IDENT_VALUE_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "Identification/"
+ PDATA
+ "Value";
/** Xpath expression to the Identification Value element */
public static final String PERSON_IDENT_TYPE_XPATH =
PERSON_XPATH
+ "/"
+ PDATA
+ "Identification/"
+ PDATA
+ "Type";
/** Xpath expression to the RSAKeyValue element */
private static final String RSA_KEY_VALUE_XPATH =
ROOT
+ SAML
+ "AttributeStatement/"
+ SAML
+ "Attribute/"
+ SAML
+ "AttributeValue/"
+ DSIG
+ "RSAKeyValue";
/** Xpath expression to the ECKeyValue element */
private static final String ECDSA_KEY_VALUE_XPATH =
ROOT
+ SAML
+ "AttributeStatement/"
+ SAML
+ "Attribute/"
+ SAML
+ "AttributeValue/"
+ ECDSA
+ "ECDSAKeyValue";
/** Xpath expression to the RSA Modulus element */
private static final String RSA_KEY_MODULUS_XPATH = DSIG + "Modulus";
/** Xpath expression to the RSA Exponent element */
private static final String RSA_KEY_EXPONENT_XPATH = DSIG + "Exponent";
/** Xpath expression to the DSIG X509Certificate element */
private static final String DSIG_CERTIFICATES_XPATH =
ROOT
+ DSIG
+ "Signature/"
+ DSIG
+ "KeyInfo/"
+ DSIG
+ "X509Data/"
+ DSIG
+ "X509Certificate";
/** Xpath expression to the DSIG Transforms element */
private static final String DSIG_REFERENCE_TRANSFORMATION_XPATH =
ROOT
+ DSIG
+ "Signature/"
+ DSIG
+ "SignedInfo/"
+ DSIG
+ "Reference/"
+ DSIG
+ "Transforms";
/** The IssueInstant attribute of the SAML assertion */
private static final String ISSUE_INSTANT_ATTR = "IssueInstant";
public static final String ASSERTIONID = "AssertionID";
/**This is the root element of the XML-Document provided by the Security Layer Card*/
private Element assertionElem;
/**
* Constructor for IdentityLinkAssertionParser
.
* A DOM-representation of the incoming String will be created
* @param xmlAssertion <saml:Assertion>
as String
* @throws EAAFParserException on any parsing error
*/
public SimpleIdentityLinkAssertionParser(String xmlAssertion) throws EAAFParserException {
try {
InputStream s = new ByteArrayInputStream(xmlAssertion.getBytes("UTF-8"));
assertionElem = DOMUtils.parseXmlValidating(s);
}
catch (Throwable t) {
throw new EAAFParserException("parser.01", new Object[] { t.toString()}, t);
}
}
/**
* Sets the <@link assertionElem>.
* @param xmlAssertion the assertion element
* @throws EAAFParserException on any parsing error
*/
public SimpleIdentityLinkAssertionParser(Element xmlAssertion) throws EAAFParserException {
assertionElem = xmlAssertion;
}
/**
* Constructor for IdentityLinkAssertionParser
.
* A DOM-representation of the incoming Inputstream will be created
* @param xmlAssertion <saml:Assertion>
as InputStream
* @throws EAAFParserException on any parsing error
*/
public SimpleIdentityLinkAssertionParser(InputStream xmlAssertion) throws EAAFParserException {
try {
assertionElem = DOMUtils.parseXmlValidating(xmlAssertion);
}
catch (Throwable t) {
throw new EAAFParserException("parser.01", new Object[] { t.toString() }, t);
}
}
/**
* Parses the identity link from the <saml:Assertion>
* @return Identity link
* @throws EAAFParserException on any parsing error
*/
public IIdentityLink parseIdentityLink() throws EAAFParserException {
IIdentityLink identityLink;
try {
identityLink = new IdentityLink();
identityLink.setSamlAssertion(assertionElem);
identityLink.setIssueInstant(assertionElem.getAttribute(ISSUE_INSTANT_ATTR));
identityLink.setPrPerson((Element)
XPathUtils.selectSingleNode(assertionElem, PERSON_XPATH));
identityLink.setIdentificationValue(
XPathUtils.getElementValue(assertionElem, PERSON_IDENT_VALUE_XPATH, ""));
identityLink.setIdentificationType(
XPathUtils.getElementValue(assertionElem, PERSON_IDENT_TYPE_XPATH, ""));
String givenname = XPathUtils.getElementValue(assertionElem, PERSON_GIVEN_NAME_XPATH, "");
String familyname = XPathUtils.getElementValue(assertionElem, PERSON_FAMILY_NAME_XPATH, "");
// replace ' in name with '
// givenname = givenname.replaceAll("'", "'");
// familyname = familyname.replaceAll("'", "'");
identityLink.setGivenName(givenname);
identityLink.setFamilyName(familyname);
identityLink.setDateOfBirth(
XPathUtils.getElementValue(assertionElem, PERSON_DATE_OF_BIRTH_XPATH, ""));
NodeIterator dsigRefTransforms =
XPathUtils.selectNodeIterator(assertionElem, DSIG_REFERENCE_TRANSFORMATION_XPATH);
List transElems = new ArrayList();
Element transformsElem;
while ((transformsElem = (Element) dsigRefTransforms.nextNode()) != null) {
transElems.add(transformsElem);
}
Element[] result = new Element[transElems.size()];
transElems.toArray(result);
identityLink.setDsigReferenceTransforms(result);
//identityLink.setPublicKey(getPublicKeys());
}
catch (Throwable t) {
throw new EAAFParserException("parser.01", new Object[] { t.toString() }, t);
}
return identityLink;
}
/**
* Parses a string array of decoded base64 certificates from
* the <InfoboxReadResponse>
found in the dsig-signature
* @return String[] with raw-certificates from the dsig-signature keyinfo
* @throws Exception
*/
public String[] getCertificates() throws Exception {
List certs = new ArrayList();
NodeIterator rsaIter =
XPathUtils.selectNodeIterator(assertionElem, DSIG_CERTIFICATES_XPATH);
Element certElem;
while ((certElem = (Element) rsaIter.nextNode()) != null) {
String content = DOMUtils.getText(certElem);
certs.add(new String(Base64Utils.decodeFromString(content)));
}
String[] result = new String[certs.size()];
certs.toArray(result);
return result;
}
}