From c4efec1daeb50b30d363bb9fb83aec5435dbf2ad Mon Sep 17 00:00:00 2001 From: tknall Date: Mon, 27 Apr 2009 08:16:42 +0000 Subject: New signature layout for new MOCCA bku integrated (etsi-moc-1.1). New architecture implemented that allows different signature layouts for single types of BKUs. git-svn-id: https://joinup.ec.europa.eu/svn/pdf-as/trunk@337 7b5415b0-85f9-ee4d-85bd-d5d0c3b42d1c --- .classpath | 4 +- .project | 6 - .../org.eclipse.wst.common.project.facet.core.xml | 2 +- pom.xml | 2 +- .../at/gv/egiz/pdfas/api/commons/Constants.java | 2 + .../at/gv/egiz/pdfas/exceptions/ErrorCode.java | 5 +- .../egiz/pdfas/framework/ConnectorParameters.java | 147 ++++++++++----------- .../java/at/knowcenter/wag/egov/egiz/PdfAS.java | 2 +- .../egov/egiz/sig/connectors/bku/BKUHelper.java | 71 ++++++++++ .../egiz/sig/connectors/bku/BKUPostConnection.java | 11 ++ .../sig/connectors/bku/DetachedBKUConnector.java | 44 +++--- .../bku/EnvelopedBase64BKUConnector.java | 9 +- .../connectors/moa/DetachedLocRefMOAConnector.java | 8 -- .../moa/EnvelopingBase64MOAConnector.java | 8 -- .../moa/MOASoapWithAttachmentConnector.java | 23 ++-- .../mocca/LocRefDetachedMOCCAConnector.java | 61 ++++++--- .../egiz/sig/connectors/mocca/MOCCAHelper.java | 19 --- .../egiz/sig/sigid/DetachedMOCIdFormatter.java | 12 +- .../wag/egov/egiz/sig/sigkz/SigKZIDHelper.java | 62 ++++++++- .../signaturelayout/SignatureLayoutHandler.java | 21 +++ .../SignatureLayoutHandlerFactory.java | 121 +++++++++++++++++ .../mocca/MOCCASignatureLayout10Handler.java | 24 ++++ .../mocca/OldMOCCASignatureLayoutHandler.java | 24 ++++ .../td/TrustDeskSignatureLayoutHandler.java | 22 +++ .../wag/egov/egiz/web/servlets/DataURLServlet.java | 28 ++-- src/main/resources/DefaultConfiguration.zip | Bin 648796 -> 649973 bytes src/main/webapp/WEB-INF/decorators.xml | 5 + src/main/webapp/css/pdfas-standalone-styles.css | 4 + src/site/changes.xml | 7 +- work/cfg/config.properties | 19 ++- work/cfg/help_text.properties | 4 + work/cfg/log4j.properties | 10 +- .../templates/moc.etsi-moc-1.1.verify.template.xml | 1 + 33 files changed, 578 insertions(+), 210 deletions(-) create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java create mode 100644 src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java create mode 100644 work/templates/moc.etsi-moc-1.1.verify.template.xml diff --git a/.classpath b/.classpath index 471f82e..bc38ea8 100644 --- a/.classpath +++ b/.classpath @@ -3,13 +3,13 @@ - - + + diff --git a/.project b/.project index 1ec8925..28557b9 100644 --- a/.project +++ b/.project @@ -20,11 +20,6 @@ - - edu.umd.cs.findbugs.plugin.eclipse.findbugsBuilder - - - org.eclipse.wst.validation.validationbuilder @@ -34,7 +29,6 @@ org.eclipse.jdt.core.javanature org.maven.ide.eclipse.maven2Nature - edu.umd.cs.findbugs.plugin.eclipse.findbugsNature org.eclipse.wst.common.project.facet.core.nature org.eclipse.wst.common.modulecore.ModuleCoreNature org.eclipse.jem.workbench.JavaEMFNature diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml index 88f9e67..1436c27 100644 --- a/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -1,6 +1,6 @@ - + diff --git a/pom.xml b/pom.xml index 5f89609..ed11916 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ knowcenter pdf-as PDF-AS - 3.0.9-20090319 + 3.0.9-20090417 Amtssignatur fuer elektronische Aktenfuehrung 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 19f7613..4fec0a1 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 @@ -110,6 +110,8 @@ public final class Constants * The name of the directory, where temporary files are stored. */ public static final String TEMP_DIR_NAME = "pdfastmp"; + + public static final String BKU_HEADER_SIGNATURE_LAYOUT = "SignatureLayout"; } 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 f6b5602..c51d10a 100644 --- a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java +++ b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java @@ -20,6 +20,7 @@ public final class ErrorCode public static final int SETTINGS_EXCEPTION = 101; public static final int KZ_SETTING_NOT_FOUND = 102; public static final int NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA = 103; + public static final int INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED = 104; public static final int DOCUMENT_CANNOT_BE_READ = 201; public static final int TEXT_EXTRACTION_EXCEPTION = 202; @@ -44,7 +45,9 @@ public final class ErrorCode 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 INVALID_SIGNING_TIME = 372; + + public static final int BKU_NOT_SUPPORTED = 373; public static final int WEB_EXCEPTION = 330; diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java index a7c5d7a..235a03e 100644 --- a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java +++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java @@ -15,93 +15,84 @@ import java.util.Date; * * @author wprinz */ -public class ConnectorParameters -{ - /** - * The profile Id to get the connector parameters from. - * - *

