From 6ef9bdefc58cb2553f23aaa9711d6341e293c9f7 Mon Sep 17 00:00:00 2001 From: tknall Date: Fri, 10 Oct 2008 11:13:40 +0000 Subject: Deprecated webapp-folder removed from svn repository. New DefaultConfiguration.zip integrated in order to allow mocca signatures. Minor bug concerning choice of cce within the web application fixed. Signature with new online bku MOCCA integrated (new signature device "moc" created). Configuration keys for mocca added. New error codes (371 = signature verification not supported by this connector, 372 = invalid signing time) introduced. Optional check of the signing time for the web application implemented. At signature creation time the signing time is checked for plausibility. This is a workaround for the ITS:mac-linux signing time bug. New configuration key ("signing_time_tolerance") added (applies to web application only) to overcome invalid signing times. A signature is only accepted if its signing time is within a time frame of [current time - signing_time_tolerance, current time + signing_time_tolerance] where signing_time_tolerance is interpreted as seconds. Bugfix: Correct extraction of signatures with wrong signing times implemented. (The order of the signatures is still invalid in case of false signing times.) Optional override of the dynamic creation of the signature retrieval url (locrefcontent) implemented in order to overcome ssl problems (retrieve_signature_data_url_override). Note: Assure that this URL is accessible from the citizen card environment. Download of signed pdf-file for external application interface adjusted. Verification of mocca signed documents implemented. Retrieval of xml response via multipart implemented (mocca strictly follows security layer spec) git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@296 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .../at/gv/egiz/pdfas/api/commons/Constants.java | 10 +++ .../java/at/gv/egiz/pdfas/commandline/Main.java | 6 +- .../at/gv/egiz/pdfas/exceptions/ErrorCode.java | 3 + .../pdfas/impl/vfilter/VerificationFilterImpl.java | 44 +++++++-- src/main/java/at/gv/egiz/pdfas/utils/WebUtils.java | 100 +++++++++++++++++++++ .../egiz/pdfas/web/helper/SignServletHelper.java | 4 +- .../egiz/pdfas/web/helper/SigningTimeHelper.java | 83 +++++++++++++++++ 7 files changed, 241 insertions(+), 9 deletions(-) create mode 100644 src/main/java/at/gv/egiz/pdfas/utils/WebUtils.java create mode 100644 src/main/java/at/gv/egiz/pdfas/web/helper/SigningTimeHelper.java (limited to 'src/main/java/at/gv') diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java index f9a3c03..a7bc776 100644 --- a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java +++ b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java @@ -49,6 +49,16 @@ public final class Constants */ public static String SIGNATURE_DEVICE_BKU = "bku"; + /** + * The signature device a1. + */ + public static String SIGNATURE_DEVICE_A1 = "a1"; + + /** + * The signature device MOCCA (online bku). + */ + public static final String SIGNATURE_DEVICE_MOC = "moc"; + /** * Only binary signatures are verified. */ diff --git a/src/main/java/at/gv/egiz/pdfas/commandline/Main.java b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java index c84b417..44a472b 100644 --- a/src/main/java/at/gv/egiz/pdfas/commandline/Main.java +++ b/src/main/java/at/gv/egiz/pdfas/commandline/Main.java @@ -490,7 +490,7 @@ public abstract class Main public static void carryOutSign(String input, String connector, String signature_mode, String signature_type, String pos_string, String user_name, String user_password, String output, PrintWriter messageOutput) throws PdfAsException { - messageOutput.println("Signing..."); + messageOutput.println("Signing " + input + "..."); // for performance measurement long startTime = 0; @@ -537,12 +537,12 @@ public abstract class Main logger_.info(toReport); } - messageOutput.println("Signing was successful."); + messageOutput.println("Signing was successful (" + output + ")."); } public static void carryOutVerify(String input, String connector, int verify_which, PrintWriter messageOutput) throws PdfAsException { - messageOutput.println("Verifying..."); + messageOutput.println("Verifying " + input + "..."); // for performance measurement long startTime = 0; diff --git a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java index 7566c41..062ff6b 100644 --- a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java +++ b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java @@ -40,6 +40,9 @@ public final class ErrorCode public static final int MODIFIED_AFTER_SIGNATION = 316; public static final int NON_BINARY_SIGNATURES_PRESENT = 317; + + public static final int SIGNATURE_VERIFICATION_NOT_SUPPORTED = 371; + public static final int INVALID_SIGNING_TIME = 372; public static final int WEB_EXCEPTION = 330; diff --git a/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java b/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java index 3ca497b..d9549b0 100644 --- a/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java +++ b/src/main/java/at/gv/egiz/pdfas/impl/vfilter/VerificationFilterImpl.java @@ -413,11 +413,12 @@ public class VerificationFilterImpl implements VerificationFilter { assert partitionResult.size() >= prevPartitionResult.size(); - for (int i = prevPartitionResult.size(); i < partitionResult.size(); i++) - { - SignatureHolder sh = (SignatureHolder) partitionResult.get(i); - extractedSignatures.add(sh); - } +// for (int i = prevPartitionResult.size(); i < partitionResult.size(); i++) +// { +// SignatureHolder sh = (SignatureHolder) partitionResult.get(i); +// extractedSignatures.add(sh); +// } + mergeSignatures(prevPartitionResult, partitionResult, extractedSignatures); } prevPartitionResult = partitionResult; @@ -436,6 +437,39 @@ public class VerificationFilterImpl implements VerificationFilter return signatureHolderChain; } + private void mergeSignatures(List oldList, List newList, List result) { + + for(int i=0; i < newList.size(); i++) { + + SignatureHolder currentNewSh = (SignatureHolder)newList.get(i); + + boolean shAlreadyPresentInOldList = false; + int pos = -1; + + for(int j=0; j add + result.add(currentNewSh); + } + + } + + + return; + } + + protected List flattenOutTextPartitions (List partitions, List blocks) { diff --git a/src/main/java/at/gv/egiz/pdfas/utils/WebUtils.java b/src/main/java/at/gv/egiz/pdfas/utils/WebUtils.java new file mode 100644 index 0000000..4bca486 --- /dev/null +++ b/src/main/java/at/gv/egiz/pdfas/utils/WebUtils.java @@ -0,0 +1,100 @@ +package at.gv.egiz.pdfas.utils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.web.LocalRequestHelper; + +/** + * @author tknall + */ +public final class WebUtils { + + private WebUtils() { + } + + /** + * The log. + */ + private final static Log LOG = LogFactory.getLog(WebUtils.class); + + /** + * The configuration key that replaces a dynamically generated retrieve signature data url. + */ + private final static String RETRIEVE_SIGNATURE_DATA_URL_OVERRIDE_KEY = "retrieve_signature_data_url_override"; + + /** + * Unlike {@link HttpServletResponse#encodeURL(String)} that adds only a + * {@code JSESSIONID} entry to the given url if needed, this method always + * adds the session id (except if already present within the url. + * + * @param url + * The given url. + * @param session + * The {@link HttpSession}. + * @return The given url plus a session id. + */ + public static String addJSessionID(String url, HttpSession session) { + if (url == null) { + return null; + } + if (!StringUtils.containsIgnoreCase(url, ";jsessionid=")) { + url = url + ";jsessionid=" + session.getId(); + LOG.debug("Adding jsessionid " + session.getId()); + } else { + LOG.debug("No need to add a jsessionid."); + } + LOG.debug("Returning url " + url); + return url; + } + + /** + * Unlike {@link HttpServletResponse#encodeURL(String)} that adds only a + * {@code JSESSIONID} entry to the given url if needed, this method always + * adds the session id (except if already present within the url. + * + * @param url + * The given url. + * @param request + * The {@link HttpServletRequest}. + * @return The given url plus a session id. + */ + public static String addJSessionID(String url, HttpServletRequest request) { + return addJSessionID(url, request.getSession()); + } + + /** + * Either dynamically creates locref content url or uses a url provides by the pdf-as + * configuration (key {@code retrieve_signature_data_url_override}). + * @param request The {@link HttpServletRequest}. + * @param response The {@link HttpServletResponse}. + * @return The retrieve signature data url. + */ + public static String buildRetrieveSignatureDataURL(HttpServletRequest request, HttpServletResponse response) { + String override = null; + LOG.debug("Building retrieve signature data url."); + try { + override = SettingsReader.getInstance().getSetting(RETRIEVE_SIGNATURE_DATA_URL_OVERRIDE_KEY, null); + } catch (SettingsException e) { + LOG.error(e); + } + String result; + if (override == null) { + result = WebUtils.addJSessionID(LocalRequestHelper.getLocalContextAddress(request, response) + "/RetrieveSignatureData", request); + } else { + LOG.debug("Override url found: " + override); + result = WebUtils.addJSessionID(override, request); + } + LOG.debug("RetrieveSignatureDataURL = " + result); + return result; + } + +} diff --git a/src/main/java/at/gv/egiz/pdfas/web/helper/SignServletHelper.java b/src/main/java/at/gv/egiz/pdfas/web/helper/SignServletHelper.java index a904ad4..6fc7a1a 100644 --- a/src/main/java/at/gv/egiz/pdfas/web/helper/SignServletHelper.java +++ b/src/main/java/at/gv/egiz/pdfas/web/helper/SignServletHelper.java @@ -20,6 +20,7 @@ import at.gv.egiz.pdfas.framework.SignatorFactory; import at.gv.egiz.pdfas.framework.signator.Signator; import at.gv.egiz.pdfas.impl.output.ByteArrayDataSink; import at.gv.egiz.pdfas.impl.output.FileBasedDataSink; +import at.gv.egiz.pdfas.utils.WebUtils; import at.gv.egiz.pdfas.web.SignSessionInformation; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; @@ -135,7 +136,8 @@ public class SignServletHelper // TODO TR: Web-Applikation verwendet in Loc-Ref-Variante ext. Referenz, um performanter zu sein; // nachfolend auskommentieren, wenn anstatt SwA-Connector LocRef-Connector verwendet wird - URL signature_data_URL = new URL(LocalRequestHelper.getLocalContextAddress(request, response) + "/RetrieveSignatureData"); +// URL signature_data_URL = new URL(WebUtils.addJSessionID(LocalRequestHelper.getLocalContextAddress(request, response) + "/RetrieveSignatureData", request)); + URL signature_data_URL = new URL(WebUtils.buildRetrieveSignatureDataURL(request, response)); String signature_data_url = response.encodeURL(signature_data_URL.toString()); Connector c = ConnectorChooser.chooseWebConnectorForSign(si.connector, si.type, signature_data_url); diff --git a/src/main/java/at/gv/egiz/pdfas/web/helper/SigningTimeHelper.java b/src/main/java/at/gv/egiz/pdfas/web/helper/SigningTimeHelper.java new file mode 100644 index 0000000..673c197 --- /dev/null +++ b/src/main/java/at/gv/egiz/pdfas/web/helper/SigningTimeHelper.java @@ -0,0 +1,83 @@ +package at.gv.egiz.pdfas.web.helper; + +import java.util.Date; + +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.gv.egiz.pdfas.framework.signator.SignatorInformation; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; +import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; +import at.knowcenter.wag.egov.egiz.pdf.EGIZDate; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * This class deals with invalid signing times. + * @author tknall + */ +public final class SigningTimeHelper { + + private SigningTimeHelper() { + } + + private static Integer tolerance = null; + + /** + * The log. + */ + private final static Log LOG = LogFactory.getLog(SigningTimeHelper.class); + + private final static String SIGNING_TIME_TOLERANCE_KEY = "signing_time_tolerance"; + private final static String FORMAT_UTC_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'"; + + public static void checkSigningTimeAgainstHostTime(SignatorInformation si) throws SignatureException { + checkSigningTimeAgainstHostTime(si.getSignSignatureObject()); + } + + public static synchronized void checkSigningTimeAgainstHostTime(SignSignatureObject sso) throws SignatureException { + if (tolerance == null) { + try { + String toleranceString = SettingsReader.getInstance().getSetting(SIGNING_TIME_TOLERANCE_KEY, "-1"); + tolerance = new Integer(Integer.parseInt(toleranceString)); + } catch (NumberFormatException e) { + LOG.warn("Invalid configuration key = " + SIGNING_TIME_TOLERANCE_KEY + ". Disabling signing time check."); + tolerance = new Integer(-1); + } catch (SettingsException e) { + LOG.error("Error reading settings. Disabling signing time check.", e); + tolerance = new Integer(-1); + } + } + if (tolerance.intValue() == -1) { + return; + } + + // signing time + Date signingTime = EGIZDate.parseDateFromString(sso.getDate()); + + // current time + Date currentTime = new Date(); + + // lower limit + Date lowerLimit = new Date(currentTime.getTime() - tolerance.intValue()*1000); + + // upper limit + Date upperLimit = new Date(currentTime.getTime() + tolerance.intValue()*1000); + + String signingTimeString = DateFormatUtils.formatUTC(signingTime, FORMAT_UTC_DATE_PATTERN); + + if (LOG.isDebugEnabled()) { + String lower = DateFormatUtils.formatUTC(lowerLimit, FORMAT_UTC_DATE_PATTERN); + String upper = DateFormatUtils.formatUTC(upperLimit, FORMAT_UTC_DATE_PATTERN); + LOG.debug("Checking if signing time " + signingTimeString + " is valid according to the given time frame [ " + lower + ", " + upper + " ]."); + } + + if (signingTime.before(lowerLimit) || signingTime.after(upperLimit)) { + throw new SignatureException(ErrorCode.INVALID_SIGNING_TIME, "The signing time " + signingTimeString + " is out of the given tolerance of " + tolerance.intValue() + " seconds."); + } + + } + +} -- cgit v1.2.3