aboutsummaryrefslogtreecommitdiff
path: root/spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java
diff options
context:
space:
mode:
Diffstat (limited to 'spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java')
-rw-r--r--spss.slinterface/WEB-INF/src/at/gv/egovernment/moa/spss/slinterface/beans/DataInfoBean.java366
1 files changed, 354 insertions, 12 deletions
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);
+ }
}