- * The there are no explicit parameters for the connector in the profile, the - * default parameters are used. - *

- */ - protected String profileId = null; +public class ConnectorParameters { + /** + * The profile Id to get the connector parameters from. + * + *

+ * The there are no explicit parameters for the connector in the profile, the + * default parameters are used. + *

+ */ + protected String profileId = null; - /** - * The signature key identifier to be used or null if it should be read from - * the profile. - * - *

- * Currently this is only used by MOA connectors and identifies the MOA key - * group to be used when signing. If null, the MOA connector reads the key - * from the profile. - *

- */ - protected String signatureKeyIdentifier = null; + /** + * The signature key identifier to be used or null if it should be read from + * the profile. + * + *

+ * Currently this is only used by MOA connectors and identifies the MOA key + * group to be used when signing. If null, the MOA connector reads the key + * from the profile. + *

+ */ + protected String signatureKeyIdentifier = null; - /** - * Tells, if the connector should ask the device to return the hash input - * data. - * - *

- * Note that not all connectors support to return the hash input data - so - * there is no guarantee that the hash value will actually be returned. - *

- */ - protected boolean returnHashInputData = false; + /** + * Tells, if the connector should ask the device to return the hash input + * data. + * + *

+ * Note that not all connectors support to return the hash input data - so + * there is no guarantee that the hash value will actually be returned. + *

+ */ + protected boolean returnHashInputData = false; - /** - * Allows to specify an explicit time of verification. - * - *

- * If null, the device's default behaviour determines the time of - * verification, which is usually the current time. - *

- *

- * The time of verification usually influences the certificate check. E.g. the - * certificate may not be valid at the time of verification. - *

- */ - protected Date verificationTime = null; + /** + * Allows to specify an explicit time of verification. + * + *

+ * If null, the device's default behaviour determines the time of + * verification, which is usually the current time. + *

+ *

+ * The time of verification usually influences the certificate check. E.g. + * the certificate may not be valid at the time of verification. + *

+ */ + protected Date verificationTime = null; - public String getProfileId() - { - return this.profileId; - } + public String getProfileId() { + return this.profileId; + } - public void setProfileId(String profileId) - { - this.profileId = profileId; - } - - public String getSignatureKeyIdentifier() - { - return this.signatureKeyIdentifier; - } + public void setProfileId(String profileId) { + this.profileId = profileId; + } - public void setSignatureKeyIdentifier(String signatureKeyIdentifier) - { - this.signatureKeyIdentifier = signatureKeyIdentifier; - } + public String getSignatureKeyIdentifier() { + return this.signatureKeyIdentifier; + } - public boolean isReturnHashInputData() - { - return this.returnHashInputData; - } + public void setSignatureKeyIdentifier(String signatureKeyIdentifier) { + this.signatureKeyIdentifier = signatureKeyIdentifier; + } - public void setReturnHashInputData(boolean returnHashInputData) - { - this.returnHashInputData = returnHashInputData; - } + public boolean isReturnHashInputData() { + return this.returnHashInputData; + } - public Date getVerificationTime() - { - return this.verificationTime; - } + public void setReturnHashInputData(boolean returnHashInputData) { + this.returnHashInputData = returnHashInputData; + } - public void setVerificationTime(Date verificationTime) - { - this.verificationTime = verificationTime; - } + public Date getVerificationTime() { + return this.verificationTime; + } + + public void setVerificationTime(Date verificationTime) { + this.verificationTime = verificationTime; + } } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java index c56a03e..2073714 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java @@ -96,7 +96,7 @@ public abstract class PdfAS * The current version of the pdf-as library. This version string is logged on every invocation * of the api or the web application. */ - public static final String PDFAS_VERSION = "3.0.9-20090319"; + public static final String PDFAS_VERSION = "3.0.9-20090417"; /** * The key of the strict mode setting. diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java index af155a1..43c9649 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java @@ -9,14 +9,18 @@ import java.security.cert.X509Certificate; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Properties; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.servlet.http.HttpServletRequest; + import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.pdfas.api.commons.Constants; import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException; import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; @@ -582,4 +586,71 @@ public final class BKUHelper }; return dateTimeElement; } + + public static String getBKUIdentifier(Properties parsedResponseProperties) { + + // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser + String bkuServerHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); + + // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl + String bkuUserAgentHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); + + String bkuSignatureLayout = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY); + + log.debug("BKU response header \"user-agent\": " + bkuUserAgentHeader); + log.debug("BKU response header \"server\": " + bkuServerHeader); + log.trace("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\": " + bkuSignatureLayout); + + String result = null; + + if (bkuServerHeader != null) { + result = bkuServerHeader; + } else if (bkuUserAgentHeader != null) { + result = bkuUserAgentHeader; + } else { + log.warn("Unable to find any BKU identifier (neither header value \"user-agent\" nor \"server\".)"); + } + + if (bkuSignatureLayout != null && result != null) { + log.info("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\" found."); + String signatureLayoutData = " " + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "/" + bkuSignatureLayout; + if (!result.endsWith(signatureLayoutData)) { + log.debug("Appending signature layout value \"" + bkuSignatureLayout + "\" to bku identifier."); + result += signatureLayoutData; + } else { + log.debug("Signature layout already encoded in server/user-agent header."); + } + } + + if (result != null) { + log.debug("Returning BKU identifier \"" + result + "\""); + } else { + log.debug("Returning null BKU identifier."); + } + + return result; + } + + public static String getBKUIdentifier(HttpServletRequest request) { + return getBKUIdentifier(getBKUProperties(request)); + } + + public static Properties getBKUProperties(HttpServletRequest request) { + Properties props = new Properties(); + String server = request.getHeader("server"); + String userAgent = request.getHeader("user-agent"); + String signatureLayout = request.getHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT); + if (server != null) { + props.setProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY, server); + } + if (userAgent != null) { + props.setProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY, userAgent); + } + if (signatureLayout != null) { + props.setProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayout); + } + return props; + } + + } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java index b582715..d2cffe8 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java @@ -20,6 +20,7 @@ import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.pdfas.api.commons.Constants; import at.knowcenter.wag.egov.egiz.sig.SignatureData; /** @@ -39,6 +40,11 @@ public final class BKUPostConnection * The response Properties key that identifies the BKU Server header. */ public static final String BKU_SERVER_HEADER_KEY = "BKU-Server-Header"; //$NON-NLS-1$ + + /** + * The response property that declares the signature layout being applied. + */ + public static final String BKU_SIGNATURE_LAYOUT_HEADER_KEY = "BKU-Signature-Layout"; //$NON-NLS-1$ /** * The response Properties key that identifies the BKU User-Agent header. @@ -130,6 +136,11 @@ public final class BKUPostConnection log.warn("BKU response header \"Server\" is empty."); } + Header signatureLayoutHeader = post_method.getResponseHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT); //$NON-NLS-1$ + if (signatureLayoutHeader != null) { + response_properties.setProperty(BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayoutHeader.getValue()); + } + log.debug(post_method.getResponseCharSet()); if (!post_method.getResponseCharSet().equals("UTF-8")) //$NON-NLS-1$ { diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java index 5164771..100f054 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java @@ -21,10 +21,10 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.Connector; import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector; import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces; import at.knowcenter.wag.egov.egiz.sig.connectors.moa.DetachedLocRefMOAConnector; -import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper; -import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter; -import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector; import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; @@ -125,24 +125,20 @@ public class DetachedBKUConnector implements Connector, LocalConnector log.debug("analyzeSignResponse:"); //$NON-NLS-1$ String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); + log.debug("BKU identifier: \"" + bkuIdentifier + "\""); - SignSignatureObject so; - if (MOCCAHelper.isMOCCACCEId(bkuServerHeader == null ? bkuUserAgentHeader : bkuServerHeader)) { - log.debug("Evaluating response as MOCCA response."); - so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter()); - } else { - so = BKUHelper.parseCreateXMLResponse(response_string, new DetachedIdFormatter()); + SignatureLayoutHandler sigLayout; + try { + sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier); + } catch (SettingsException e) { + throw new ConnectorException(e.getErrorCode(), e.getMessage()); } + + SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string); so.response_properties = response_properties; @@ -322,17 +318,29 @@ public class DetachedBKUConnector implements Connector, LocalConnector String verify_request_template = this.environment.getVerifyRequestTemplate(); String xml_content = null; + + // MOA if (SigKZIDHelper.isMOASigned(so)) { log.debug("The signature is MOA signed -> getting XML content from DetachedLocRefMOA connector."); DetachedLocRefMOAConnector moa_conn = new DetachedLocRefMOAConnector(this.environment.getProfile(), "loc ref not needed here"); xml_content = moa_conn.prepareXMLContent(data, so); - } + + // MOCCA + } else if (SigKZIDHelper.isMOCCASigned(so)) { + log.debug("MOCCA signature detected."); + String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id); + log.debug("Algorithm = " + algorithmId); + LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId); + xml_content = mocca_connector.prepareXMLContent(data, so); + } + // TD else { + log.debug("TD signature signature detected."); xml_content = prepareXMLContent(data, so); } - + String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent()); verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl")); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java index f30b4b7..e415e98 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java @@ -360,13 +360,8 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); + log.debug("BKU identifier: \"" + bkuIdentifier + "\""); SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter()); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java index 6ad5b94..b31d1ec 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java @@ -107,14 +107,6 @@ public class DetachedLocRefMOAConnector implements Connector BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); - SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter()); log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java index b309432..a6db63c 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java @@ -218,14 +218,6 @@ public class EnvelopingBase64MOAConnector implements Connector BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); - SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new OldMOAIdFormatter()); log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java index abd2b09..4636e20 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java @@ -115,14 +115,6 @@ public class MOASoapWithAttachmentConnector implements Connector BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); - SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter()); log.debug("analyzeSignResponse finished."); //$NON-NLS-1$ @@ -189,17 +181,24 @@ public class MOASoapWithAttachmentConnector implements Connector String xml_content = null; + // MOA if (SigKZIDHelper.isMOASigned(so)) { log.debug("MOA signature detected."); xml_content = prepareXMLContent(data, so); + + // MOCCA } else if (SigKZIDHelper.isMOCCASigned(so)) { log.debug("MOCCA signature detected."); - LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here"); + String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id); + log.debug("Algorithm = " + algorithmId); + LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId); xml_content = mocca_connector.prepareXMLContent(data, so); + + // TD } else { - log.debug("Generic signature (not MOA/MOCCA) signature detected."); - DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here"); - xml_content = bku_connector.prepareXMLContent(data, so); + log.debug("TD signature signature detected."); + DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here"); + xml_content = bku_connector.prepareXMLContent(data, so); } String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java index c44f34b..b27edde 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java @@ -12,6 +12,7 @@ import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.framework.ConnectorParameters; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.sig.SignatureData; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; @@ -22,6 +23,9 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; import at.knowcenter.wag.egov.egiz.tools.CodingHelper; import at.knowcenter.wag.egov.egiz.tools.FileHelper; @@ -50,8 +54,19 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { * @throws ConnectorException Thrown in case of error. */ public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException { + this(connectorParameters, loc_ref_content, null); + } + + /** + * Constructor that builds the configuration environment for this connector according to the + * given profile. + * @param connectorParameters The connectot parameters. + * @param algorithmId The algorithm idenifier. + * @throws ConnectorException Thrown in case of error. + */ + public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content, String algorithmId) throws ConnectorException { this.params = connectorParameters; - this.environment = new Environment(this.params.getProfileId(), loc_ref_content); + this.environment = new Environment(this.params.getProfileId(), loc_ref_content, algorithmId); } /** @@ -116,15 +131,17 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY); BKUHelper.checkResponseForError(response_string); - // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs - String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY); - String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + bkuUserAgentHeader); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + bkuServerHeader); - - SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter()); + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); + log.debug("BKU identifier: \"" + bkuIdentifier + "\""); + SignatureLayoutHandler sigLayout; + try { + sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier); + } catch (SettingsException e) { + throw new ConnectorException(e.getErrorCode(), e.getMessage()); + } + +// SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter()); + SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string); so.response_properties = response_properties; log.debug("analyzeSignResponse finished."); return so; @@ -275,21 +292,21 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { protected static final String TEMPLATE_FILE_PREFIX = "./templates/moc."; /** - * signing file template sufix + * signing file template suffix */ - protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.request.xml"; + protected static final String SIGN_TEMPLATE_FILE_SUFFIX = ".sign.request.xml"; /** - * verifing template file sufix + * verifing template file suffix */ /* signature verification is not supported by mocca protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml"; */ /** - * verifing file template key sufix + * verifing file template key suffix */ - protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml"; + protected static final String VERIFY_TEMPLATE_SUFFIX = ".verify.template.xml"; /** * The configuration key of the verify request template. @@ -343,13 +360,16 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { protected String cert_alg_ecdsa = null; protected String cert_alg_rsa = null; + + protected String algorithmId = null; /** * Initializes the environment with a given profile. * @param profile The configuration profile. + * @param algorithmId The algorithm identifer. * @throws ConnectorException Thrown in case of an error. */ - public Environment(String profile, String loc_ref_content) throws ConnectorException { + public Environment(String profile, String loc_ref_content, String algorithmId) throws ConnectorException { this.profile = profile; this.loc_ref_content = loc_ref_content; @@ -363,11 +383,16 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY); + if (algorithmId == null) { + this.algorithmId = settings.getValueFromKey("default.moc.algorithm.id"); + } else { + this.algorithmId = algorithmId; + } // SIGN REQUEST // try specific file - String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX; + String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX; log.debug("Trying to load specific sign request file " + sign_request_filename); this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename)); @@ -410,7 +435,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector { // load template file // try specific file - String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_TEMPLATE_SUFIX; + String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX; log.debug("Trying to load specific signature template file " + verify_filename); this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename)); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java index fe23584..7e32230 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java @@ -38,25 +38,6 @@ public final class MOCCAHelper { */ private final static Log log = LogFactory.getLog(MOCCAHelper.class); - /** - * The pattern that identifies a mocca response (that matches the header value "Server" or "User-Agent"). - */ - private final static Pattern MOCCA_PATTERN = Pattern.compile("(citizen-card-environment/\\d+(\\.\\d+) MOCCA[ /].*)|(Jetty(.*))"); - - /** - * Checks if the given header value for "Server" or "User-Agent" respectively indicates that - * the response was from a mocca cce. - * @param cceId The value of the http header "Server" or "User-Agent". - * @see http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung - * @return true if the id points to a mocca response, false if not. - */ - public final static boolean isMOCCACCEId(String cceId) { - if (cceId == null) { - return false; - } - return MOCCA_PATTERN.matcher(cceId).matches(); - } - /** * This method parses the signature creation response of the signature * device mocca. diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java index ae46225..8b9b606 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java @@ -16,17 +16,21 @@ import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; */ public class DetachedMOCIdFormatter implements IdFormatter { - public static final String SIG_ID_PREFIX = "etsi-moc-1.0"; - /** * Key value in property file */ - public static final String SIG_ID_PROPERTY_KEY = "default.moc.algorithm.id"; + private static final String SIG_ID_PROPERTY_KEY = "default.moc.algorithm.id"; /** * The log. */ private static Log log = LogFactory.getLog(DetachedIdFormatter.class); + + private String algorithmId; + + public DetachedMOCIdFormatter(String algorithmId) { + this.algorithmId = algorithmId; + } /** * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[]) @@ -39,7 +43,7 @@ public class DetachedMOCIdFormatter implements IdFormatter { } catch (SettingsException e) { log.error(e.getMessage(), e); } - prefix = StringUtils.defaultIfEmpty(prefix, SIG_ID_PREFIX); + prefix = StringUtils.defaultIfEmpty(this.algorithmId, prefix); StringBuffer formattedIds = new StringBuffer(prefix).append("@").append(ids[0]); return formattedIds.toString(); diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java index 67c5e15..5c3fc07 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java @@ -3,14 +3,22 @@ */ package at.knowcenter.wag.egov.egiz.sig.sigkz; +import java.util.Iterator; +import java.util.Vector; +import java.util.regex.Pattern; + import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.knowcenter.wag.egov.egiz.PdfASID; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter; @@ -95,17 +103,34 @@ public final class SigKZIDHelper * @author tknall */ public static boolean isMOCCASigned(SignSignatureObject so) { - String sig_kz = so.kz; String sig_id = so.id; - if (StringUtils.isEmpty(sig_kz) || StringUtils.isEmpty(sig_id)) { + if (StringUtils.isEmpty(sig_id)) { return false; } String[] ids = sig_id.split("@"); if (ArrayUtils.isEmpty(ids)) { return false; } - String prefix = ids[0]; - return DetachedMOCIdFormatter.SIG_ID_PREFIX.equals(prefix); + String algorithmId = parseAlgorithmId(sig_id); + if (algorithmId == null) { + return false; + } else { + return algorithmId.startsWith("etsi-moc-"); + } + } + + /** + * @author tknall + */ + public static String parseAlgorithmId(String algorithmParameter) { + if (StringUtils.isEmpty(algorithmParameter)) { + return null; + } + String[] ids = algorithmParameter.split("@"); + if (ArrayUtils.isEmpty(ids)) { + return null; + } + return ids[0]; } public static boolean isOldBKU(PdfASID sig_kz, String sig_id) throws ConnectorException @@ -158,5 +183,34 @@ public final class SigKZIDHelper return isOldBKU(kz, sig_id); } + + public static String getAlgorithmId(String bkuIdentifier) throws SettingsException, SettingNotFoundException, ConnectorException { + SettingsReader sr = SettingsReader.getInstance(); + + String base = "signaturelayout.pattern"; + Vector v = sr.getSettingKeys(base); + + Iterator it = v.iterator(); + while (it.hasNext()) { + String subKey = (String) it.next(); + String key = base + "." + subKey; + String value = sr.getSetting(key); + Pattern p = Pattern.compile(value); + if (p.matcher(bkuIdentifier).matches()) { + String algKey = "signaturelayout.algorithm.id." + subKey; + String algValue = sr.getSetting(algKey); + return algValue; + } + } + + if ("true".equalsIgnoreCase(sr.getSetting("signaturelayout.strict", "false"))) { + logger.debug("Enforcing bku support check."); + throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier); + } else { + logger.debug("bku support check disabled."); + return null; + } + + } } diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java new file mode 100644 index 0000000..964908d --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java @@ -0,0 +1,21 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; + +/** + * Considers different signature layout characteristics among different versions of citizen card + * environments. + * @author tknall + */ +public interface SignatureLayoutHandler { + + /** + * This method parses the CreateXMLSignatureResponse given from a certain signature device. + * + * @param xmlResponse The response string. + * @return Returns the parsed signature object. + */ + public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException; + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java new file mode 100644 index 0000000..c56b5f6 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java @@ -0,0 +1,121 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Vector; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.pdfas.exceptions.ErrorCode; +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; + +/** + * Returns instances of signature layout handlers based on given bku + * identifiers. + * + * @author tknall + */ +public class SignatureLayoutHandlerFactory { + + /** + * Prefix of configuration keys defining bku identifiers for a signature layout. + */ + private final static String SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN = "signaturelayout.pattern"; + + /** + * Prefix of configuration keys defining implementations of signature layout handlers. + * @see SignatureLayoutHandler + */ + private final static String SIGNATURE_LAYOUT_CONFIG_KEY_IMPL = "signaturelayout.implementation"; + + /** + * A map holding instantiated signature layout implementations (for performance reasons). + */ + private final static Map instances = Collections.synchronizedMap(new HashMap()); + + /** + * The log. + */ + private static Log log = LogFactory.getLog(SignatureLayoutHandlerFactory.class); + + /** + * Returns an instance of a signature layout handler based on the given bku identifier. + * @param bkuIdentifier The bku identifier (e.g. citizen-card-environment/1.2 MOCCA/1.1.1). + * @return An implementation of a signature layout handler. + * @throws ConnectorException Thrown in case of an error finding a match within the configuration with the given bku identifier. + * @throws SettingsException Thrown in case of an error within the configuration. + */ + public static SignatureLayoutHandler getSignatureLayoutHandlerInstance(String bkuIdentifier) throws ConnectorException, SettingsException { + SignatureLayoutHandler signatureLayoutHandler = (SignatureLayoutHandler) instances.get(bkuIdentifier); + + if (signatureLayoutHandler == null) { + SettingsReader sr = SettingsReader.getInstance(); + + Vector v = sr.getSettingKeys(SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN); + String implValue = null; + + Iterator it = v.iterator(); + try { + while (it.hasNext()) { + String subKey = (String) it.next(); + String key = SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN + "." + subKey; + String value = sr.getSetting(key); + Pattern p = Pattern.compile(value); + if (p.matcher(bkuIdentifier).matches()) { + String implKey = SIGNATURE_LAYOUT_CONFIG_KEY_IMPL + "." + subKey; + implValue = sr.getSetting(implKey); + } + } + } catch (SettingNotFoundException e) { + throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, e.getMessage()); + } + + if (implValue == null) { + throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier); + } + + log.debug("Trying to instantiate SignatureLayoutHandler \"" + implValue + "\"."); + + try { + Class clazz = Class.forName(implValue); + Object obj = clazz.newInstance(); + if (!(obj instanceof SignatureLayoutHandler)) { + throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Invalid signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\"."); + } + signatureLayoutHandler = (SignatureLayoutHandler) obj; + } catch (InstantiationException e) { + throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Error instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\"."); + } catch (IllegalAccessException e) { + throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Illegal access instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\"."); + } catch (ClassNotFoundException e) { + throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Unable to find signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\"."); + } + + log.debug("SignatureLayoutHandler successfully instantiated."); + instances.put(bkuIdentifier, signatureLayoutHandler); + } else { + log.trace("SignatureLayoutHandler has already been instantiated. Returning old instance."); + } + + return signatureLayoutHandler; + + } + + /** + * Verifies that the bku is supported trying to match the given bku identifier. + * @param bkuIdentifier The bku identifier (e.g. citizen-card-environment/1.2 MOCCA/1.1.1). + * @throws ConnectorException Thrown in case of an error (e.g. bku not supported). + * @throws SettingsException Thrown in case of an error within the configuration. + */ + public static void verifyBKUSupport(String bkuIdentifier) throws ConnectorException, SettingsException { + getSignatureLayoutHandlerInstance(bkuIdentifier); + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java new file mode 100644 index 0000000..0913b49 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java @@ -0,0 +1,24 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper; +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; + +/** + * Implementation of a signature layout handler for the first release of mocca. + * @author tknall + */ +public class MOCCASignatureLayout10Handler implements SignatureLayoutHandler { + + private final static String ALGORITHM_ID = "etsi-moc-1.1"; + + /** + * Parses the given xmlResponse with respect to the specific signature layout of mocca. + */ + public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException { + return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID)); + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java new file mode 100644 index 0000000..958370e --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java @@ -0,0 +1,24 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper; +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; + +/** + * Implementation of a signature layout handler for the beta version of mocca. + * @author tknall + */ +public class OldMOCCASignatureLayoutHandler implements SignatureLayoutHandler { + + private final static String ALGORITHM_ID = "etsi-moc-1.0"; + + /** + * Parses the given xmlResponse with respect to the specific signature layout of mocca. + */ + public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException { + return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID)); + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java new file mode 100644 index 0000000..5d6eb96 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java @@ -0,0 +1,22 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.td; + +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject; +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; + +/** + * Implementation of a signature layout handler for trustDesk basic. + * @author tknall + */ +public class TrustDeskSignatureLayoutHandler implements SignatureLayoutHandler { + + /** + * Parses the given xmlResponse with respect to the specific signature layout of trustDesk basic. + */ + public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException { + return BKUHelper.parseCreateXMLResponse(xmlResponse, new DetachedIdFormatter()); + } + +} diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java index 7947d90..7cf762e 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java @@ -42,13 +42,17 @@ import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException; import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException; import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorChooser; import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector; +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper; import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler; +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory; import at.knowcenter.wag.egov.egiz.web.FormFields; import at.knowcenter.wag.egov.egiz.web.LocalRequest; import at.knowcenter.wag.egov.egiz.web.LocalRequestHelper; @@ -200,7 +204,17 @@ public class DataURLServlet extends HttpServlet log.trace("processSign"); String xml_response = retrieveXMLResponse(request); + Properties response_properties = BKUHelper.getBKUProperties(request); + String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties); + log.debug("BKU identifier: \"" + bkuIdentifier + "\""); + + try { + SignatureLayoutHandlerFactory.verifyBKUSupport(bkuIdentifier); + } catch (SettingsException e) { + throw new ConnectorException(e.getErrorCode(), e.getMessage()); + } + if (isNullResponse(xml_response)) { log.debug("Received a NullOperationResponse -> answering with the first request."); //$NON-NLS-1$ @@ -210,12 +224,6 @@ public class DataURLServlet extends HttpServlet log.debug("There are still requests to be performed -> answering with request."); //$NON-NLS-1$ - // TODO[tknall] Parse user agent's cce type and version in order to prevent unsupported cces from signing pdfs - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl - log.debug("BKU response header \"user-agent\" header: " + request.getHeader("User-Agent")); - // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser - log.debug("BKU response header \"server\" header: " + request.getHeader("Server")); - LocalRequest local_request = si.localRequest; String request_string = local_request.getRequestString(); @@ -229,16 +237,8 @@ public class DataURLServlet extends HttpServlet { log.debug("Received a normal response -> storing the response."); //$NON-NLS-1$ - Properties response_properties = new Properties(); response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xml_response); - String userAgent = request.getHeader("User-Agent"); - if (userAgent != null) { - response_properties.setProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY, userAgent); - } else { - log.warn("BKU request/response header \"User-Agent\" is empty."); - } - si.response_properties = response_properties; log.debug("All requests have been processed -> processing the responses."); //$NON-NLS-1$ diff --git a/src/main/resources/DefaultConfiguration.zip b/src/main/resources/DefaultConfiguration.zip index efc2604..40af0ed 100644 Binary files a/src/main/resources/DefaultConfiguration.zip and b/src/main/resources/DefaultConfiguration.zip differ diff --git a/src/main/webapp/WEB-INF/decorators.xml b/src/main/webapp/WEB-INF/decorators.xml index a88892d..352a902 100644 --- a/src/main/webapp/WEB-INF/decorators.xml +++ b/src/main/webapp/WEB-INF/decorators.xml @@ -9,6 +9,11 @@ /*.pdf + /* diff --git a/src/main/webapp/css/pdfas-standalone-styles.css b/src/main/webapp/css/pdfas-standalone-styles.css index 9131c0d..aa9459c 100644 --- a/src/main/webapp/css/pdfas-standalone-styles.css +++ b/src/main/webapp/css/pdfas-standalone-styles.css @@ -5,3 +5,7 @@ table.pdfassignature td.pdfaslabel { table.pdfassignature td.pdfasvalue { font-size: 0.9em; } + +pre.pdfasnt { + font-size: 0.8em; +} diff --git a/src/site/changes.xml b/src/site/changes.xml index bc477dc..1b983a7 100644 --- a/src/site/changes.xml +++ b/src/site/changes.xml @@ -1,4 +1,4 @@ - + @@ -13,6 +13,11 @@ --> + + New signature layout for new MOCCA bku integrated (etsi-moc-1.1). + New architecture implemented that allows different signature layouts for single types of bkus. + + Layout for webapplication adjusted for IE. diff --git a/work/cfg/config.properties b/work/cfg/config.properties index 2fac9ad..9ac5c4b 100644 --- a/work/cfg/config.properties +++ b/work/cfg/config.properties @@ -63,7 +63,7 @@ external_corrector_timeout=15000 # In beiden Fällen wird check_old_textual_sigs berücksichtigt. check_document=true -#VerificationFilterPatameters +#VerificationFilterParameters # modify only if you really know the algorithms binary_only=false assume_only_signature_blocks=false @@ -78,6 +78,21 @@ default.moa.algorithm.id=etsi-bka-moa-1.0 # MOCCA Algorithm - Kennzeichnung default.moc.algorithm.id=etsi-moc-1.0 + +# SIGNATURE LAYOUTS +# signature layout for mocca without any signature layout declaration +signaturelayout.pattern.moc.none=^((citizen-card-environment/1\\.2 MOCCA(?!.*SignatureLayout/).*)|(Jetty\\(6\\.1\\.10\\)))$ +signaturelayout.implementation.moc.none=at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca.OldMOCCASignatureLayoutHandler + +# signature layout 1.0 for mocca +signaturelayout.pattern.moc.10=^citizen-card-environment/1\\.2 MOCCA/.*SignatureLayout/1\\.0.*$ +signaturelayout.implementation.moc.10=at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca.MOCCASignatureLayout10Handler + +# signature layout for supported trustDesk basic versions +signaturelayout.pattern.tdb=^citizen-card-environment/1\\.2 trustDeskbasic((-OSX)|(-Linux))?/((2\\.7\\.\\d)|(2\\.8\\.\\d))$ +signaturelayout.implementation.tdb=at.knowcenter.wag.egov.egiz.sig.signaturelayout.td.TrustDeskSignatureLayoutHandler + + # MOA Detached Signieren aus Konsole möglich - zurzeit möglich nur mit BKU moa.sign.console.detached.enabled=false @@ -530,7 +545,7 @@ sig_obj.SIGNATURBLOCK_EN.table.info.6=SIG_ID-cv ################################################################################################### # PROFIL: Unsichtbarer Signaturblock -#sig_obj.INVISIBLE.description=Unsichtbarer Signaturblock +sig_obj.INVISIBLE.description=Unsichtbarer Signaturblock # Derzeit muss noch mindestens ein sig_obj.XXX.key.XXX Schluessel angegeben werden. sig_obj.INVISIBLE.key.SIG_VALUE=foo diff --git a/work/cfg/help_text.properties b/work/cfg/help_text.properties index ca06f3e..78d1644 100644 --- a/work/cfg/help_text.properties +++ b/work/cfg/help_text.properties @@ -13,6 +13,7 @@ error.code.100=Der Konfigurationsschl error.code.101=Die Konfigurationsdatei konnte nicht geladen werden. error.code.102=Das Signaturprofil enthält keinen Bericht für die Kennzeichnung. error.code.103=Für den PDA/A Modus muss eine einbettbare TrueType-Schrift konfiguriert sein. +error.code.104=Die Konfiguration der SignaturLayout-Implementierung fehlt oder ist ungültig. #PDFDocumentException error.code.201=Das PDF Dokument kann nicht gelesen werden, oder die Datei hat ein falsches Format. @@ -68,6 +69,9 @@ error.code.371=Dieses Signaturger # Workaround for ITS(Mac/Linux) bug concerning the signing time. error.code.372=Der Signaturzeitpunkt ist ungültig. Stellen Sie bitte sicher, dass die Systemzeit sowie die Zeitzoneneinstellung Ihres Rechners korrekt sind sowie dass Sie die aktuellste Version Ihrer Bürgerkartenumgebung verwenden. +# Unsupported BKU +error.code.373=Dieses Signaturgerät wird nicht unterstützt. + #NormalizeException error.code.400=Das Normalisierungsmodul kann nicht initialisiert werden. diff --git a/work/cfg/log4j.properties b/work/cfg/log4j.properties index e470745..f6bb9e4 100644 --- a/work/cfg/log4j.properties +++ b/work/cfg/log4j.properties @@ -1,17 +1,17 @@ log4j.rootLogger = WARN, CONSOLE, ROLLINGFILE # DETAIL LEVELS -#log4j.logger.at.gv.egiz.pdfas = TRACE -#log4j.logger.at.knowcenter = TRACE -log4j.logger.at.gv.egiz.pdfas = INFO -log4j.logger.at.knowcenter = INFO +log4j.logger.at.gv.egiz.pdfas = DEBUG +log4j.logger.at.knowcenter = DEBUG +#log4j.logger.at.gv.egiz.pdfas = INFO +#log4j.logger.at.knowcenter = INFO log4j.logger.org.apache.commons.httpclient.HttpMethodBase = ERROR # CONSOLE log4j.appender.CONSOLE = org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern = [%-5p@%d{dd.MM.yyyy HH:mm:ss}] %c:%M:%L - %m%n -log4j.appender.CONSOLE.threshold = ERROR +#log4j.appender.CONSOLE.threshold = ERROR log4j.appender.CONSOLE.Target = System.out # ROLLINGFILE diff --git a/work/templates/moc.etsi-moc-1.1.verify.template.xml b/work/templates/moc.etsi-moc-1.1.verify.template.xml new file mode 100644 index 0000000..fe166ed --- /dev/null +++ b/work/templates/moc.etsi-moc-1.1.verify.template.xml @@ -0,0 +1 @@ +DigestValueSignedDataReplaceDigestValueSignedPropertiesReplaceSignatureValueReplaceX509CertificateReplaceSigningTimeReplaceDigestValueX509CertificateReplaceX509IssuerNameReplaceX509SerialNumberReplaceMimeTypeReplace \ No newline at end of file -- cgit v1.2.3