/* * Created on 20.11.2003 * * (c) Stabsstelle IKT-Strategie des Bundes */ package at.gv.egovernment.moa.spss.slinterface.transformers; import java.io.InputStream; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.StringTokenizer; import javax.servlet.ServletException; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import at.gv.egovernment.moa.spss.slinterface.Constants; import at.gv.egovernment.moa.spss.slinterface.DOMUtils; import at.gv.egovernment.moa.spss.slinterface.XPathUtils; /** * @author Gregor Karlinger (mailto:gregor.karlinger@siemens.com) */ public class SL2MOA { private static Logger logger_ = Logger.getLogger(Constants.LH_TRANSFORMERS_); /** * Transforms an SL VerifyXMLSignatureRequest into a MOA VerifyXMLSignatureRequest * and makes the following additions to the resulting VerifyXMLSignatureRequest: * * * @param slVerifyXMLSignatureRequest The SL VerifyXMLSignatureRequest to be transformed. * * @return the specified request document, transformed into a MOA VerifyXMLSignatureRequest. Please note * that slVerifyXMLSignatureRequest is modified into the moa request. * * @pre slVerifyXMLSignatureRequest is a valid instance of the SL Schema (version 1.2 or 1.1). * * @throws ServletException if transforming the request fails for any reason. */ public static Document toMoaVerifyXMLSignatureRequest(Document slVerifyXMLSignatureRequest, String trustProfileID) throws ServletException { // Namespace to namespace prefix mapping HashMap prefixMap = new HashMap(4); prefixMap.put(Constants.NSURI_SL_10_, Constants.NSPRE_SL_10_); prefixMap.put(Constants.NSURI_SL_11_, Constants.NSPRE_SL_11_); prefixMap.put(Constants.NSURI_SL_12_, Constants.NSPRE_SL_12_); prefixMap.put(Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_); // Namespaces to be changed HashMap nsTransforms = new HashMap(); nsTransforms.put(Constants.NSURI_SL_10_, Constants.NSURI_MOA_12_); nsTransforms.put(Constants.NSURI_SL_11_, Constants.NSURI_MOA_12_); nsTransforms.put(Constants.NSURI_SL_12_, Constants.NSURI_MOA_12_); // Names to be changed HashMap nameTransforms = new HashMap(); nameTransforms.put( new QName(Constants.NSURI_SL_11_, "SignatureInfo"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureInfo")); nameTransforms.put( new QName(Constants.NSURI_SL_12_, "SignatureInfo"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureInfo")); nameTransforms.put( new QName(Constants.NSURI_SL_11_, "SignatureEnvironment"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureEnvironment")); nameTransforms.put( new QName(Constants.NSURI_SL_12_, "SignatureEnvironment"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureEnvironment")); nameTransforms.put( new QName(Constants.NSURI_SL_11_, "SignatureLocation"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureLocation")); nameTransforms.put( new QName(Constants.NSURI_SL_12_, "SignatureLocation"), new QName(Constants.NSURI_MOA_12_,"VerifySignatureLocation")); nameTransforms.put( new QName(Constants.NSURI_SL_11_, "Supplement"), new QName(Constants.NSURI_MOA_12_,"SupplementProfile")); nameTransforms.put( new QName(Constants.NSURI_SL_12_, "Supplement"), new QName(Constants.NSURI_MOA_12_,"SupplementProfile")); Element verifyRequestElem = slVerifyXMLSignatureRequest.getDocumentElement(); verifyRequestElem.setAttributeNS(Constants.NSURI_NAMESPACES_, "xmlns:" + Constants.NSPRE_MOA_12_, Constants.NSURI_MOA_12_); // Convert SL request into MOA request verifyRequestElem = Utils.transformDeep(verifyRequestElem, prefixMap, nsTransforms, nameTransforms); // Add DateTime element to MOA VerifyXMLSignature request, if // - no one exists and // - no etsi:SigningTime element exists in the xml signature of the MOA VerifyXMLSinatureRequest if (!dateTimeExists(verifyRequestElem) && !signingTimeExists(verifyRequestElem)) { // Extract creation date meta information from E-Recht XML document for use in MOA VerifyXMLSignature request String dateTimeStr = extractXMLDocCreationTime(verifyRequestElem); if (dateTimeStr != null) { // Creation date meta information could be extracted successfully from E-Recht XML document Element dateTimeElem = slVerifyXMLSignatureRequest.createElementNS( Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_ + ":DateTime"); dateTimeElem.appendChild(slVerifyXMLSignatureRequest.createTextNode(dateTimeStr)); Element verifySignatureInfoElem = DOMUtils.getChildElem(verifyRequestElem, Constants.NSURI_MOA_12_, "VerifySignatureInfo"); verifyRequestElem.insertBefore(dateTimeElem, verifySignatureInfoElem); } else { logger_.warn("Could not extract creation date meta information from E-Recht XML document."); } } // Add ReturnHashInputData element Element returnHashInputDataElem = slVerifyXMLSignatureRequest.createElementNS( Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_ + ":ReturnHashInputData"); verifyRequestElem.appendChild(returnHashInputDataElem); // Add trust profile ID element Element trustProfileIDElem = slVerifyXMLSignatureRequest.createElementNS( Constants.NSURI_MOA_12_, Constants.NSPRE_MOA_12_ + ":TrustProfileID"); trustProfileIDElem.appendChild(slVerifyXMLSignatureRequest.createTextNode(trustProfileID)); verifyRequestElem.appendChild(trustProfileIDElem); return slVerifyXMLSignatureRequest; } /** * Extracts the creation time meta information from the E-Recht XML document that is referenced by * the XML signature contained in the specified MOA VerifyXMLSignatureRequest. * * @param verifyRequestElem The MOA VerifyXMLSignatureRequest. It is assumed that the * request contains an XML signature which signs a E-Recht XML document * (referring to the E-Recht XML document and transforming it to a corresponding * XHTML representation respectively). The E-Recht XML document is assumed to * have a root element with the name erechtdok in the namespace * http://www.bka.gv.at. The creation time meta information is * assumed to be contained in the attribute h-created of the root * element. The value of the attribute h-created is assumed to have * the format dd. MMMMM yyyy, hh:mm:ss where MMMMM denotes the month * in German prose (see @link #convertMonth(String)). * * @return the extracted creation time meta information, or null, if the extraction fails for * any reason. */ private static String extractXMLDocCreationTime(Element verifyRequestElem) { // Get E-Recht XML document using location information in MOA VerifyXMLSignature request String nSPrefixes = Constants.NSPRE_MOA_12_ + " " + Constants.NSURI_MOA_12_; String xPathXMLDocumentLocContent = "//" + Constants.NSPRE_MOA_12_ + ":SupplementProfile" + "/" + Constants.NSPRE_MOA_12_ + ":Content[@Reference=\"dokument.xml\"]" + "/" + Constants.NSPRE_MOA_12_ + ":LocRefContent"; Document xmlDocument = null; try { XPathUtils utils = new XPathUtils(); utils.setupContext(xPathXMLDocumentLocContent, verifyRequestElem, nSPrefixes); NodeList resultNL = utils.selectNodeSet(verifyRequestElem); if (resultNL == null || resultNL.getLength() < 1) { logger_.warn("LocRefContent element for E-Recht XML document not found in MOA VerifyXMLSignatureRequest."); return null; } URL locRefURL = new URL(DOMUtils.getText((Element) resultNL.item(0))); InputStream locRefURLIS = locRefURL.openStream(); xmlDocument = DOMUtils.parseWellFormed(locRefURLIS); } catch (Exception e) { String message = "An error occurred while trying to load E-Recht XML document:"; logger_.warn(message, e); return null; } // Extract attribute "h-created" from E-Recht XML document root element String hCreated = xmlDocument.getDocumentElement().getAttributeNS(null, "h-created"); if (hCreated == null || "".equals(hCreated)) { logger_.warn("Attribute \"h-created\" not found in E-Recht XML document root element."); return null; } // Convert attribute "h-created" into a java date ("h-created" has formats like "10. März 2006, 11:15:09") try { String dateStr = hCreated.substring(0, hCreated.indexOf(',')).trim(); String timeStr = hCreated.substring(hCreated.indexOf(',') + 1).trim(); StringTokenizer tokenizer = new StringTokenizer(dateStr, " "); String dateDayStr = tokenizer.nextToken(); int dateDay = Integer.parseInt(dateDayStr.substring(0, dateDayStr.indexOf('.'))); String dateMonthAlphaStr = tokenizer.nextToken(); int dateMonthNum = convertMonth(dateMonthAlphaStr); int dateYear = Integer.parseInt(tokenizer.nextToken()); tokenizer = new StringTokenizer(timeStr, ":"); int timeHours = Integer.parseInt(tokenizer.nextToken()); int timeMins = Integer.parseInt(tokenizer.nextToken()); int timeSecs = Integer.parseInt(tokenizer.nextToken()); GregorianCalendar calendar = new GregorianCalendar(dateYear, dateMonthNum, dateDay, timeHours, timeMins, timeSecs); SimpleDateFormat dF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); return dF.format(calendar.getTime()); } catch (Throwable t) { logger_.warn("Attribute \"h-created\" in E-Recht XML document root element has unexpected format: " + hCreated); return null; } } /** * Converts the specified month name into a numeric representation as specified in @link Calendar, e.g. * @link Calendar#JANUARY. * * @param dateMonthAlphaStr The specified month name; must be one of Jänner, Januar, * Februar, Feber, März, April, * Mai, Juni, Juli, August, * September, Oktober, November, or * Dezember. * * @return the numeric representation of the specified month. * * @throws Exception if dateMonthAlphaStr contains an invalid month name. */ private static int convertMonth(String dateMonthAlphaStr) throws Exception { if ("Jänner".equalsIgnoreCase(dateMonthAlphaStr) || "Januar".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.JANUARY; if ("Februar".equalsIgnoreCase(dateMonthAlphaStr) || "Feber".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.FEBRUARY; if ("März".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.MARCH; if ("April".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.APRIL; if ("Mai".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.MAY; if ("Juni".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.JUNE; if ("Juli".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.JULY; if ("August".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.AUGUST; if ("September".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.SEPTEMBER; if ("Oktober".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.OCTOBER; if ("November".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.NOVEMBER; if ("Dezember".equalsIgnoreCase(dateMonthAlphaStr)) return Calendar.DECEMBER; String message = "Invalid month identifier found in attribute \"h-created\":" + dateMonthAlphaStr; logger_.warn(message); throw new Exception(message); } /** * Checks wheter a DateTime element exists in the specified MOA * VerifyXMLSignatureRequest. * * @param moaVerifyXMLSignatureRequest The MOA VerifyXMLSingatureRequest. * * @return true if the element exists, false otherwhise. * * @throws ServletException if the check fails for any reason. */ private static boolean dateTimeExists(Element moaVerifyXMLSignatureRequest) throws ServletException { String nSPrefixes = Constants.NSPRE_MOA_12_ + " " + Constants.NSURI_MOA_12_; String xPathDateTime = "//" + Constants.NSPRE_MOA_12_ + ":DateTime"; NodeList resultNL; try { XPathUtils utils = new XPathUtils(); utils.setupContext(xPathDateTime, moaVerifyXMLSignatureRequest, nSPrefixes); resultNL = utils.selectNodeSet(moaVerifyXMLSignatureRequest); } catch (Exception e) { String message = "An error occurred while checking for DateTime element in MOA VerifyXMLSignatureRequest:"; logger_.error(message, e); throw new ServletException(message, e); } if (resultNL == null) return false; if (resultNL.getLength() < 1) return false; return true; } /** * Checks whether an etsi:SigningTime signed attribute exists as part of the XML signature * contained in the specified MOA VerifyXMLSingatureRequest. * * @param moaVerifyXMLSignatureRequest The MOA VerifyXMLSingatureRequest. * * @return true, if the attribute exists, false otherwhise. * * @throws ServletException if the check fails for any reason. */ private static boolean signingTimeExists(Element moaVerifyXMLSignatureRequest) throws ServletException { String nSPrefixes = Constants.NSPRE_ETSI_ + " " + Constants.NSURI_ETSI_; String xPathDateTime = "//" + Constants.NSPRE_ETSI_ + ":SigningTime"; NodeList resultNL; try { XPathUtils utils = new XPathUtils(); utils.setupContext(xPathDateTime, moaVerifyXMLSignatureRequest, nSPrefixes); resultNL = utils.selectNodeSet(moaVerifyXMLSignatureRequest); } catch (Exception e) { String message = "An error occurred while checking for " + Constants.NSPRE_ETSI_ + ":SigningTime element in XML signature in MOA VerifyXMLSignatureRequest:"; logger_.error(message, e); throw new ServletException(message, e); } if (resultNL == null) return false; if (resultNL.getLength() < 1) return false; return true; } }