From d0c59a890be350ff1c39901e7fa94bf68c048065 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Tue, 28 Jan 2014 16:05:21 +0100 Subject: URL Whitelist + Basic Design --- .../gv/egiz/pdfas/web/config/WebConfiguration.java | 60 ++++++++++++++++++++-- .../web/exception/PdfAsSecurityLayerException.java | 14 +++++ .../at/gv/egiz/pdfas/web/helper/PdfAsHelper.java | 1 - .../gv/egiz/pdfas/web/helper/RemotePDFFetcher.java | 26 +++++++--- .../gv/egiz/pdfas/web/servlets/DataURLServlet.java | 22 ++++++-- .../at/gv/egiz/pdfas/web/servlets/ErrorPage.java | 14 +++-- .../egiz/pdfas/web/servlets/ProvidePDFServlet.java | 14 ++++- 7 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java (limited to 'pdf-as-web/src/main/java/at/gv/egiz/pdfas') diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java index 6609e51d..c7520347 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/config/WebConfiguration.java @@ -2,6 +2,9 @@ package at.gv.egiz.pdfas.web.config; import java.io.File; import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; import java.util.Properties; import org.slf4j.Logger; @@ -24,12 +27,21 @@ public class WebConfiguration { public static final String KEYSTORE_ALIAS = "ks.key.alias"; public static final String KEYSTORE_KEY_PASS = "ks.key.pass"; + public static final String WHITELIST_ENABLED = "whitelist.enabled"; + public static final String WHITELIST_VALUE_PRE = "whitelist.url."; + private static Properties properties = new Properties(); private static final Logger logger = LoggerFactory .getLogger(WebConfiguration.class); + private static List whiteListregEx = new ArrayList(); + public static void configure(String config) { + + properties.clear(); + whiteListregEx.clear(); + try { properties.load(new FileInputStream(config)); } catch(Exception e) { @@ -37,6 +49,23 @@ public class WebConfiguration { throw new RuntimeException(e); } + if(isWhiteListEnabled()) { + Iterator keyIt = properties.keySet().iterator(); + while(keyIt.hasNext()) { + Object keyObj = keyIt.next(); + if(keyObj != null) { + String key = keyObj.toString(); + if(key.startsWith(WHITELIST_VALUE_PRE)) { + String whitelist_expr = properties.getProperty(key); + if(whitelist_expr != null) { + whiteListregEx.add(whitelist_expr); + logger.debug("URL Whitelist: " + whitelist_expr); + } + } + } + } + } + String pdfASDir = getPdfASDir(); if(pdfASDir == null) { logger.error("Please configure pdf as working directory in the web configuration"); @@ -107,9 +136,34 @@ public class WebConfiguration { } return false; } - - public static boolean isProvidePdfURLinWhitelist(String url) { - //TODO implement whitelisting for pdfURLS + + public static boolean isWhiteListEnabled() { + String value = properties.getProperty(WHITELIST_ENABLED); + if(value != null) { + if(value.equals("true")) { + return true; + } + } return false; } + + public static synchronized boolean isProvidePdfURLinWhitelist(String url) { + if(isWhiteListEnabled()) { + + Iterator patterns = whiteListregEx.iterator(); + while(patterns.hasNext()) { + String pattern = patterns.next(); + try { + if(url.matches(pattern)) { + return true; + } + } catch(Throwable e) { + logger.error("Error in matching regex: " + pattern, e); + } + } + + return false; + } + return true; + } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java new file mode 100644 index 00000000..e499302d --- /dev/null +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/exception/PdfAsSecurityLayerException.java @@ -0,0 +1,14 @@ +package at.gv.egiz.pdfas.web.exception; + +public class PdfAsSecurityLayerException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -4632774270754873043L; + + public PdfAsSecurityLayerException(String info, int errorcode) { + super("SecurityLayer Error: [" + errorcode + "] " + info); + } + +} diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java index 2f62269b..1059738e 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/PdfAsHelper.java @@ -76,7 +76,6 @@ public class PdfAsHelper { private static ObjectFactory of = new ObjectFactory(); static { - // TODO: read from config file logger.debug("Creating PDF-AS"); pdfAs = PdfAsFactory.createPdfAs(new File(WebConfiguration.getPdfASDir())); logger.debug("Creating PDF-AS done"); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java index 9532e074..cb404b66 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/helper/RemotePDFFetcher.java @@ -5,6 +5,7 @@ import java.net.MalformedURLException; import java.net.URL; import at.gv.egiz.pdfas.common.utils.StreamUtils; +import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; public class RemotePDFFetcher { @@ -16,16 +17,25 @@ public class RemotePDFFetcher { } catch (MalformedURLException e) { throw new PdfAsWebException("Not a valid URL!", e); } - if(url.getProtocol().equals("http") || url.getProtocol().equals("https")) { - - try { - InputStream is = url.openStream(); - return StreamUtils.inputStreamToByteArray(is); - } catch (Exception e) { - throw new PdfAsWebException("Failed to fetch pdf document!", e); + if (WebConfiguration.isProvidePdfURLinWhitelist(url.toExternalForm())) { + if (url.getProtocol().equals("http") + || url.getProtocol().equals("https")) { + + try { + InputStream is = url.openStream(); + return StreamUtils.inputStreamToByteArray(is); + } catch (Exception e) { + throw new PdfAsWebException( + "Failed to fetch pdf document!", e); + } + } else { + throw new PdfAsWebException( + "Failed to fetch pdf document protocol " + + url.getProtocol() + " is not supported"); } } else { - throw new PdfAsWebException("Failed to fetch pdf document protocol " + url.getProtocol() + " is not supported"); + throw new PdfAsWebException( + "Failed to fetch pdf document " + url.toExternalForm() + " is not allowed"); } } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java index a0fe3e80..7847d840 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/DataURLServlet.java @@ -6,10 +6,12 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import javax.xml.bind.JAXBElement; -import at.gv.egiz.pdfas.lib.api.StatusRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.web.exception.PdfAsSecurityLayerException; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.sl.CreateCMSSignatureResponseType; import at.gv.egiz.sl.ErrorResponseType; @@ -22,6 +24,9 @@ import at.gv.egiz.sl.util.SLMarschaller; public class DataURLServlet extends HttpServlet { private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory + .getLogger(DataURLServlet.class); + /** * @see HttpServlet#HttpServlet() */ @@ -64,11 +69,18 @@ public class DataURLServlet extends HttpServlet { PdfAsHelper.injectSignature(request, response, createCMSSignatureResponseType, getServletContext()); } else if(jaxbObject.getValue() instanceof ErrorResponseType) { ErrorResponseType errorResponseType = (ErrorResponseType)jaxbObject.getValue(); - // TODO: store error and redirect user - System.out.println("ERROR: " + errorResponseType.getErrorCode() + " " + errorResponseType.getInfo()); + logger.error("SecurityLayer: " + errorResponseType.getErrorCode() + " " + errorResponseType.getInfo()); + throw new PdfAsSecurityLayerException(errorResponseType.getInfo(), + errorResponseType.getErrorCode()); + + } else { + throw new PdfAsSecurityLayerException("Unknown SL response", + 9999); } } catch (Exception e) { - e.printStackTrace(); + PdfAsHelper.setSessionException(request, response, e.getMessage(), + e); + PdfAsHelper.gotoError(getServletContext(), request, response); } } diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java index fe436566..ef8e058f 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ErrorPage.java @@ -8,9 +8,9 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.swing.text.html.HTML; -import org.apache.commons.lang3.StringEscapeUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.HTMLFormater; @@ -21,7 +21,10 @@ import at.gv.egiz.pdfas.web.helper.PdfAsHelper; */ public class ErrorPage extends HttpServlet { private static final long serialVersionUID = 1L; - + + private static final Logger logger = LoggerFactory + .getLogger(ErrorPage.class); + /** * @see HttpServlet#HttpServlet() */ @@ -61,7 +64,7 @@ public class ErrorPage extends HttpServlet { .getSessionException(request, response); String message = PdfAsHelper.getSessionErrMessage(request, response); - if (errorURL != null) { + if (errorURL != null && WebConfiguration.isProvidePdfURLinWhitelist(errorURL)) { String template = PdfAsHelper.getErrorRedirectTemplateSL(); template = template.replace("##ERROR_URL##", errorURL); @@ -81,6 +84,9 @@ public class ErrorPage extends HttpServlet { response.getWriter().write(template); response.getWriter().close(); } else { + if(!WebConfiguration.isProvidePdfURLinWhitelist(errorURL)) { + logger.warn(errorURL + " is not allowed by whitelist"); + } response.setContentType("text/html"); PrintWriter pw = response.getWriter(); diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java index e1387fce..194a9a63 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ProvidePDFServlet.java @@ -8,7 +8,11 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.helper.PdfAsHelper; /** @@ -17,6 +21,9 @@ import at.gv.egiz.pdfas.web.helper.PdfAsHelper; public class ProvidePDFServlet extends HttpServlet { private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory + .getLogger(ProvidePDFServlet.class); + /** * @see HttpServlet#HttpServlet() */ @@ -47,7 +54,12 @@ public class ProvidePDFServlet extends HttpServlet { try { String invokeURL = PdfAsHelper.getInvokeURL(request, response); - if (invokeURL == null) { + if (invokeURL == null || WebConfiguration.isProvidePdfURLinWhitelist(invokeURL)) { + + if(!WebConfiguration.isProvidePdfURLinWhitelist(invokeURL)) { + logger.warn(invokeURL + " is not allowed by whitelist"); + } + // Deliver to Browser directly! response.setContentType("text/html"); PrintWriter pw = response.getWriter(); -- cgit v1.2.3