From 1d39a4fa10f410c5d4fdcc64413b9e0f0372f9e1 Mon Sep 17 00:00:00 2001 From: gregor Date: Wed, 3 Dec 2003 08:54:36 +0000 Subject: Zwischenstand, compilierbar git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@69 d688527b-c9ab-4aba-bd8d-4036d912da1d --- .../moa/spss/slinterface/beans/DataInfoBean.java | 366 ++++++++++++++++++++- .../spss/slinterface/beans/HashInputDataInfo.java | 55 ++++ 2 files changed, 409 insertions(+), 12 deletions(-) create mode 100644 spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/HashInputDataInfo.java (limited to 'spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans') diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java index 3e23c9eb0..db67ac411 100644 --- a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java @@ -7,13 +7,22 @@ package at.gv.egovernment.moa.spss.slinterface.beans; import iaik.utils.Util; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.net.URL; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Random; +import java.util.Set; +import java.util.StringTokenizer; import javax.servlet.ServletContext; import javax.servlet.http.HttpSession; @@ -21,11 +30,18 @@ import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; import org.apache.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; import at.gv.egovernment.moa.spss.slinterface.Constants; import at.gv.egovernment.moa.spss.slinterface.DOMUtils; +import at.gv.egovernment.moa.spss.slinterface.XPathUtils; +import at.gv.egovernment.moa.spss.slinterface.moainvoker.MOAInvoker; /** * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) @@ -34,27 +50,56 @@ public class DataInfoBean implements HttpSessionBindingListener { private static Logger logger_ = Logger.getLogger(Constants.LH_BEANS_); + // MOA private static final String HID_ELEM_ = "HashInputData"; private static final String B64CONT_ELEM_ = "Base64Content"; private static final String XMLCONT_ELEM_ = "XMLContent"; + private static final String SIGLOC_ELEM_ = "VerifySignatureLocation"; + // XMLDSIG + private static final String TYPE_ATTR_ = "Type"; + private static final String URI_ATTR_ = "URI"; + + // XHTML + private static final String SRC_ATTR_ = "src"; + private static final String HTML_ELEM_ = "html"; + private static final String HID_URL_PREFIX_ = "/showdata?hidCount="; - List hashInputDataFilenames_; + private static final String XPATH_ALL_IMG_ = "//" + Constants.NSPRE_XHTML_ + ":img"; + private static final String XPATH_ALL_REF_ = "./" + Constants.NSPRE_DSIG_ + ":SignedInfo/" + + Constants.NSPRE_DSIG_ + ":Reference"; + private static final String XPATH_SIG_ENV_CONTENT_ = "/" + Constants.NSPRE_MOA_12_ + ":VerifyXMLSignatureRequest/" + + Constants.NSPRE_MOA_12_ + ":VerifySignatureInfo/" + Constants.NSPRE_MOA_12_ + ":VerifySignatureEnvironment/*"; + + + + private static final String SLXHTML_TYPE_PREFIX_ = "http://www.buergerkarte.at/specifications/" + + "Security-Layer/20031113?Name=SignedImage&InstanceDocRef="; + + ServletContext context_; + + /** + * Contains objects of type {@link HashInputDataInfo}. + */ + List hashInputDataInfos_; + int hashInputDataCount_; /* ---------------------------------------------------------------------------------------------------- */ - public DataInfoBean(Document moaResponseDoc, ServletContext context, HttpSession session) - throws IOException + public DataInfoBean(Document moaRequestDoc, Document moaResponseDoc, ServletContext context, + HttpSession session) throws Exception { - hashInputDataFilenames_ = new ArrayList(); + context_ = context; + + hashInputDataInfos_ = new ArrayList(); int hashInputDataCount_ = 0; Element moaResponseElem = moaResponseDoc.getDocumentElement(); List hidElems = DOMUtils.getChildElems(moaResponseElem, Constants.NSURI_MOA_12_, HID_ELEM_, false); - Properties initProps = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + Properties initProps = (Properties) context_.getAttribute(Constants.WSCP_INIT_PROPS_); String tempDir = initProps.getProperty(Constants.IP_TEMP_DIR_); if (tempDir == null) { @@ -69,7 +114,7 @@ public class DataInfoBean implements HttpSessionBindingListener // Open file for current hash input data String currHidFileNameStr = tempDir + session.getId() + "_" + System.currentTimeMillis() + "_" + random.nextLong(); - currHidFileNameStr = context.getRealPath(currHidFileNameStr); + currHidFileNameStr = context_.getRealPath(currHidFileNameStr); FileOutputStream currHidFOS; try { @@ -111,7 +156,25 @@ public class DataInfoBean implements HttpSessionBindingListener throw new RuntimeException("XML content not support yet."); } - hashInputDataFilenames_.add(currHidFileNameStr); + hashInputDataInfos_.add(new HashInputDataInfo(currHidFileNameStr)); + } + + // Check if hids are slxhtml documents; mark them appropriately + try + { + Map signedImages = getSignedImages(moaRequestDoc, hashInputDataInfos_); + for (int i = 0; i < hashInputDataInfos_.size(); i++) + { + HashInputDataInfo currHid = (HashInputDataInfo) hashInputDataInfos_.get(i); + FileInputStream currHidIS = new FileInputStream(currHid.filename_); + checkImages(currHidIS, currHid, signedImages); + } + } + catch (Exception e) + { + String message = "Performing SLXHTML checks failed."; + logger_.error(message, e); + throw new Exception(message, e); } } @@ -127,9 +190,9 @@ public class DataInfoBean implements HttpSessionBindingListener public void valueUnbound(HttpSessionBindingEvent event) { // Delete all temporary hash input data files - for (int i = 0; i < hashInputDataFilenames_.size(); i++) + for (int i = 0; i < hashInputDataInfos_.size(); i++) { - String currFileStr = (String) hashInputDataFilenames_.get(i); + String currFileStr = ((HashInputDataInfo) hashInputDataInfos_.get(i)).filename_; File currFile = new File(currFileStr); currFile.delete(); } @@ -146,16 +209,295 @@ public class DataInfoBean implements HttpSessionBindingListener public String getHashInputDataFilename() { - return (String) hashInputDataFilenames_.get(hashInputDataCount_); + HashInputDataInfo currHid = (HashInputDataInfo) hashInputDataInfos_.get(hashInputDataCount_); + return (currHid == null) ? null : currHid.filename_; } /* ---------------------------------------------------------------------------------------------------- */ public String getHashInputDataURL() { - - return (hashInputDataFilenames_.size() > hashInputDataCount_) + return (hashInputDataInfos_.size() > hashInputDataCount_) ? HID_URL_PREFIX_ + hashInputDataCount_ : null; } + + /* ---------------------------------------------------------------------------------------------------- */ + + public boolean getShowHashInputData() + { + HashInputDataInfo currHid = (HashInputDataInfo) hashInputDataInfos_.get(hashInputDataCount_); + return (currHid == null) ? false : currHid.doShow_; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + public boolean getIsSLXHTMLDocument() + { + HashInputDataInfo currHid = (HashInputDataInfo) hashInputDataInfos_.get(hashInputDataCount_); + return (currHid == null) ? false : currHid.isSLXHTMLDocument_; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Document parseSLXHTMLDocument(InputStream docIS) + { + DOMParser xmlParser = (DOMParser) context_.getAttribute(Constants.WSCP_XMLPARSER_); + InputSource docInputSource = new InputSource(docIS); + Document parsedDoc = null; + try + { + xmlParser.parse(docInputSource); + parsedDoc = xmlParser.getDocument(); + } + catch (Exception e) + { + // Exception shows that document is not a valid SLXHTML document; return null in that case + logger_.debug("HashInputData is not a valid SLXHTML document.", e); + return null; + } + + Element docElem = parsedDoc.getDocumentElement(); + if (docElem.getNamespaceURI() != Constants.NSURI_XHTML_ || docElem.getLocalName() != HTML_ELEM_) + { + return null; + } + + return parsedDoc; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private void checkImages(InputStream hidIS, HashInputDataInfo hid, Map signedImages) throws Exception + { + // Parse hidIS + Document slxhtmlDoc = parseSLXHTMLDocument(hidIS); + if (slxhtmlDoc == null) return; + + // Get all img elements of slxhtml document + XPathUtils xpUtils = new XPathUtils(); + String additionalNSPrefixes = Constants.NSPRE_XHTML_ + " " + Constants.NSURI_XHTML_; + xpUtils.setupContext(XPATH_ALL_IMG_, slxhtmlDoc.getDocumentElement(), additionalNSPrefixes); + NodeList imgTags = xpUtils.selectNodeSet(slxhtmlDoc); + + // Check if all img elements have corresponding slxhtml signed images + boolean allImgsSigned = true; + for (int i = 0; i < imgTags.getLength(); i++) + { + Element currImgElem = (Element) imgTags.item(i); + String uri = currImgElem.getAttribute(SRC_ATTR_); + if (!signedImages.containsKey(uri)) + { + allImgsSigned = false; + break; + } + } + + // Mark all corresponding slxhtml signed images as not to be shown + if (allImgsSigned) + { + for (int i = 0; i < imgTags.getLength(); i++) + { + Element currImgElem = (Element) imgTags.item(i); + String uri = currImgElem.getAttribute(SRC_ATTR_); + HashInputDataInfo currHidi = (HashInputDataInfo) signedImages.get(uri); + currHidi.doShow_ = false; + } + } + + // Change the src attributes of all img tags so that they refer to the temporary names + if (allImgsSigned) + { + for (int i = 0; i < imgTags.getLength(); i++) + { + Element currImgElem = (Element) imgTags.item(i); + String uri = currImgElem.getAttribute(SRC_ATTR_); + HashInputDataInfo currHidi = (HashInputDataInfo) signedImages.get(uri); + + Attr srcAttr = currImgElem.getAttributeNode(SRC_ATTR_); + int slashPos = currHidi.filename_.lastIndexOf('/'); + if (slashPos == -1) slashPos = 0; + String newSrcAttrValue = currHidi.filename_.substring(slashPos + 1); + srcAttr.setNodeValue(newSrcAttrValue); + } + } + + // Mark hid slxhtml document + hid.isSLXHTMLDocument_ = true; + + // Serialize modified slxhtml document to temporary file location + if (allImgsSigned) + { + FileOutputStream slxhtmlFOS = new FileOutputStream(hid.filename_); + MOAInvoker.serializeDocument(slxhtmlDoc, slxhtmlFOS); + slxhtmlFOS.close(); + } + + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Map getSignedImages(Document moaRequestDoc, List hashInputDataInfos) throws Exception + { + // Get signature from MOA request + Element signatureElem = getSignature(moaRequestDoc); + + // Get all signature references from MOA request + XPathUtils xpUtils = new XPathUtils(); + String additionalNSPrefixes = Constants.NSPRE_DSIG_ + " " + Constants.NSURI_DSIG_; + xpUtils.setupContext(XPATH_ALL_REF_, signatureElem, additionalNSPrefixes); + NodeList dsigRefs = xpUtils.selectNodeSet(signatureElem); + + // Check signature references for slxhtml images + HashMap imgHids = new HashMap(dsigRefs.getLength()); + for (int i = 0; i < dsigRefs.getLength(); i++) + { + Element currRef = (Element) dsigRefs.item(i); + String type = currRef.getAttribute(TYPE_ATTR_); + if (type != null && type.startsWith(SLXHTML_TYPE_PREFIX_)) + { + String uri = currRef.getAttribute(URI_ATTR_); + Set referredHids = createReferredHidsSet(type); + HashInputDataInfo currHidi = (HashInputDataInfo)hashInputDataInfos.get(i); + currHidi.uri_ = uri; + currHidi.referredHids_ = referredHids; + currHidi.isSLXHTMLImage_ = true; + imgHids.put(uri, currHidi); + } + } + + return imgHids; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Set createReferredHidsSet(String type) throws Exception + { + HashSet set = new HashSet(); + String typeSuffix = type.substring(SLXHTML_TYPE_PREFIX_.length()); + StringTokenizer tokenizer = new StringTokenizer(typeSuffix, ","); + while (tokenizer.hasMoreTokens()) + { + try + { + set.add(new Integer(tokenizer.nextToken())); + } + catch (NumberFormatException e) + { + String message = "Signed image type attribute \"" + type + "\" is malformed."; + logger_.error(message, e); + throw new Exception(message, e); + } + } + return set; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Element getSignature(Document moaRequestDoc) throws Exception + { + // Get signature environment content + NodeList contentNL; + try + { + XPathUtils xpUtils = new XPathUtils(); + String addNSPrefixes = Constants.NSPRE_MOA_12_ + " " + Constants.NSURI_MOA_12_; + xpUtils.setupContext(XPATH_SIG_ENV_CONTENT_, moaRequestDoc, addNSPrefixes); + contentNL = xpUtils.selectNodeSet(moaRequestDoc); + } + catch (Exception e) + { + String message = "Cannot find signature environment content."; + logger_.error(message); + throw new Exception(message, e); + } + if (contentNL.getLength() == 0) + { + String message = "Cannot find signature environment content."; + logger_.error(message); + throw new Exception(message); + } + Element contentElem = (Element) contentNL.item(0); + + // Get signature environment document form siganture environment content + String contentElemLocName = contentElem.getLocalName(); + Element sigEnvElem = null; + if (XMLCONT_ELEM_.equals(contentElemLocName)) + { + // XML content + NodeList contentNodes = contentElem.getChildNodes(); + for (int i = 0; i < contentNodes.getLength(); i++) + { + Node currContNode = (Node) contentNodes.item(i); + if (currContNode.getNodeType() == Node.ELEMENT_NODE) + { + sigEnvElem = (Element) currContNode; + break; + } + } + } + else if (B64CONT_ELEM_.equals(contentElemLocName)) + { + // Base64 content + String base64ContStr = DOMUtils.getText(contentElem); + byte[] contBytes = Util.Base64Decode(base64ContStr.getBytes()); + ByteArrayInputStream contBIS = new ByteArrayInputStream(contBytes); + Document sigEnvDoc; + try + { + sigEnvDoc = DOMUtils.parseWellFormed(contBIS); + } + catch (Exception e) + { + String message = "Cannot parse signature environment from base64 content."; + logger_.error(message); + throw new Exception(message, e); + } + sigEnvElem = sigEnvDoc.getDocumentElement(); + } + else + { + // LocRef content + String locRef = DOMUtils.getText(contentElem); + URL locRefURL = new URL(locRef); + InputStream contentIS = locRefURL.openStream(); + Document sigEnvDoc; + try + { + sigEnvDoc = DOMUtils.parseWellFormed(contentIS); + } + catch (Exception e) + { + String message = "Cannot parse signature environment from location reference content."; + logger_.error(message); + throw new Exception(message, e); + } + sigEnvElem = sigEnvDoc.getDocumentElement(); + } + + // Get signature form signature environment document + Element sigInfoElem = (Element) contentElem.getParentNode().getParentNode(); + Element sigLocElem = DOMUtils.getChildElem(sigInfoElem, Constants.NSURI_MOA_12_, SIGLOC_ELEM_); + String sigLocXPath = DOMUtils.getText(sigLocElem); + NodeList sigElemNL; + try + { + XPathUtils xpUtils = new XPathUtils(); + xpUtils.setupContext(sigLocXPath, sigLocElem, null); + sigElemNL = xpUtils.selectNodeSet(sigEnvElem); + } + catch (Exception e) + { + String message = "Cannot get signature at location \"" + sigLocXPath + "\" from signature environment."; + logger_.error(message); + throw new Exception(message, e); + } + if (sigElemNL.getLength() != 1 || ((Node) sigElemNL.item(0)).getNodeType() != Node.ELEMENT_NODE) + { + String message = "Cannot get signature at location \"" + sigLocXPath + "\" from signature environment."; + logger_.error(message); + throw new Exception(message); + } + return (Element) sigElemNL.item(0); + } } diff --git a/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/HashInputDataInfo.java b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/HashInputDataInfo.java new file mode 100644 index 000000000..e2cb27ab3 --- /dev/null +++ b/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/HashInputDataInfo.java @@ -0,0 +1,55 @@ +/* + * Created on 02.12.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.beans; + +import java.util.Set; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class HashInputDataInfo +{ + /** + * The name of the temporary file in which this data is stored. + */ + public String filename_; + + /** + * Is this HID a SLXHTML document? + */ + public boolean isSLXHTMLDocument_; + + /** + * Is this HID a SLXHTML signed image? + */ + public boolean isSLXHTMLImage_; + + /** + * Show HID in result presentation? + */ + public boolean doShow_; + + /** + * The URI attribute value of the dsig:Reference corresponding with this HID. + */ + public String uri_; + + /** + * In case that this ID is a SLXHTML signed image, this set contains objects of type Integer, + * indicating the SLXHTML HIDs where this image is referenced. + */ + public Set referredHids_; + + public HashInputDataInfo(String filename) + { + filename_ = filename; + isSLXHTMLDocument_ = false; + isSLXHTMLImage_ = false; + doShow_ = true; + uri_ = null; + referredHids_ = null; + } +} -- cgit v1.2.3