diff options
Diffstat (limited to 'spss.slinterface/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java')
-rw-r--r-- | spss.slinterface/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/spss.slinterface/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java b/spss.slinterface/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java new file mode 100644 index 000000000..0ff14551f --- /dev/null +++ b/spss.slinterface/src/at/gv/egovernment/moa/spss/slinterface/filters/SL2MOAFilter.java @@ -0,0 +1,381 @@ +/* + * Created on 18.11.2003 + * + * (c) Stabsstelle IKT-Strategie des Bundes + */ +package at.gv.egovernment.moa.spss.slinterface.filters; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.fileupload.DiskFileUpload; +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileUpload; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.xerces.parsers.DOMParser; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.spss.slinterface.Constants; +import at.gv.egovernment.moa.spss.slinterface.beans.ChecksInfoBean; +import at.gv.egovernment.moa.spss.slinterface.beans.DataInfoBean; +import at.gv.egovernment.moa.spss.slinterface.beans.SignerInfoBean; +import at.gv.egovernment.moa.spss.slinterface.moainvoker.MOAInvoker; +import at.gv.egovernment.moa.spss.slinterface.servlets.SLRequest; +import at.gv.egovernment.moa.spss.slinterface.transformers.MOA2SL; +import at.gv.egovernment.moa.spss.slinterface.transformers.SL2MOA; + +/** + * @author Gregor Karlinger (mailto:gregor.karlinger@cio.gv.at) + */ +public class SL2MOAFilter implements Filter +{ + private static Logger logger_ = Logger.getLogger(Constants.LH_FILTERS_); + + private FilterConfig config_; + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) + */ + public void init(FilterConfig config) throws ServletException + { + // Store filter configuration + config_ = config; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) + */ + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException + { + // It is necessary to set the content type header already here, because for any unknown reason setting + // it in the response JSP page has no effects at all. Perhaps any of the filters or the like already + // writes to the response output stream. + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.setHeader("Content-Type", "text/html; charset='ISO-8859-1'"); + + // Create session + HttpSession session = ((HttpServletRequest) request).getSession(true); + + // Check if request is HTTP-POST + checkHttpPost((HttpServletRequest) request); + + // Remember remote IP address for later URL rewriting + session.setAttribute("remoteAddr", request.getRemoteAddr()); + + // Get SL request from content of request + SLRequest slRequest = parseRequest((HttpServletRequest) request); + session.setAttribute("slRequest", slRequest); + + // Schema validate SL request + CharArrayReader slXmlRequestCAR = new CharArrayReader(slRequest.xmlRequest_.toCharArray()); + Document slXMLRequestDoc = parseSlXmlRequest(slXmlRequestCAR); + logger_.debug("Finnished schema validating SL request."); + + // Transform SL request into a MOA SPSS request + Properties initProps = (Properties)config_.getServletContext().getAttribute(Constants.WSCP_INIT_PROPS_); + String trustProfileId = initProps.getProperty(Constants.IP_SP_TRUSTPROFILEID_); + Document moaXMLRequestDoc = SL2MOA.toMoaVerifyXMLSignatureRequest(slXMLRequestDoc, trustProfileId); + ByteArrayOutputStream moaRequestBOS = new ByteArrayOutputStream(); + MOAInvoker.serializeDocument(moaXMLRequestDoc, moaRequestBOS); + logger_.debug("SL request transformed into MOA request:\n" + moaRequestBOS); + ByteArrayInputStream moaRequestIS = new ByteArrayInputStream(moaRequestBOS.toByteArray()); + logger_.debug("Finnished transforming SL request into a MOA SP request."); + + // Invoke MOA SPSS + RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request, moaRequestIS); + ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response); + chain.doFilter(requestWrapper, responseWrapper); + logger_.debug("Finnished invoking MOA SP service."); + + // Parse MOA response + DOMParser xmlParser = (DOMParser) config_.getServletContext().getAttribute(Constants.WSCP_XMLPARSER_); + ServletOutputStream moaResponseSOS = (ServletOutputStream) responseWrapper.getOutputStream(); + ByteArrayInputStream moaResponseBIS = new ByteArrayInputStream(moaResponseSOS.toByteArray()); + InputSource responseSource = new InputSource(moaResponseBIS); + Document moaResponseDoc; + try + { + xmlParser.parse(responseSource); + moaResponseDoc = xmlParser.getDocument(); + } + catch (SAXException e) + { + String message = "Parsing MOA XML response failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + logger_.debug("Finnished parsing MOA SP response."); + + // Create bean with info about signed data + try + { + DataInfoBean dataInfo = new DataInfoBean( + moaXMLRequestDoc, + moaResponseDoc, + ((HttpServletRequest) request).getContextPath(), + session, + config_.getServletContext()); + session.setAttribute("dataInfo", dataInfo); + } + catch (Exception e) + { + String message = "Creating DataInfobean failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + logger_.debug("Finnished creating bean with info about signed data."); + + // Transform MOA response into a SL response + Document slResponseDoc; + slResponseDoc = MOA2SL.toSlVerifyXMLSignatureResponse(moaResponseDoc); + session.setAttribute("slResponseDoc", slResponseDoc); + logger_.debug("Finnished transforming MOA SP response into a SL response."); + + // Create bean with info about signer + SignerInfoBean signerInfo = new SignerInfoBean(slResponseDoc); + request.setAttribute("signerInfo", signerInfo); + logger_.debug("Finnished creating bean with info about signer."); + + // Create bean with info about checks + ChecksInfoBean checksInfo = new ChecksInfoBean(slResponseDoc); + request.setAttribute("checksInfo", checksInfo); + logger_.debug("Finnished creating bean with info about checks."); + + // Include jsp page, which writes the overview information about the verified signature + try + { + RequestDispatcher dispatcher = request.getRequestDispatcher("/pages/resultOverview.jsp"); + dispatcher.include(request, response); + } + catch (IOException e) + { + String message = "Failed to create result overview page."; + logger_.error(message, e); + throw new ServletException(message, e); + } + logger_.debug("Finnished SL2MOAFilter."); + } + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * @see javax.servlet.Filter#destroy() + */ + public void destroy() + { + // Nothing to do here at the moment. + } + + /* ---------------------------------------------------------------------------------------------------- */ + + // TODO Revisit if method can be removed + /* private void initTransformer(ServletContext context, String initPropStylesheetLoc) throws ServletException + { + String stylesheetName = + (Constants.IP_SL2MOA_STYLESHEET_.equals(initPropStylesheetLoc)) + ? "sl2Moa" + : "moa2Sl"; + + String contextAttrName = + (Constants.IP_SL2MOA_STYLESHEET_.equals(initPropStylesheetLoc)) + ? Constants.WSCP_SL2MOA_TRANSFORMER_ + : Constants.WSCP_MOA2SL_TRANSFORMER_; + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Properties initProps = (Properties) context.getAttribute(Constants.WSCP_INIT_PROPS_); + String stylesheetLoc = initProps.getProperty(initPropStylesheetLoc); + InputStream stylesheetIS = context.getResourceAsStream(stylesheetLoc); + if (stylesheetIS == null) + { + String message = + "Cannot load " + stylesheetName + " stylesheet from location \"" + stylesheetLoc + "\"."; + logger_.error(message); + throw new ServletException(message); + } + Transformer transformer; + try + { + StreamSource stylesheetSS = new StreamSource(stylesheetIS); + transformer = transformerFactory.newTransformer(stylesheetSS); + } + catch (TransformerConfigurationException e) + { + String message = "Cannot create XSLT transformer with " + stylesheetName + " stylesheet."; + logger_.error(message, e); + throw new ServletException(message, e); + } + context.setAttribute(contextAttrName, transformer); + }*/ + + /* ---------------------------------------------------------------------------------------------------- */ + + /** + * Parses the http request. + */ + private SLRequest parseRequest(HttpServletRequest request) throws IOException + { + SLRequest slRequest = new SLRequest(); + + // Check if request URL ends with "http-security-layer-request" + // @TODO Don't know if this check is sufficient - spec says request URL must have this value as path + String requestURI = request.getRequestURI(); + if (!requestURI.endsWith(Constants.SLC_NAME_HTTP_REQUEST_)) + { + String message = "Request does not end with \"" + Constants.SLC_NAME_HTTP_REQUEST_ + "\"."; + logger_.error(message); + throw new IOException(message); + } + + if (FileUpload.isMultipartContent(request)) + { + // Request is encoded as mulitpart/form-data + List items; + try + { + DiskFileUpload upload = new DiskFileUpload(); + items = upload.parseRequest(request); + } + catch (FileUploadException e) + { + String message = "Cannot parse multipart/form-data request."; + logger_.error(message); + throw new IOException(message); + } + + Iterator itemsIt = items.iterator(); + while (itemsIt.hasNext()) + { + FileItem currItem = (FileItem) itemsIt.next(); + String currItemName = currItem.getFieldName(); + if (Constants.SLC_NAME_XML_REQUEST_.equals(currItemName)) + slRequest.xmlRequest_ = currItem.getString(); + else if (Constants.SLC_NAME_DATA_URL_.equals(currItemName)) + slRequest.dataUrl_ = currItem.getString(); + else if (Constants.SLC_NAME_STYLESHEET_URL_.equals(currItemName)) + slRequest.stylesheetUrl_ = currItem.getString(); + else if (Constants.SLC_NAME_REDIRECT_URL_.equals(currItemName)) + slRequest.redirectUrl_ = currItem.getString(); + else + continue; // @TODO Do not evaluate other params at the moment + } + } + else + { + // Request is encoded as application/x-www-form-urlencoded + Map paramsMap = request.getParameterMap(); + Iterator paramNames = paramsMap.keySet().iterator(); + while (paramNames.hasNext()) + { + String currName = (String) paramNames.next(); + String[] currValues = (String[]) paramsMap.get(currName); + if (Constants.SLC_NAME_XML_REQUEST_.equals(currName)) + slRequest.xmlRequest_ = currValues[0]; + else if (Constants.SLC_NAME_DATA_URL_.equals(currName)) + slRequest.dataUrl_ = currValues[0]; + else if (Constants.SLC_NAME_STYLESHEET_URL_.equals(currName)) + slRequest.stylesheetUrl_ = currValues[0]; + else if (Constants.SLC_NAME_REDIRECT_URL_.equals(currName)) + slRequest.redirectUrl_ = currValues[0]; + else + continue; // @TODO Do not evaluate other params at the moment + } + } + + if (slRequest.xmlRequest_ == null || slRequest.dataUrl_ == null || + slRequest.stylesheetUrl_ != null || slRequest.redirectUrl_ != null) + { + // @TODO Only combination of XMLRequest and DataURL allowed at the moment + String message = "Currently only (XMLRequest + DataURL) is supported."; + logger_.error(message); + throw new IOException(message); + } + + return slRequest; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private Document parseSlXmlRequest(Reader slXmlRequest) throws ServletException + { + // Parse sl request + InputSource slXMLRequestIS = new InputSource(slXmlRequest); + Document slXmlRequestDoc = null; + try + { + DOMParser xmlParser = (DOMParser) config_.getServletContext().getAttribute(Constants.WSCP_XMLPARSER_); + xmlParser.parse(slXMLRequestIS); + slXmlRequestDoc = xmlParser.getDocument(); + } + catch (Exception e) + { + String message = "Parsing Security-Layer request failed."; + logger_.error(message, e); + throw new ServletException(message, e); + } + if (logger_.getEffectiveLevel().isGreaterOrEqual(Level.DEBUG)) + { + ByteArrayOutputStream debugOutputStream = new ByteArrayOutputStream(); + try + { + MOAInvoker.serializeDocument(slXmlRequestDoc, debugOutputStream); + logger_.debug("XML-Request received:\n" + debugOutputStream); + } + catch (IOException e) + { + // No debug output if this fails + } + } + + // Check if namespace is correct + String namespaceURI = slXmlRequestDoc.getDocumentElement().getNamespaceURI(); + if (!Constants.NSURI_SL_11_.equals(namespaceURI) && !Constants.NSURI_SL_12_.equals(namespaceURI)) + { + String message = "XML request has invalid namespace: \"" + namespaceURI + "\"."; + logger_.error(message); + throw new ServletException(message); + } + + return slXmlRequestDoc; + } + + /* ---------------------------------------------------------------------------------------------------- */ + + private void checkHttpPost(HttpServletRequest request) throws ServletException + { + String method = request.getMethod(); + if (!"POST".equals(method)) + { + String message = "HTTP method \"" + method + "\" not supported. Must be \"POST\"."; + logger_.error(message); + throw new ServletException(message); + } + } +} |