/* * Copyright 2003 Federal Chancellery Austria * MOA-SPSS 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.egovernment.moa.spss.api.xmlbind; import java.io.IOException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.Calendar; import java.util.TimeZone; import javax.xml.bind.DatatypeConverter; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import iaik.utils.RFC2253NameParser; import iaik.utils.RFC2253NameParserException; import at.gv.egovernment.moa.spss.MOAApplicationException; import at.gv.egovernment.moa.spss.MOASystemException; import at.gv.egovernment.moa.spss.api.common.ExtendedCertificateCheckResult; import at.gv.egovernment.moa.spss.api.common.TslInfos; import at.gv.egovernment.moaspss.util.Base64Utils; import at.gv.egovernment.moaspss.util.Constants; import at.gv.egovernment.moaspss.util.MiscUtil; /** * Utility methods used by the verious ResponseBuilder classes. * * @author Patrick Peck * @version $Id$ */ public class ResponseBuilderUtils { // // shortcuts to various XML namespace constants // private static final String MOA_NS_URI = Constants.MOA_NS_URI; private static final String DSIG = Constants.DSIG_PREFIX + ":"; private static final String DSIG_NS_URI = Constants.DSIG_NS_URI; private static final String XMLNS_NS_URI = Constants.XMLNS_NS_URI; /** * Add an DOM element with a specific name as child to a root element * * @param elementName Name of the DOM element * @param response Full document with namespace information * @param rootElement Root element * @return new child DOM element */ public static Element addChildElement(String elementName, Document response, Element rootElement) { Element childElement = response.createElementNS(MOA_NS_URI, elementName); rootElement.appendChild(childElement); return childElement; } /** * Create a response element with all the namespaces set. * * @param responseName The name of the response root element. * @return A DOM document containing the response root element and predefined * MOA, DSIG and XML namespace declarations. * @throws MOASystemException An error building the response document. */ public static Document createResponse(String responseName) throws MOASystemException { try { DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); DOMImplementation impl = docBuilder.getDOMImplementation(); Document response; Element root; String attrValue; response = impl.createDocument(MOA_NS_URI, responseName, null); root = response.getDocumentElement(); // add namespace prefix declarations root.setAttributeNS(XMLNS_NS_URI, "xmlns", MOA_NS_URI); attrValue = "xmlns:" + Constants.DSIG_PREFIX; root.setAttributeNS(XMLNS_NS_URI, attrValue, DSIG_NS_URI); return response; } catch (ParserConfigurationException e) { throw new MOASystemException("2200", null, e); } } /** * Add a SignerInfo element to the response. * * @param response The response document, in order to create new elements in * it. * @param root The root element into which the SignerInfo element * will be inserted. * @param cert The signer certificate to add. * @param isQualified Indicates, whether cert is a qualified * certificate. * @param isPublicAuthority Indicates, whether cert is * certificate owned by a public authority. * @param publicAuthorityID Information about the public authority owning * cert. Must not be null, if * isPublicAuthority ! = null. * @throws MOAApplicationException An error occurred reading data from the * certificate. */ public static void addSignerInfo( Document response, Element root, X509Certificate cert, boolean isQualified, String qcSource, boolean isPublicAuthority, String publicAuthorityID, boolean isSSCD, String sscdSource, String issuerCountryCode, TslInfos tslInfos) throws MOAApplicationException { Element signerInfoElem = response.createElementNS(MOA_NS_URI, "SignerInfo"); Element x509DataElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509Data"); Element x509IssuerSerialElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerSerial"); Element x509IssuerElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509IssuerName"); String issuer = cert.getIssuerDN().getName(); Element x509SerialNumberElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509SerialNumber"); String serialNumber = cert.getSerialNumber().toString(); Element x509SubjectNameElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509SubjectName"); Element x509CertificateElem = response.createElementNS(DSIG_NS_URI, DSIG + "X509Certificate"); Element qualifiedCertificateElem = isQualified ? response.createElementNS(MOA_NS_URI, "QualifiedCertificate") : null; Element sscdElem = isSSCD ? response.createElementNS(MOA_NS_URI, "SecureSignatureCreationDevice") : null; Element issuerCountryCodeElem = null; if (issuerCountryCode != null) { issuerCountryCodeElem = response.createElementNS(MOA_NS_URI, "IssuerCountryCode"); issuerCountryCodeElem.setTextContent(issuerCountryCode); } //add TSL infos Element tslInfoElement = null; if (tslInfos != null) { tslInfoElement = response.createElementNS(MOA_NS_URI, "TSLInformation"); //append TSL issuer country-code if (MiscUtil.isNotEmpty(tslInfos.getTslIssuerCountry())); { Element tslIssuerCountryCodeElem = response.createElementNS(MOA_NS_URI, "TSLIssuerCountryCode"); tslIssuerCountryCodeElem.setTextContent(tslInfos.getTslIssuerCountry()); tslInfoElement.appendChild(tslIssuerCountryCodeElem); } //append Service-Type Status if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeStatus())); { Element tslServiceInfo = response.createElementNS(MOA_NS_URI, "ServiceTypeStatus"); tslServiceInfo.setTextContent(tslInfos.getServiceTypeStatus()); tslInfoElement.appendChild(tslServiceInfo); } //append Service-Type Identifier if (MiscUtil.isNotEmpty(tslInfos.getServiceTypeIdentifier())); { Element tslServiceInfo = response.createElementNS(MOA_NS_URI, "ServiceTypeIdentifier"); tslServiceInfo.setTextContent(tslInfos.getServiceTypeIdentifier()); tslInfoElement.appendChild(tslServiceInfo); } //append qualifiers if (tslInfos.getQualifiers() != null && tslInfos.getQualifiers().size() > 0) { Element tslQualifiers = response.createElementNS(MOA_NS_URI, "Qualifiers"); for (String el : tslInfos.getQualifiers()) { Element tslQualifier = response.createElementNS(MOA_NS_URI, "Qualifier"); tslQualifier.setTextContent(el); tslQualifiers.appendChild(tslQualifier); } tslInfoElement.appendChild(tslQualifiers); } //append additional service information if (tslInfos.getAdditionalServiceInformation() != null && tslInfos.getAdditionalServiceInformation().size() > 0) { Element tslAdditionalServiceInformations = response.createElementNS(MOA_NS_URI, "AdditionalServiceInformations"); for (String el : tslInfos.getAdditionalServiceInformation()) { Element tslAdditionalServiceInformation = response.createElementNS(MOA_NS_URI, "AdditionalServiceInformation"); tslAdditionalServiceInformation.setTextContent(el); tslAdditionalServiceInformations.appendChild(tslAdditionalServiceInformation); } tslInfoElement.appendChild(tslAdditionalServiceInformations); } } Element publicAuthorityElem = isPublicAuthority ? response.createElementNS(MOA_NS_URI, "PublicAuthority") : null; Element codeElem = publicAuthorityID != null ? response.createElementNS(MOA_NS_URI, "Code") : null; // fill in text x509IssuerElem.appendChild(response.createTextNode(issuer)); x509SerialNumberElem.appendChild(response.createTextNode(serialNumber)); try { RFC2253NameParser parser = new RFC2253NameParser(cert.getSubjectDN().getName()); String subjectRfc2253 = parser.parse().getRFC2253String(); x509SubjectNameElem.appendChild(response.createTextNode(subjectRfc2253)); } catch (RFC2253NameParserException e) { x509SubjectNameElem.appendChild( response.createTextNode(cert.getSubjectDN().getName())); } try { x509CertificateElem.appendChild( response.createTextNode(Base64Utils.encode(cert.getEncoded()))); } catch (CertificateEncodingException e) { throw new MOAApplicationException("2245", null, e); } catch (IOException e) { throw new MOAApplicationException("2245", null, e); } // build structure x509DataElem.appendChild(x509SubjectNameElem); x509IssuerSerialElem.appendChild(x509IssuerElem); x509IssuerSerialElem.appendChild(x509SerialNumberElem); x509DataElem.appendChild(x509IssuerSerialElem); x509DataElem.appendChild(x509CertificateElem); if (isQualified) { if (qcSource.compareToIgnoreCase("TSL") == 0) qualifiedCertificateElem.setAttributeNS(MOA_NS_URI, "Source", qcSource); x509DataElem.appendChild(qualifiedCertificateElem); } if (isPublicAuthority) { x509DataElem.appendChild(publicAuthorityElem); if (publicAuthorityID != null) { codeElem.appendChild(response.createTextNode(publicAuthorityID)); publicAuthorityElem.appendChild(codeElem); } } if (isSSCD) { sscdElem.setAttributeNS(MOA_NS_URI, "Source", sscdSource); x509DataElem.appendChild(sscdElem); } if (issuerCountryCodeElem != null) x509DataElem.appendChild(issuerCountryCodeElem); //add TSL infos to X509Date if TSL infos exists if (tslInfoElement != null) x509DataElem.appendChild(tslInfoElement); signerInfoElem.appendChild(x509DataElem); root.appendChild(signerInfoElem); } /** * Add an element containing Code and Info * subelements. * * @param response The response document, in order to create new elements in * it. * @param root The root element into which to insert the newly created * element. * @param elementName The name of the newly created element. * @param code The content of the Code subelement. * @param info The content of the Info subelement. */ public static void addCodeInfoElement( Document response, Element root, String elementName, int code, NodeList info) { Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName); Element codeElem = response.createElementNS(MOA_NS_URI, "Code"); Element infoElem; int i; codeElem.appendChild(response.createTextNode(Integer.toString(code))); codeInfoElem.appendChild(codeElem); if (info != null) { infoElem = response.createElementNS(MOA_NS_URI, "Info"); for (i = 0; i < info.getLength(); i++) { infoElem.appendChild(info.item(i).cloneNode(true)); } codeInfoElem.appendChild(infoElem); } root.appendChild(codeInfoElem); } /** * Add an element containing Code and Info * subelements. * * @param response The response document, in order to create new elements in * it. * @param root The root element into which to insert the newly created * element. * @param elementName The name of the newly created element. * @param code The content of the Code subelement. * @param info The content of the Info subelement. */ public static void addCodeInfoElement( Document response, Element root, String elementName, int code, String info) { Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName); Element codeElem = response.createElementNS(MOA_NS_URI, "Code"); Element infoElem; int i; codeElem.appendChild(response.createTextNode(Integer.toString(code))); codeInfoElem.appendChild(codeElem); if (info != null) { infoElem = response.createElementNS(MOA_NS_URI, "Info"); infoElem.appendChild(response.createTextNode(info)); codeInfoElem.appendChild(infoElem); } root.appendChild(codeInfoElem); } public static void addSigningTime(Document response, Element root, Date signingTime) { if(signingTime != null) { Element extElem = response.createElementNS(MOA_NS_URI, "SigningTime"); TimeZone tz = TimeZone.getTimeZone("UTC"); Calendar calendar = new GregorianCalendar(); calendar.setTimeZone(tz); calendar.setTime(signingTime); String date = DatatypeConverter.printDateTime(calendar); extElem.appendChild(response.createTextNode(date)); root.appendChild(extElem); } } public static void addExtendendResult(Document response, Element root, ExtendedCertificateCheckResult result) { Element extElem = response.createElementNS(MOA_NS_URI, "ExtendedCertificateCheck"); Element extMajorElem = response.createElementNS(MOA_NS_URI, "Major"); Element codeMajorCodeElem = response.createElementNS(MOA_NS_URI, "Code"); Element codeMajorNameElem = response.createElementNS(MOA_NS_URI, "Name"); codeMajorCodeElem.appendChild(response.createTextNode(Integer.toString( result.getMajorCode()))); codeMajorNameElem.appendChild(response.createTextNode(result.getMajorInfo())); extMajorElem.appendChild(codeMajorCodeElem); extMajorElem.appendChild(codeMajorNameElem); extElem.appendChild(extMajorElem); if(result.getMinorCode() >= 0) { Element extMinorElem = response.createElementNS(MOA_NS_URI, "Minor"); Element codeMinorCodeElem = response.createElementNS(MOA_NS_URI, "Code"); Element codeMinorNameElem = response.createElementNS(MOA_NS_URI, "Name"); codeMinorCodeElem.appendChild(response.createTextNode(Integer.toString( result.getMinorCode()))); codeMinorNameElem.appendChild(response.createTextNode(result.getMinorInfo())); extMinorElem.appendChild(codeMinorCodeElem); extMinorElem.appendChild(codeMinorNameElem); extElem.appendChild(extMinorElem); } root.appendChild(extElem); } /** * Add an element containing Code and Info * subelements. * * @param response The response document, in order to create new elements in * it. * @param root The root element into which to insert the newly created * element. * @param elementName The name of the newly created element. * @param code The content of the Code subelement. * @param info The content of the Info subelement. */ public static void addFormCheckElement( Document response, Element root, String elementName, int code, String name) { Element codeInfoElem = response.createElementNS(MOA_NS_URI, elementName); Element codeElem = response.createElementNS(MOA_NS_URI, "Code"); Element infoElem; codeElem.appendChild(response.createTextNode(Integer.toString(code))); codeInfoElem.appendChild(codeElem); infoElem = response.createElementNS(MOA_NS_URI, "Name"); infoElem.appendChild(response.createTextNode(name)); codeInfoElem.appendChild(infoElem); root.appendChild(codeInfoElem); } }