From c0374673df99e32bbe41ebfc3cde58630d853ede Mon Sep 17 00:00:00 2001 From: kstranacher_eGovL Date: Fri, 21 Dec 2012 12:37:45 +0000 Subject: Integration TSL library. git-svn-id: https://joinup.ec.europa.eu/svn/moa-idspss/trunk@1301 d688527b-c9ab-4aba-bd8d-4036d912da1d --- spss/handbook/clients/api/.classpath | 1 - spss/handbook/clients/webservice/.classpath | 1 - .../serverlib/.settings/org.eclipse.jdt.core.prefs | 16 +- .../.settings/org.eclipse.wst.common.component | 7 +- .../org.eclipse.wst.common.project.facet.core.xml | 4 +- spss/server/serverlib/pom.xml | 40 ++ .../gv/egovernment/moa/spss/api/SPSSFactory.java | 7 +- .../moa/spss/api/common/SignerInfo.java | 10 + .../moa/spss/api/common/TSLConfiguration.java | 74 ++ .../moa/spss/api/impl/SPSSFactoryImpl.java | 4 +- .../moa/spss/api/impl/SignerInfoImpl.java | 15 + .../moa/spss/api/impl/TSLConfigurationImpl.java | 87 +++ .../moa/spss/api/xmlbind/ResponseBuilderUtils.java | 10 +- .../xmlbind/VerifyCMSSignatureResponseBuilder.java | 4 +- .../xmlbind/VerifyXMLSignatureResponseBuilder.java | 3 +- .../server/config/ConfigurationPartsBuilder.java | 157 +++- .../spss/server/config/ConfigurationProvider.java | 66 +- .../moa/spss/server/config/TrustProfile.java | 21 + .../moa/spss/server/init/SystemInitializer.java | 118 ++- .../spss/server/invoke/IaikExceptionMapper.java | 30 +- .../invoke/VerifyCMSSignatureResponseBuilder.java | 4 +- .../invoke/VerifyXMLSignatureResponseBuilder.java | 28 +- .../invoke/XMLSignatureVerificationInvoker.java | 42 +- .../moa/spss/tsl/config/Configurator.java | 128 ++++ .../moa/spss/tsl/connector/TSLConnector.java | 718 +++++++++++++++++++ .../spss/tsl/connector/TSLConnectorInterface.java | 95 +++ .../exception/MitigatedTSLSecurityException.java | 17 + .../moa/spss/tsl/timer/TSLUpdaterTimerTask.java | 150 ++++ .../moa/spss/tsl/utils/CertificateReader.java | 155 ++++ .../egovernment/moa/spss/tsl/utils/Mitigation.java | 15 + .../spss/tsl/utils/TSLEUImportFromFileContext.java | 140 ++++ .../moa/spss/tsl/utils/TSLEvaluationContext.java | 134 ++++ .../spss/tsl/utils/TSLImportFromFileContext.java | 788 +++++++++++++++++++++ .../properties/spss_messages_de.properties | 15 +- spss/server/serverws/.classpath | 38 +- .../.settings/org.eclipse.wst.common.component | 3 + .../org.eclipse.wst.common.project.facet.core.xml | 4 +- spss/server/serverws/pom.xml | 4 + spss/server/tools/.classpath | 21 +- 39 files changed, 3052 insertions(+), 122 deletions(-) create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/TSLConfiguration.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/TSLConfigurationImpl.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/config/Configurator.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnector.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnectorInterface.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/exception/MitigatedTSLSecurityException.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/timer/TSLUpdaterTimerTask.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/CertificateReader.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/Mitigation.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEUImportFromFileContext.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEvaluationContext.java create mode 100644 spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java (limited to 'spss') diff --git a/spss/handbook/clients/api/.classpath b/spss/handbook/clients/api/.classpath index 280649336..0fb87fef8 100644 --- a/spss/handbook/clients/api/.classpath +++ b/spss/handbook/clients/api/.classpath @@ -29,6 +29,5 @@ - \ No newline at end of file diff --git a/spss/handbook/clients/webservice/.classpath b/spss/handbook/clients/webservice/.classpath index 280649336..0fb87fef8 100644 --- a/spss/handbook/clients/webservice/.classpath +++ b/spss/handbook/clients/webservice/.classpath @@ -29,6 +29,5 @@ - \ No newline at end of file diff --git a/spss/server/serverlib/.settings/org.eclipse.jdt.core.prefs b/spss/server/serverlib/.settings/org.eclipse.jdt.core.prefs index 4f0fe7d5d..7dfadf4fe 100644 --- a/spss/server/serverlib/.settings/org.eclipse.jdt.core.prefs +++ b/spss/server/serverlib/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,13 @@ +#Tue Dec 18 14:23:26 CET 2012 eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.4 -org.eclipse.jdt.core.compiler.compliance=1.4 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning -org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.source=1.4 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/spss/server/serverlib/.settings/org.eclipse.wst.common.component b/spss/server/serverlib/.settings/org.eclipse.wst.common.component index 2ae51a94e..feb12899a 100644 --- a/spss/server/serverlib/.settings/org.eclipse.wst.common.component +++ b/spss/server/serverlib/.settings/org.eclipse.wst.common.component @@ -1,7 +1,10 @@ - + + + + - \ No newline at end of file + diff --git a/spss/server/serverlib/.settings/org.eclipse.wst.common.project.facet.core.xml b/spss/server/serverlib/.settings/org.eclipse.wst.common.project.facet.core.xml index eb7de6322..3679d8190 100644 --- a/spss/server/serverlib/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/spss/server/serverlib/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -3,5 +3,5 @@ - - \ No newline at end of file + + diff --git a/spss/server/serverlib/pom.xml b/spss/server/serverlib/pom.xml index ced3dacc2..481464f63 100644 --- a/spss/server/serverlib/pom.xml +++ b/spss/server/serverlib/pom.xml @@ -141,6 +141,46 @@ moa-spss-tools test + + + iaik + iaik_tsl + + + + iaik + iaik.util + + + + iaik + iaik.xsect + + + + javax.xml.bind + jaxb-api + + + + com.sun.xml.bind + jaxb-impl + + + + org.xerial + sqlite-jdbc + + + + iaik + iaik.jsse + + + + + + diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/SPSSFactory.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/SPSSFactory.java index 54b166a99..fbf40be88 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/SPSSFactory.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/SPSSFactory.java @@ -1008,6 +1008,8 @@ public abstract class SPSSFactory { * @param publicAuthorityID The identification of the public authority * (if publicAuthority is true). May be * null. + * @param sscd true, if the TSL check verifies the + * signature based on a SSDC, otherwise false. * @return The SignerInfo containing the above data. * * @pre signerCertSubjectName != null @@ -1018,8 +1020,9 @@ public abstract class SPSSFactory { X509Certificate signerCertificate, boolean qualifiedCertificate, boolean publicAuthority, - String publicAuthorityID); - + String publicAuthorityID, + boolean sscd); + /** * Create a new X509IssuerSerial object. * diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/SignerInfo.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/SignerInfo.java index 2e00c3142..7a1942214 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/SignerInfo.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/SignerInfo.java @@ -48,6 +48,16 @@ public interface SignerInfo { * false. */ public boolean isQualifiedCertificate(); + + + /** + * Checks, whether the signature is based on a SSCD. + * + * @return true, if the signature is based on a SSCD, otherwise + * false. + */ + public boolean isSSCD(); + /** * Checks, whether the certificate contained in this object is a * public authority certificate. diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/TSLConfiguration.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/TSLConfiguration.java new file mode 100644 index 000000000..fd7d38217 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/common/TSLConfiguration.java @@ -0,0 +1,74 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.api.common; + +import java.util.Date; + + +/** + * Contains TSL configuration information. + * + * @author kstranacher + */ +public interface TSLConfiguration { + + /** Default URL of EU TSL */ + public String DEFAULT_EU_TSL_URL = "https://ec.europa.eu/information_society/policy/esignature/trusted-list/tl-mp.xml"; + + /** Default period (1day=86400000 msec) for update schedule */ + public String DEFAULT_UPDATE_SCHEDULE_PERIOD = "86400000"; + + /** Default start time (2:00 AM) for update schedule */ + public String DEFAULT_UPDATE_SCHEDULE_STARTTIME = "02:00:00"; + + public String DEFAULT_WORKING_DIR = "tslworking"; + + /** + * Gets the EU TSL URL. + * + * @return The EU TSL URL. + */ + public String getEuTSLUrl(); + + /** + * + * @return + */ + public Date getUpdateScheduleStartTime(); + + /** + * + * @return + */ + public long getUpdateSchedulePeriod(); + + /** + * + * @return + */ + public String getWorkingDirectory(); + + +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SPSSFactoryImpl.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SPSSFactoryImpl.java index cc7b8d00d..a23a1d98f 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SPSSFactoryImpl.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SPSSFactoryImpl.java @@ -574,12 +574,14 @@ public class SPSSFactoryImpl extends SPSSFactory { X509Certificate signerCertificate, boolean qualifiedCertificate, boolean publicAuthority, - String publicAuthorityID) { + String publicAuthorityID, + boolean sscd) { SignerInfoImpl signerInfo = new SignerInfoImpl(); signerInfo.setSignerCertificate(signerCertificate); signerInfo.setQualifiedCertificate(qualifiedCertificate); signerInfo.setPublicAuthority(publicAuthority); signerInfo.setPublicAuhtorityID(publicAuthorityID); + signerInfo.setSSCD(sscd); return signerInfo; } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SignerInfoImpl.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SignerInfoImpl.java index bdc9b45d2..56a9004fc 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SignerInfoImpl.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/SignerInfoImpl.java @@ -47,6 +47,8 @@ public class SignerInfoImpl implements SignerInfo { /** The public authority ID of the signerCertificate. */ private String publicAuthorityID; + /** Determines, whether the signature is based on an SSCD */ + private boolean sscd; /** * Sets the signer certificate. * @@ -74,6 +76,19 @@ public class SignerInfoImpl implements SignerInfo { return qualifiedCertificate; } + /** + * Sets, whether the signature is based on an SSCS or not. + * + * @param sscd Is true, if the signature is + * based on an SSCD, otherwise false. + */ + public void setSSCD(boolean sscd) { + this.sscd = sscd; + } + public boolean isSSCD() { + return sscd; + } + /** * Sets, whether the certificate contained in this object is an * e-government certificate or not. diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/TSLConfigurationImpl.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/TSLConfigurationImpl.java new file mode 100644 index 000000000..15d66614e --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/impl/TSLConfigurationImpl.java @@ -0,0 +1,87 @@ +/* + * Copyright 2003 Federal Chancellery Austria + * MOA-SPSS has been developed in a cooperation between BRZ, the Federal + * Chancellery Austria - ICT staff unit, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.spss.api.impl; + +import java.util.Date; + +import at.gv.egovernment.moa.spss.api.common.TSLConfiguration; + +/** + * Default implementation of TSLConfiguration. + * + * @author kstranacher + */ +public class TSLConfigurationImpl implements TSLConfiguration { + + + + /** The EU TSL URL. */ +// private String euTSLUrl; + + /** update period in milliseconds */ + private long updateSchedulePeriod; + + /** Time of the first update */ + private Date updateScheduleStartTime; + + /** Working directory */ + private String workingDirectory; + + public String getEuTSLUrl() { + return this.DEFAULT_EU_TSL_URL; + } + + public long getUpdateSchedulePeriod() { + return this.updateSchedulePeriod; + } + + public Date getUpdateScheduleStartTime() { + return this.updateScheduleStartTime; + } + + public String getWorkingDirectory() { + return this.workingDirectory; + } + +// public void setEuTSLUrl(String euTSLUrl) { +// this.euTSLUrl = euTSLUrl; +// } + + public void setUpdateSchedulePeriod(long updateSchedulePeriod) { + this.updateSchedulePeriod = updateSchedulePeriod; + } + + public void setUpdateScheduleStartTime(Date updateScheduleStartTime) { + this.updateScheduleStartTime = updateScheduleStartTime; + } + + public void setWorkingDirectory(String workingDirectory) { + this.workingDirectory = workingDirectory; + } + + + + +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/ResponseBuilderUtils.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/ResponseBuilderUtils.java index 6e4389e1d..a228a0db8 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/ResponseBuilderUtils.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/ResponseBuilderUtils.java @@ -118,7 +118,8 @@ class ResponseBuilderUtils { X509Certificate cert, boolean isQualified, boolean isPublicAuthority, - String publicAuthorityID) + String publicAuthorityID, + boolean isSSCD) throws MOAApplicationException { Element signerInfoElem = response.createElementNS(MOA_NS_URI, "SignerInfo"); @@ -140,6 +141,10 @@ class ResponseBuilderUtils { isQualified ? response.createElementNS(MOA_NS_URI, "QualifiedCertificate") : null; + Element sscdElem = + isSSCD + ? response.createElementNS(MOA_NS_URI, "SecureSignatureCreationDevice") + : null; Element publicAuthorityElem = isPublicAuthority ? response.createElementNS(MOA_NS_URI, "PublicAuthority") @@ -186,6 +191,9 @@ class ResponseBuilderUtils { publicAuthorityElem.appendChild(codeElem); } } + if (isSSCD) { + x509DataElem.appendChild(sscdElem); + } signerInfoElem.appendChild(x509DataElem); root.appendChild(signerInfoElem); } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyCMSSignatureResponseBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyCMSSignatureResponseBuilder.java index 2fee98fdd..1971096a8 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyCMSSignatureResponseBuilder.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyCMSSignatureResponseBuilder.java @@ -99,13 +99,15 @@ public class VerifyCMSSignatureResponseBuilder { CheckResult signatureCheck = responseElement.getSignatureCheck(); CheckResult certCheck = responseElement.getCertificateCheck(); + // TODO CMS TSL check ResponseBuilderUtils.addSignerInfo( responseDoc, responseElem, signerInfo.getSignerCertificate(), signerInfo.isQualifiedCertificate(), signerInfo.isPublicAuthority(), - signerInfo.getPublicAuhtorityID()); + signerInfo.getPublicAuhtorityID(), + false); ResponseBuilderUtils.addCodeInfoElement( responseDoc, diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyXMLSignatureResponseBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyXMLSignatureResponseBuilder.java index d028ef5fb..0d3e0c18e 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyXMLSignatureResponseBuilder.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/api/xmlbind/VerifyXMLSignatureResponseBuilder.java @@ -97,7 +97,8 @@ public class VerifyXMLSignatureResponseBuilder { response.getSignerInfo().getSignerCertificate(), response.getSignerInfo().isQualifiedCertificate(), response.getSignerInfo().isPublicAuthority(), - response.getSignerInfo().getPublicAuhtorityID()); + response.getSignerInfo().getPublicAuhtorityID(), + response.getSignerInfo().isSSCD()); // add HashInputData elements responseData = response.getHashInputDatas(); diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java index 7381c4733..09f496c74 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationPartsBuilder.java @@ -1,5 +1,4 @@ /* - * Copyright 2003 Federal Chancellery Austria * MOA-SPSS has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * @@ -43,6 +42,8 @@ import java.net.MalformedURLException; import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -50,6 +51,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import javax.xml.bind.DatatypeConverter; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Attr; @@ -59,9 +61,12 @@ import org.xml.sax.SAXException; import at.gv.egovernment.moa.logging.LogMsg; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.api.common.TSLConfiguration; +import at.gv.egovernment.moa.spss.api.impl.TSLConfigurationImpl; import at.gv.egovernment.moa.spss.util.MessageProvider; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.StringUtils; import at.gv.egovernment.moa.util.XPathUtils; /** @@ -195,12 +200,6 @@ public class ConfigurationPartsBuilder { + CONF + "RevocationChecking/" + CONF + "Archiving/" + CONF + "EnableArchiving"; - private static final String ENABLE_EUTSL_XPATH = - ROOT + CONF + "SignatureVerification/" - + CONF + "CertificateValidation/" - + CONF + "PathValidation/" - + CONF + "TrustProfile/" - + CONF + "EUTSL"; private static final String CRL_ARCHIVE_DURATION_XPATH = ROOT + CONF + "SignatureVerification/" + CONF + "CertificateValidation/" @@ -238,6 +237,11 @@ public class ConfigurationPartsBuilder { private static final String PERMIT_FILE_URIS_XPATH = ROOT + CONF + "SignatureVerification/" + CONF + "PermitFileURIs"; + + private static final String TSL_CONFIGURATION_XPATH = + ROOT + CONF + "SignatureVerification/" + + CONF + "CertificateValidation/" + + CONF + "TSLConfiguration/"; // // default values for configuration parameters // @@ -1043,9 +1047,11 @@ public class ConfigurationPartsBuilder { String id = getElementValue(profileElem, CONF + "Id", null); String trustAnchorsLocStr = getElementValue(profileElem, CONF + "TrustAnchorsLocation", null); String signerCertsLocStr = getElementValue(profileElem, CONF + "SignerCertsLocation", null); - String sTSLenabled = getElementValue(getConfigElem(), ENABLE_EUTSL_XPATH, null); - //System.out.println("sTSLenabled: " + sTSLenabled); - boolean tslEnabled = Boolean.valueOf(sTSLenabled).booleanValue(); + Element eutslElem = (Element) XPathUtils.selectSingleNode(profileElem, CONF + "EUTSL"); + boolean tslEnabled = false; + if (eutslElem != null) //EUTSL element found --> TSL enabled + tslEnabled = true; + String countries = getElementValue(profileElem, CONF + "EUTSL" + "/" + CONF + "CountrySelection", null); URI trustAnchorsLocURI = null; @@ -1103,10 +1109,6 @@ public class ConfigurationPartsBuilder { } } -// System.out.println("ID: " + id); -// System.out.println("Enable EUTSL: " + tslEnabled); -// System.out.println("Countries: " + countries); - signerCertsLocStr = (signerCertsLocURI != null) ? signerCertsLocURI.toString() : null; TrustProfile profile = new TrustProfile(id, trustAnchorsLocURI.toString(), signerCertsLocStr, tslEnabled, countries); trustProfiles.put(id, profile); @@ -1234,6 +1236,18 @@ public class ConfigurationPartsBuilder { warnings.add(txt); } + /** + * Log a debug message. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void debug(String message) { + Logger.debug(new LogMsg(message)); + + } + /** * Log a warning. * @@ -1250,6 +1264,37 @@ public class ConfigurationPartsBuilder { warnings.add(txt); } + /** + * Log an error. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void error(String messageId, Object[] args) { + MessageProvider msg = MessageProvider.getInstance(); + String txt = msg.getMessage(messageId, args); + + Logger.error(new LogMsg(txt)); + warnings.add(txt); + } + + /** + * Log an error. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @param t An exception being the cause of the warning. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void error(String messageId, Object[] args, Throwable t) { + MessageProvider msg = MessageProvider.getInstance(); + String txt = msg.getMessage(messageId, args); + + Logger.error(new LogMsg(txt), t); + warnings.add(txt); + } + /** * Returns whether revocation information should be archived. * @@ -1375,6 +1420,89 @@ public class ConfigurationPartsBuilder { return Boolean.valueOf(permitFileURIs).booleanValue(); } + /** + * Returns the TSL configuration from the config file + * @return + */ + public TSLConfiguration getTSLConfiguration() { + TSLConfigurationImpl tslconfiguration = new TSLConfigurationImpl(); + + +// String euTSLUrl = getElementValue(getConfigElem(), TSL_CONFIGURATION_XPATH + CONF + "EUTSLUrl", null); +// if (StringUtils.isEmpty(euTSLUrl)) { +// warn("config.39", new Object[] { "EUTSL", euTSLUrl }); +// return null; +// } + + String updateSchedulePeriod = getElementValue(getConfigElem(), TSL_CONFIGURATION_XPATH + CONF + "UpdateSchedule/" + CONF + "Period" , null); + + if (StringUtils.isEmpty(updateSchedulePeriod)) { + updateSchedulePeriod = TSLConfiguration.DEFAULT_UPDATE_SCHEDULE_PERIOD; + warn("config.39", new Object[] { "UpdateSchedule/Period", updateSchedulePeriod }); + } + + String updateScheduleStartTime = getElementValue(getConfigElem(), TSL_CONFIGURATION_XPATH + CONF + "UpdateSchedule/" + CONF + "StartTime", null); + if (StringUtils.isEmpty(updateScheduleStartTime)) { + updateScheduleStartTime = TSLConfiguration.DEFAULT_UPDATE_SCHEDULE_STARTTIME; + warn("config.39", new Object[] { "UpdateSchedule/StartTime", updateScheduleStartTime }); + + } + + String workingDirectoryStr = getElementValue(getConfigElem(), TSL_CONFIGURATION_XPATH + CONF + "WorkingDirectory", null); + if (StringUtils.isEmpty(workingDirectoryStr)) { + workingDirectoryStr = TSLConfiguration.DEFAULT_WORKING_DIR; + warn("config.39", new Object[] { "WorkingDirectory", workingDirectoryStr }); + } + + // convert update schedule starting time to Date object + Calendar Cal = DatatypeConverter.parseDateTime(updateScheduleStartTime); + Date updateScheduleStartTimeDate = Cal.getTime(); + + // convert working directory + URI workingDirectoryURI = null; + try + { + workingDirectoryURI = new URI(workingDirectoryStr); + if (!workingDirectoryURI.isAbsolute()) { // make it absolute to the config file + workingDirectoryURI = new URI(configRoot_.toURL() + workingDirectoryStr); + } + } + catch (URIException e) { + warn("config.37", new Object[] { workingDirectoryStr }, e); + workingDirectoryStr = TSLConfiguration.DEFAULT_WORKING_DIR; + warn("config.39", new Object[] { "WorkingDirectory", workingDirectoryStr }); + } + catch (MalformedURLException e) + { + warn("config.37", new Object[] { workingDirectoryStr }, e); + workingDirectoryStr = TSLConfiguration.DEFAULT_WORKING_DIR; + warn("config.39", new Object[] { "WorkingDirectory", workingDirectoryStr }); + } + + File tslWorkingDir = new File(workingDirectoryURI.getPath()); + if (!tslWorkingDir.exists()) { + tslWorkingDir.mkdir(); + } + if (!tslWorkingDir.isDirectory()) { + error("config.38", new Object[] { workingDirectoryStr }); + return null; + } + + debug("TSL Konfiguration - UpdateSchedule/Period: " + updateSchedulePeriod); + debug("TSL Konfiguration - UpdateSchedule/StartTime: " + updateScheduleStartTime); + debug("TSL Konfiguration - TSLWorkingDirectory: " + tslWorkingDir.getAbsolutePath()); + + // set TSL configuration + //tslconfiguration.setEuTSLUrl(euTSLUrl); + tslconfiguration.setUpdateSchedulePeriod(Long.valueOf(updateSchedulePeriod).longValue()); + tslconfiguration.setUpdateScheduleStartTime(updateScheduleStartTimeDate); + tslconfiguration.setWorkingDirectory(tslWorkingDir.getAbsolutePath()); + + + + return tslconfiguration; + } + /** * Returns a map of CRL retention intervals * @return @@ -1404,4 +1532,5 @@ public class ConfigurationPartsBuilder { return map; } + } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java index 84b8561ac..25fa0d6ad 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/ConfigurationProvider.java @@ -38,6 +38,7 @@ import java.security.Principal; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -46,6 +47,7 @@ import org.w3c.dom.Element; import at.gv.egovernment.moa.logging.LogMsg; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.api.common.TSLConfiguration; import at.gv.egovernment.moa.spss.util.MessageProvider; import at.gv.egovernment.moa.util.DOMUtils; @@ -142,8 +144,8 @@ public class ConfigurationProvider * to distribution points (a Set of * DistributionPoints) mapping. */ - private Map distributionPoints; + private Map distributionPoints; /** * The CRL archive duration. */ @@ -249,6 +251,12 @@ public class ConfigurationProvider */ private List blackListedUris_; + /** + * A TSLConfiguration that represents the global TSL configuration + */ + private TSLConfiguration tslconfiguration_; + + /** * Return the single instance of configuration data. * @@ -356,6 +364,13 @@ public class ConfigurationProvider cRLArchiveDuration = builder.getRevocationArchiveDuration(); revocationArchiveJDBCURL_ = builder.getRevocationArchiveJDBCURL(); revocationArchiveJDBCDriverClass_ = builder.getRevocationArchiveJDBCDriverClass(); + + tslconfiguration_ = builder.getTSLConfiguration(); + //check TSL configuration + checkTSLConfiguration(); + + + certStoreLocation_ = builder.getCertStoreLocation(); createTransformsInfoProfiles = builder.buildCreateTransformsInfoProfiles(); createSignatureEnvironmentProfiles = builder.buildCreateSignatureEnvironmentProfiles(); @@ -396,6 +411,31 @@ public class ConfigurationProvider } } } + + private void checkTSLConfiguration() throws ConfigurationException { + boolean bTSLEnabledTPExist = false; + Iterator it = trustProfiles.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry pairs = (Map.Entry)it.next(); + TrustProfile tp = (TrustProfile) pairs.getValue(); + if (tp.isTSLEnabled()) + bTSLEnabledTPExist = bTSLEnabledTPExist || true; + } + + if (!bTSLEnabledTPExist) { + // if no trustprofile has TSL support enabled, delete TSL configuration + tslconfiguration_ = null; + return; + } + + if (bTSLEnabledTPExist && (tslconfiguration_ == null)) { + error("config.40", null); + throw new ConfigurationException("config.40", null); + } + + + } + /** * Returns the warnings encountered during building the configuration. @@ -690,6 +730,21 @@ public class ConfigurationProvider warnings.add(txt); } + /** + * Log an error. + * + * @param messageId The message ID. + * @param args Additional parameters for the message. + * @see at.gv.egovernment.moa.spss.server.util.MessageProvider + */ + private void error(String messageId, Object[] args) { + MessageProvider msg = MessageProvider.getInstance(); + String txt = msg.getMessage(messageId, args); + + Logger.warn(new LogMsg(txt)); +// warnings.add(txt); + } + /** * Returns the JDBC URL for the revocation archive database. * @@ -783,6 +838,13 @@ public class ConfigurationProvider public Map getCrlRetentionIntervals() { return crlRetentionIntervals; } - + + /** + * Returns the global TSL configuration + * @return The global TSL configuration + */ + public TSLConfiguration getTSLConfiguration() { + return tslconfiguration_; + } } \ No newline at end of file diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/TrustProfile.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/TrustProfile.java index dac91be87..1b5f4473d 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/TrustProfile.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/config/TrustProfile.java @@ -24,6 +24,8 @@ package at.gv.egovernment.moa.spss.server.config; +import iaik.x509.X509Certificate; + /** * Information about a trust profile. * @@ -41,6 +43,8 @@ public class TrustProfile { private boolean tslEnabled; /** The countries given */ private String countries; + /** */ + private X509Certificate[] certificatesToBeRemoved; /** * Create a TrustProfile. @@ -56,6 +60,7 @@ public class TrustProfile { this.signerCertsUri = signerCertsUri; this.tslEnabled = tslEnabled; this.countries = countries; + this.certificatesToBeRemoved = new X509Certificate[0]; } /** @@ -103,4 +108,20 @@ public class TrustProfile { return countries; } + /** + * Return the old certificates (from previous TSL update) to be removed from the truststore before performing a new TSL update + * @return The old certificates (from previous TSL update) to be removed from the truststore before performing a new TSL update + */ + public X509Certificate[] getCertficatesToBeRemoved() { + return certificatesToBeRemoved; + } + + /** + * Sets the old certificates (from previous TSL update) to be removed from the truststore before performing a new TSL update + * @param certificates The old certificates (from previous TSL update) to be removed from the truststore before performing a new TSL update + */ + public void setCertificatesToBeRemoved(X509Certificate[] certificates) { + this.certificatesToBeRemoved = new X509Certificate[certificates.length]; + this.certificatesToBeRemoved = certificates; + } } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/init/SystemInitializer.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/init/SystemInitializer.java index b4b172c8a..c9b76dd7e 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/init/SystemInitializer.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/init/SystemInitializer.java @@ -25,28 +25,35 @@ package at.gv.egovernment.moa.spss.server.init; import iaik.ixsil.init.IXSILInit; -import iaik.logging.TransactionId; import iaik.pki.store.certstore.CertStoreException; -import iaik.pki.store.certstore.CertStoreParameters; import iaik.pki.store.truststore.TrustStoreException; -import iaik.pki.store.truststore.TrustStoreProfile; -import iaik.pki.store.utils.StoreUpdater; import iaik.server.ConfigurationData; -import iaik.x509.X509Certificate; +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; +import iaik.xml.crypto.tsl.ex.TSLSearchException; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; import java.util.Iterator; -import java.util.Map; +import java.util.Timer; import at.gv.egovernment.moa.logging.LogMsg; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.logging.LoggingContext; import at.gv.egovernment.moa.logging.LoggingContextManager; import at.gv.egovernment.moa.spss.MOAException; +import at.gv.egovernment.moa.spss.api.common.TSLConfiguration; import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; import at.gv.egovernment.moa.spss.server.iaik.config.IaikConfigurator; import at.gv.egovernment.moa.spss.server.logging.IaikLog; import at.gv.egovernment.moa.spss.server.service.RevocationArchiveCleaner; +import at.gv.egovernment.moa.spss.tsl.connector.TSLConnector; +import at.gv.egovernment.moa.spss.tsl.timer.TSLUpdaterTimerTask; import at.gv.egovernment.moa.spss.util.MessageProvider; import at.gv.egovernment.moa.util.Constants; import at.gv.egovernment.moa.util.DOMUtils; @@ -115,42 +122,45 @@ public class SystemInitializer { try { ConfigurationProvider config = ConfigurationProvider.getInstance(); ConfigurationData configData = new IaikConfigurator().configure(config); - - Map mapTrustProfiles = config.getTrustProfiles(); - - Iterator it = mapTrustProfiles.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry pairs = (Map.Entry)it.next(); - System.out.println(pairs.getKey() + " = " + pairs.getValue()); + + //initialize TSL module + TSLConfiguration tslconfig = config.getTSLConfiguration(); + TSLConnector tslconnector = new TSLConnector(); + if (tslconfig != null) { + //Logger.info(new LogMsg(msg.getMessage("init.01", null))); + Logger.info(new LogMsg(msg.getMessage("config.41", null))); + tslconnector.initialize(tslconfig.getEuTSLUrl(), tslconfig.getWorkingDirectory(), null, null); + } - //@TSL get parameters for StoreUpdater - CertStoreParameters[] certStoreParameters = configData.getPKIConfiguration().getCertStoreConfiguration().getParameters(); - TrustStoreProfile[] trustStoreProfiles = null; - TransactionId tid = null; - - - //@TSL Init TSL Module - X509Certificate[] removeCertificates = null; - X509Certificate[] addCertificates = null; - -// iaik.pki.store.utils.StoreUpdater storeUpdater = new StoreUpdater(certStoreParameters, trustStoreProfiles, tid); -// storeUpdater.removeCertificatesFromTrustStores(removeCertificates, tid); - - + //start TSL Update + TSLUpdaterTimerTask.tslconnector_ = tslconnector; + TSLUpdaterTimerTask.update(); + + //initialize TSL Update Task + initTSLUpdateTask(tslconfig); + Logger.info(new LogMsg(msg.getMessage("init.01", null))); } catch (MOAException e) { Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); } -// catch (CertStoreException e) { -// //@TSL -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } catch (TrustStoreException e) { -// //@TSL -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } + catch (TSLEngineDiedException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } + catch (TSLSearchException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } + catch (CertStoreException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } catch (TrustStoreException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } catch (CertificateException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } catch (FileNotFoundException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } catch (IOException e) { + Logger.fatal(new LogMsg(msg.getMessage("init.00", null)), e); + } // set IXSIL debug output IXSILInit.setPrintDebugLog( @@ -167,5 +177,41 @@ public class SystemInitializer { // unset the startup logging context LoggingContextManager.getInstance().setLoggingContext(null); } + + private static void initTSLUpdateTask(TSLConfiguration tslconfig) { + MessageProvider msg = MessageProvider.getInstance(); + if (tslconfig != null) { + // get start time and period from config + long period = tslconfig.getUpdateSchedulePeriod(); + Date startConfig = tslconfig.getUpdateScheduleStartTime(); + + // get hh:mm:ss from config date + Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance + calendar.setTime(startConfig); // assigns calendar to given date + int hour = calendar.get(Calendar.HOUR_OF_DAY); + int min = calendar.get(Calendar.MINUTE); + int sec = calendar.get(Calendar.SECOND); + + // create date with today and time from config + Calendar cal = Calendar.getInstance(); + Date now = cal.getTime(); + cal.set(Calendar.HOUR_OF_DAY, hour); + cal.set(Calendar.MINUTE, min); + cal.set(Calendar.SECOND, sec); + + // proposed start time + Date start = cal.getTime(); + + // if start time has already passed today - add one day (86400000 milliseconds = 1 day) + if (start.before(now)) + start = new Date(start.getTime() + 86400000); + + Logger.debug(new LogMsg(msg.getMessage("config.46", new String[]{start.toString(), "" + period}))); + + // start TSL updater task + Timer timer = new Timer(); + timer.schedule(new TSLUpdaterTimerTask(), start, period); + } + } } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/IaikExceptionMapper.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/IaikExceptionMapper.java index b4f73b96b..869cfefa1 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/IaikExceptionMapper.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/IaikExceptionMapper.java @@ -83,7 +83,11 @@ public class IaikExceptionMapper { { iaik.server.modules.xmlverify.SignerCertificateUnavailableException.class, "2243", MOAApplicationException.class }, { iaik.server.modules.xmlverify.SupplementException.class, "2230", MOAApplicationException.class }, { iaik.server.modules.xmlverify.TransformationException.class, "2265", MOAApplicationException.class }, - { iaik.server.modules.xmlverify.TransformationParsingException.class, "2269", MOAApplicationException.class } + { iaik.server.modules.xmlverify.TransformationParsingException.class, "2269", MOAApplicationException.class }, + { iaik.xml.crypto.tsl.ex.TSLEngineDiedException.class, "2290", MOAApplicationException.class }, + { iaik.xml.crypto.tsl.ex.TSLSearchException.class, "2290", MOAApplicationException.class } + + }; /** The single instance of this class. */ @@ -145,6 +149,28 @@ public class IaikExceptionMapper { new ExceptionMappingInfo(messageId, moaExceptionClass)); } + /** + * Map an iaik.xml.crypto.tsl.ex.TSLSearchException to a MOAException. + * + * @param tslSearchException The iaik.xml.crypto.tsl.ex.TSLSearchException to map. + * @return A MOAException containing the message for the + * given IAIKException. + */ + public MOAException map(iaik.xml.crypto.tsl.ex.TSLSearchException tslSearchException) { + return mapImpl(tslSearchException); + } + + /** + * Map an iaik.xml.crypto.tsl.ex.TSLEngineDiedException to a MOAException. + * + * @param tslEngineDiedException The iaik.xml.crypto.tsl.ex.TSLEngineDiedException to map. + * @return A MOAException containing the message for the + * given IAIKException. + */ + public MOAException map(iaik.xml.crypto.tsl.ex.TSLEngineDiedException tslEngineDiedException) { + return mapImpl(tslEngineDiedException); + } + /** * Map an IAIKException to a MOAException. * @@ -155,7 +181,7 @@ public class IaikExceptionMapper { public MOAException map(IAIKException iaikException) { return mapImpl(iaikException); } - + /** * Map an IAIKRuntimeException to a MOAException. * diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyCMSSignatureResponseBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyCMSSignatureResponseBuilder.java index 6dbb511ca..fcd5ae0e7 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyCMSSignatureResponseBuilder.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyCMSSignatureResponseBuilder.java @@ -87,13 +87,15 @@ public class VerifyCMSSignatureResponseBuilder { CheckResult signatureCheck; CheckResult certificateCheck; + // TODO Check TSL check // add SignerInfo element signerInfo = factory.createSignerInfo( (X509Certificate) certResult.getCertificateChain().get(0), certResult.isQualifiedCertificate(), certResult.isPublicAuthorityCertificate(), - certResult.getPublicAuthorityID()); + certResult.getPublicAuthorityID(), + false); // add SignatureCheck element signatureCheck = factory.createCheckResult(signatureCheckCode, null); diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java index d48b394ef..755ca82b6 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/VerifyXMLSignatureResponseBuilder.java @@ -60,6 +60,8 @@ import at.gv.egovernment.moa.spss.api.xmlverify.ManifestRefsCheckResultInfo; import at.gv.egovernment.moa.spss.api.xmlverify.ReferencesCheckResult; import at.gv.egovernment.moa.spss.api.xmlverify.ReferencesCheckResultInfo; import at.gv.egovernment.moa.spss.api.xmlverify.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +import at.gv.egovernment.moa.spss.server.config.TrustProfile; import at.gv.egovernment.moa.util.CollectionUtils; import at.gv.egovernment.moa.util.DOMUtils; import at.gv.egovernment.moa.util.NodeListAdapter; @@ -123,13 +125,20 @@ public class VerifyXMLSignatureResponseBuilder { * @param transformsSignatureManifestCheck The overall result for the signature * manifest check. * @param certificateCheck The overall result for the certificate check. + * @param checkQCFromTSL true, if the TSL check verifies the + * certificate as qualified, otherwise false. + * @param checkSSCDFromTSL true, if the TSL check verifies the + * signature based on a SSDC, otherwise false. * @throws MOAApplicationException An error occurred adding the result. */ public void setResult( XMLSignatureVerificationResult result, XMLSignatureVerificationProfile profile, ReferencesCheckResult transformsSignatureManifestCheck, - CheckResult certificateCheck) + CheckResult certificateCheck, + boolean checkQCFromTSL, + boolean checkSSCDFromTSL, + boolean isTSLEnabledTrustprofile) throws MOAApplicationException { CertificateValidationResult certResult = @@ -141,13 +150,26 @@ public class VerifyXMLSignatureResponseBuilder { int[] failedReferences; Iterator iter; + boolean qualifiedCertificate = false; + + // verify qualified certificate checks (certificate or TSL) + if (isTSLEnabledTrustprofile) { + // take TSL result + qualifiedCertificate = checkQCFromTSL; + } + else { + // take result from certificate + qualifiedCertificate = certResult.isQualifiedCertificate(); + } + // create the SignerInfo; signerInfo = factory.createSignerInfo( (X509Certificate) certResult.getCertificateChain().get(0), - certResult.isQualifiedCertificate(), + qualifiedCertificate, certResult.isPublicAuthorityCertificate(), - certResult.getPublicAuthorityID()); + certResult.getPublicAuthorityID(), + checkSSCDFromTSL); // Create HashInputData Content objects referenceDataList = result.getReferenceDataList(); diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/XMLSignatureVerificationInvoker.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/XMLSignatureVerificationInvoker.java index adaf0d376..290841c66 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/XMLSignatureVerificationInvoker.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/invoke/XMLSignatureVerificationInvoker.java @@ -40,6 +40,8 @@ import iaik.server.modules.xmlverify.XMLSignatureVerificationModuleFactory; import iaik.server.modules.xmlverify.XMLSignatureVerificationProfile; import iaik.server.modules.xmlverify.XMLSignatureVerificationResult; import iaik.x509.X509Certificate; +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; +import iaik.xml.crypto.tsl.ex.TSLSearchException; import java.io.File; import java.io.FileInputStream; @@ -85,6 +87,7 @@ import at.gv.egovernment.moa.spss.server.logging.IaikLog; import at.gv.egovernment.moa.spss.server.logging.TransactionId; import at.gv.egovernment.moa.spss.server.transaction.TransactionContext; import at.gv.egovernment.moa.spss.server.transaction.TransactionContextManager; +import at.gv.egovernment.moa.spss.tsl.timer.TSLUpdaterTimerTask; import at.gv.egovernment.moa.spss.util.MessageProvider; import at.gv.egovernment.moa.util.CollectionUtils; import at.gv.egovernment.moa.util.Constants; @@ -188,7 +191,7 @@ public class XMLSignatureVerificationInvoker { // build profile profile = profileFactory.createProfile(); - + // get the signingTime signingTime = request.getDateTime(); @@ -205,6 +208,13 @@ public class XMLSignatureVerificationInvoker { requestElement); } + boolean checkQCFromTSL = false; + boolean checkSSCDFromTSL = false; + + String tpID = profile.getCertificateValidationProfile().getTrustStoreProfile().getId(); + ConfigurationProvider config = ConfigurationProvider.getInstance(); + TrustProfile tp = config.getTrustProfile(tpID); + // verify the signature try { XMLSignatureVerificationModule module = @@ -219,6 +229,24 @@ public class XMLSignatureVerificationInvoker { profile, signingTime, new TransactionId(context.getTransactionID())); + if (tp.isTSLEnabled()) { + List list = result.getCertificateValidationResult().getCertificateChain(); + if (list != null) { + X509Certificate[] chain = new X509Certificate[list.size()]; + + + Iterator it = list.iterator(); + int i = 0; + while(it.hasNext()) { + chain[i] = (X509Certificate)it.next(); + i++; + } + + checkQCFromTSL = TSLUpdaterTimerTask.tslconnector_.checkQC(chain); + checkSSCDFromTSL = TSLUpdaterTimerTask.tslconnector_.checkSSCD(chain); + } + + } } catch (IAIKException e) { MOAException moaException = IaikExceptionMapper.getInstance().map(e); @@ -226,7 +254,13 @@ public class XMLSignatureVerificationInvoker { } catch (IAIKRuntimeException e) { MOAException moaException = IaikExceptionMapper.getInstance().map(e); throw moaException; - } + } catch (TSLEngineDiedException e) { + MOAException moaException = IaikExceptionMapper.getInstance().map(e); + throw moaException; + } catch (TSLSearchException e) { + MOAException moaException = IaikExceptionMapper.getInstance().map(e); + throw moaException; + } // swap back in the request as root document if (requestElement != signatureEnvironment.getElement()) { @@ -236,7 +270,6 @@ public class XMLSignatureVerificationInvoker { signatureEnvironmentParent.appendChild(signatureEnvironment.getElement()); } - // check the result signatureManifestCheck = validateSignatureManifest(request, result, profile); @@ -244,10 +277,9 @@ public class XMLSignatureVerificationInvoker { // Check if signer certificate is in trust profile's allowed signer certificates pool TrustProfile trustProfile = context.getConfiguration().getTrustProfile(request.getTrustProfileId()); CheckResult certificateCheck = validateSignerCertificate(result, trustProfile); - // build the response - responseBuilder.setResult(result, profile, signatureManifestCheck, certificateCheck); + responseBuilder.setResult(result, profile, signatureManifestCheck, certificateCheck, checkQCFromTSL, checkSSCDFromTSL, tp.isTSLEnabled()); return responseBuilder.getResponse(); } diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/config/Configurator.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/config/Configurator.java new file mode 100644 index 000000000..7e8dcf0c4 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/config/Configurator.java @@ -0,0 +1,128 @@ +package at.gv.egovernment.moa.spss.tsl.config; + +import iaik.util.logging._l; +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; + +import java.net.MalformedURLException; +import java.net.URL; + +public class Configurator { + + private static final String _TMPDBFILENAME = "temp_tsl.sqlite"; + + private static boolean _sqlMultithreaded; + private static boolean _throwExceptions; + private static boolean _logExceptions; + private static boolean _throwWarnings; + private static boolean _logWarnings; + private static boolean _nullRedundancies; + private static URL _euTSLURL; + private static String _TSLWorkingDirectoryPath; + private static String _dbFile; + private static String _euTrustAnchorsPath; + private static String _msTrustAnchorsPath; + + + private static boolean _isInitialised = false; + + + /** + * + */ + public static void initial(String euTSLURL, String TSLWorkingDirectoryPath, String jdbcURL, String jdbcDriverClass) + throws TSLEngineDiedException { + + + if (!_isInitialised) { + try { + _euTSLURL = new URL(euTSLURL); + } catch (MalformedURLException e) { + _l.err("Bad TSL URL: " + euTSLURL, e); + throw new TSLEngineDiedException(e); + } + + //@TODO Check "/" + Configurator._TSLWorkingDirectoryPath = TSLWorkingDirectoryPath + "/"; + + initialDefaultConfig(); + + _isInitialised = true; + } + } + + public static String get_TSLWorkingDirectoryPath() { + return _TSLWorkingDirectoryPath; + } + + public static String get_dbFile() { + return _dbFile; + } + + public static void set_dbFileName(String _dbFile) { + Configurator._dbFile = _TSLWorkingDirectoryPath + _dbFile; + } + + public static String get_euTrustAnchorsPath() { + return _euTrustAnchorsPath; + } + + public static String get_msTrustAnchorsPath() { + return _msTrustAnchorsPath; + } + + public static boolean is_sqlMultithreaded() { + return _sqlMultithreaded; + } + + public static boolean is_throwExceptions() { + return _throwExceptions; + } + + public static boolean is_logExceptions() { + return _logExceptions; + } + + public static boolean is_throwWarnings() { + return _throwWarnings; + } + + public static boolean is_logWarnings() { + return _logWarnings; + } + + public static boolean is_nullRedundancies() { + return _nullRedundancies; + } + + public static URL get_euTSLURL() { + return _euTSLURL; + } + + public static boolean is_isInitialised() { + return _isInitialised; + } + + public static String get_TempdbFile() { + return _TSLWorkingDirectoryPath + _TMPDBFILENAME; + } + + public static void set_euTrustAnchorsPath(String _euTrustAnchorsPath) { + Configurator._euTrustAnchorsPath = _euTrustAnchorsPath; + } + + public static void set_msTrustAnchorsPath(String _msTrustAnchorsPath) { + Configurator._msTrustAnchorsPath = _msTrustAnchorsPath; + } + + private static void initialDefaultConfig() { + _sqlMultithreaded = false; + _throwExceptions = true; + _logExceptions = true; + _throwWarnings = false; + _logWarnings = true; + _nullRedundancies = false; + _dbFile = _TSLWorkingDirectoryPath + "tsl.sqlite"; + _euTrustAnchorsPath = _TSLWorkingDirectoryPath + "trust/eu/"; + _msTrustAnchorsPath = "/trust/ms/"; + } +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnector.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnector.java new file mode 100644 index 000000000..b88255115 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnector.java @@ -0,0 +1,718 @@ +package at.gv.egovernment.moa.spss.tsl.connector; + +import iaik.asn1.ObjectID; +import iaik.util._; +import iaik.util.logging._l; +import iaik.utils.RFC2253NameParser; +import iaik.xml.crypto.EccProviderAdapter; +import iaik.xml.crypto.XSecProvider; +import iaik.xml.crypto.tsl.DbTables; +import iaik.xml.crypto.tsl.TSLCertEvaluator; +import iaik.xml.crypto.tsl.TSLCertsExporter; +import iaik.xml.crypto.tsl.TSLEngine; +import iaik.xml.crypto.tsl.TSLImportContext; +import iaik.xml.crypto.tsl.TSLResult; +import iaik.xml.crypto.tsl.TSLResultEndEntity; +import iaik.xml.crypto.tsl.TSLResultImpl; +import iaik.xml.crypto.tsl.TslSqlConnectionWrapper; +import iaik.xml.crypto.tsl.DbTables.MODE; +import iaik.xml.crypto.tsl.DbTables.Service; +import iaik.xml.crypto.tsl.TSLEngine.LocationAndCertHash; +import iaik.xml.crypto.tsl.TSLEngine.TSLEngineEU; +import iaik.xml.crypto.tsl.constants.Countries; +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; +import iaik.xml.crypto.tsl.ex.TSLEngineFatalException; +import iaik.xml.crypto.tsl.ex.TSLEngineFatalRuntimeException; +import iaik.xml.crypto.tsl.ex.TSLExceptionB; +import iaik.xml.crypto.tsl.ex.TSLRuntimeException; +import iaik.xml.crypto.tsl.ex.TSLSearchException; +import iaik.xml.crypto.tsl.ex.TSLTransactionFailedRuntimeException; +import iaik.xml.crypto.tsl.fetch.TLS; +import iaik.xml.crypto.tsl.sie.gen.QualifierType; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.channels.ByteChannel; +import java.nio.channels.FileChannel; +import java.security.Security; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import org.apache.log4j.Logger; + +import at.gv.egovernment.moa.spss.tsl.config.Configurator; +import at.gv.egovernment.moa.spss.tsl.utils.TSLEUImportFromFileContext; +import at.gv.egovernment.moa.spss.tsl.utils.TSLEvaluationContext; +import at.gv.egovernment.moa.spss.tsl.utils.TSLImportFromFileContext; + +public class TSLConnector implements TSLConnectorInterface { + + static final String _QCSSCDURI = "http://uri.etsi.org/TrstSvc/eSigDir-1999-93-EC-TrustedList/SvcInfoExt/QCWithSSCD"; + static final String _STYPETEMPLATE = "CA/QC"; + + private static final String DEFAULT_HASHCACHE_DIR = "./hashcache/"; + + + static Logger log = Logger.getLogger(TSLConnector.class); + + public void initialize(String euTSLURL, String TSLWorkingDirectoryPath, String jdbcURL, String jdbcDriverClass) + throws TSLEngineDiedException { + + Configurator.initial(euTSLURL, TSLWorkingDirectoryPath, jdbcURL, jdbcDriverClass); + + } + + public ArrayList updateAndGetQualifiedCACertificates(Date dateTime, + String[] serviceLevelStatus) throws TSLEngineDiedException, TSLSearchException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + return updateAndGetQualifiedCACertificates(dateTime, null, serviceLevelStatus); + } + + public ArrayList updateAndGetQualifiedCACertificates(Date dateTime, + String[] countries, String[] serviceLevelStatus) throws TSLEngineDiedException, TSLSearchException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + //TODO: clean hascash and TLS Download folder + String hashcachedir = System.getProperty("iaik.xml.crypto.tsl.BinaryHashCache.DIR"); + + System.out.println("hashcachedir: " + hashcachedir); + + if (hashcachedir==null) + hashcachedir = DEFAULT_HASHCACHE_DIR; + + String tsldownloaddir = Configurator.get_TSLWorkingDirectoryPath() + "TslDownload"; + + System.out.println("hashcachedir: " + hashcachedir); + + File hashcachefile = new File(hashcachedir); + System.out.println("Hashcache: " + hashcachefile.getAbsolutePath()); + + + File[] filelist = hashcachefile.listFiles(); + if (filelist != null) { + for (File f : filelist) + f.delete(); + } + + File tsldownloadfile = new File(tsldownloaddir); + if (!tsldownloadfile.exists()) { + tsldownloadfile.mkdir(); + } + File[] tslfilelist = tsldownloadfile.listFiles(); + if (tslfilelist != null) { + for (File f : tslfilelist) + f.delete(); + } + + //create sqlLite database + File dbFile = new File(Configurator.get_TempdbFile()); + try { + dbFile.delete(); + dbFile.createNewFile(); + } catch (IOException e) { + throw new TSLEngineDiedException("Could not create temporary data base file", e); + } + + //the TSL library uses the iaik.util.logging environment. + //iaik.util.logging.Log.setLogLevel(iaik.util.logging.LogLevels.WARN); + iaik.util.logging.Log.setLogLevel(iaik.util.logging.LogLevels.OFF); + + log.info("Starting EU TSL import."); + + // Certificates in Germany, Estonia, Greece, Cyprus, + // Lithuainia, Hungary, Poland, Finland, Norway use SURNAME + log.debug("### SURNAME registered as " + ObjectID.surName + " ###"); + RFC2253NameParser.register("SURNAME", ObjectID.surName); + + XSecProvider.addAsProvider(false); + + TSLEngine tslEngine; + TslSqlConnectionWrapper connection = null; + + try { + // register the Https JSSE Wrapper + TLS.register(); + log.trace("### Https JSSE Wrapper registered ###"); + + + log.debug("### Connect to Database.###"); + connection = DbTables.connectToDatabaBase(dbFile, MODE.AUTO_COMMIT_ON); + + log.trace("### Connected ###"); + + // empty the database and recreate the tables + tslEngine = new TSLEngine(dbFile, Configurator.get_TSLWorkingDirectoryPath(), + connection, true, true); + + } catch (TSLEngineFatalException e1) { + throw new TSLEngineDiedException(e1); + + } + + // H.2.2.1 Same-scheme searching + // H.2.2.2 Known scheme searching + // H.2.2.3 "Blind" (unknown) scheme searching + Number tId = null; + Countries euTerritory = Countries.EU; + TSLImportContext topLevelTslContext = new TSLEUImportFromFileContext( + euTerritory, Configurator.get_euTSLURL(), Configurator.get_TSLWorkingDirectoryPath(), + Configurator.is_sqlMultithreaded(), + Configurator.is_throwExceptions(), Configurator.is_logExceptions(), + Configurator.is_throwWarnings(), Configurator.is_logWarnings(), + Configurator.is_nullRedundancies()); + + TSLEngineEU tslengineEU; + try { + tslengineEU = tslEngine.new TSLEngineEU(); + + } catch (TSLEngineFatalException e1) { + throw new TSLEngineDiedException(e1); + } + + // establish EU TSL trust anchor + ListIterator expectedEuTslSignerCerts = + tslEngine.loadCertificatesFromResource( + Configurator.get_euTrustAnchorsPath(), topLevelTslContext); + + log.debug("Process EU TSL"); + // process the EU TSL to receive the pointers to the other TSLs + // and the trust anchors for the TSL signers + Set> pointersToMsTSLs = null; + + try { + + tId = tslengineEU.processEUTSL(topLevelTslContext, expectedEuTslSignerCerts); + log.info("Process EU TSL finished"); + + log.debug(Thread.currentThread() + " waiting for other threads ..."); + + topLevelTslContext.waitForAllOtherThreads(); + log.debug(Thread.currentThread() + + " reactivated after other threads finished ..."); + + + // get the TSLs pointed from the EU TSL + LinkedHashMap tslMap = tslengineEU + .getOtherTslMap(tId, topLevelTslContext); + + pointersToMsTSLs = tslMap.entrySet(); + + //set Errors and Warrnings + + } catch (TSLEngineFatalRuntimeException e) { + throw new TSLEngineDiedException(topLevelTslContext.dumpFatals()); + + } catch (TSLTransactionFailedRuntimeException e) { + throw new TSLEngineDiedException(topLevelTslContext.dumpTransactionFaliures()); + } + + //Backup implementation if the EU TSL includes a false signer certificate + // establish additional trust anchors for member states +// Countries[] countriesWithPotentiallyWrongCertsOnEuTsl = { +// Countries.CZ, +// Countries.LU, +// Countries.ES, +// Countries.AT, +// }; + Countries[] countriesWithPotentiallyWrongCertsOnEuTsl = {}; + + Map> + trustAnchorsWrongOnEuTsl = loadCertificatesFromResource( + Configurator.get_msTrustAnchorsPath(), tslEngine, topLevelTslContext, + countriesWithPotentiallyWrongCertsOnEuTsl); + + log.info("Starting EU member TSL import."); + + for (Entry entry : pointersToMsTSLs) { + + TSLImportContext msTslContext; + + Countries expectedTerritory = entry.getValue().getSchemeTerritory(); + try { + + if (expectedTerritory.equals("RO")) + System.out.println("Stop"); + + Number otpId = entry.getKey(); + LocationAndCertHash lac = entry.getValue(); + + URL uriReference = null; + try { + uriReference = new URL(lac.getUrl()); + + } catch (MalformedURLException e) { + log.warn("Could not process: " + uriReference, e); + continue; + } + + String baseURI = uriReference == null ? "" : "" + uriReference; + + msTslContext = new TSLImportFromFileContext( + expectedTerritory, uriReference, otpId, Configurator.get_TSLWorkingDirectoryPath(), + Configurator.is_sqlMultithreaded(), + Configurator.is_throwExceptions(), Configurator.is_logExceptions(), + Configurator.is_throwWarnings(), Configurator.is_logWarnings(), + Configurator.is_nullRedundancies(), baseURI, trustAnchorsWrongOnEuTsl, + topLevelTslContext); + + ListIterator expectedTslSignerCerts = null; + expectedTslSignerCerts = tslEngine.getCertificates(lac, msTslContext); + + if (expectedTslSignerCerts == null) { + + // no signer certificate on the EU TSL + // ignore this msTSL and log a warning + log.warn("NO signer certificate found on EU TSL! " + + lac.getSchemeTerritory() + "TSL ignored."); + + } + else { + tslEngine.processMSTSL(topLevelTslContext, msTslContext, expectedTslSignerCerts); + } + + } catch (TSLExceptionB e) { + log.warn("Failed to process TSL. " + entry.getValue().getSchemeTerritory() + + " TSL ignored."); + log.debug("Failed to process TSL. " + entry, e); + continue; + } catch (TSLRuntimeException e) { + log.warn("Failed to process TSL. " + entry.getValue().getSchemeTerritory() + + " TSL ignored."); + log.debug("Failed to process TSL. " + entry, e); + continue; + } + } + + log.debug(Thread.currentThread() + " waiting for other threads ..."); + topLevelTslContext.waitForAllOtherThreads(); + + log.debug(_.dumpAllThreads()); + log.debug(Thread.currentThread() + " reactivated after other threads finished ..."); + + connection = null; + try { + connection = DbTables.connectToDatabaBase(dbFile, MODE.AUTO_COMMIT_ON); + tslEngine.recreateTablesInvalidatedByImport(connection); + + + //TODO: implement database copy operation! + File working_database = new File(Configurator.get_dbFile()); + working_database.delete(); + copy(dbFile, working_database); + + + } catch (TSLEngineFatalException e) { + throw new TSLEngineDiedException(e); + + } finally { + try { + connection.closeConnection(); + + } catch (TSLEngineFatalException e) { + throw new TSLEngineDiedException(e); + + } + } + + return getQualifiedCACertificates(dateTime, countries, serviceLevelStatus); + } + + public ArrayList getQualifiedCACertificates(Date dateTime, + String[] serviceLevelStatus) throws TSLEngineDiedException, + TSLSearchException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + return getQualifiedCACertificates(dateTime, null, serviceLevelStatus); + } + + public ArrayList getQualifiedCACertificates(Date dateTime, + String[] countries, String[] serviceLevelStatus) + throws TSLEngineDiedException, TSLSearchException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + //TODO: database + File dbFile = new File(Configurator.get_TempdbFile()); + //File dbFile = new File(Configurator.get_dbFile()); + if(!dbFile.exists()) + throw new TSLEngineDiedException("Could not open data base file"); + + log.debug("### Connect to Database ###"); + TslSqlConnectionWrapper readConnection = null; + + try { + readConnection = DbTables.connectToDatabaBase(dbFile, MODE.READ_ONLY); + + TSLEngine tslEngine = new TSLEngine(dbFile, Configurator.get_TSLWorkingDirectoryPath(), + readConnection, false, false); + + log.debug("### Connected ###"); + + try { + TSLCertsExporter certsExporter; + certsExporter = tslEngine.createCertsExporter( + readConnection, + countries, + new String[]{_STYPETEMPLATE}, + serviceLevelStatus + ); + + return certsExporter.exportAsArray(dateTime, null); + + } catch (TSLEngineFatalException e) { + e.printStackTrace(); + _l.err("could not export Certs", e); + throw new TSLEngineDiedException(e); + } + + } catch (TSLEngineFatalException e1) { + throw new TSLEngineDiedException(e1); + + } finally { + try { + readConnection.closeConnection(); + + } catch (TSLEngineFatalException e) { + throw new TSLEngineDiedException(e); + } + } + } + + public boolean checkQC(java.security.cert.X509Certificate[] chain) + throws TSLSearchException, TSLEngineDiedException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + return checkQC(chain, 1); + } + + public boolean checkSSCD(java.security.cert.X509Certificate[] chain) + throws TSLSearchException, TSLEngineDiedException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + return checkSSCD(chain, 1); + } + + public boolean checkQC(java.security.cert.X509Certificate[] chain, int cnt) + throws TSLSearchException, TSLEngineDiedException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + LinkedHashMap tslResultC = checkchain(chain, cnt); + + //get first result + java.util.Map.Entry resultmap = tslResultC.entrySet().iterator().next(); + TSLResult tslresult = tslResultC.entrySet().iterator().next().getValue(); + + + + if (tslresult == null) { + log.info("Certificate: " + resultmap.getKey().getSubjectDN() + + " not on the TSL"); + throw new TSLSearchException("Certificate: " + resultmap.getKey().getSubjectDN() + + " not on the TSL"); + } + + if (tslresult instanceof TSLResultEndEntity) { + TSLResultEndEntity ree = (TSLResultEndEntity) tslresult; + + + String sType = (String) ree.get(Service.C.sType); + + log.info("Cert: " + resultmap.getKey().getSubjectDN() + " sType=" + sType); + + + if (sType.equals(_STYPETEMPLATE)) + return true; + else + return false; + } + + else if (tslresult instanceof TSLResultImpl) { + + //TODO: Certificate is not of Type EndEntity (equal to QCSSCD check) + // Is FALSE the correct answer? + return false; + } + + throw new TSLEngineDiedException("TSL Result has an unknown Class type"); + } + + public boolean checkSSCD(java.security.cert.X509Certificate[] chain, int cnt) + throws TSLSearchException, TSLEngineDiedException { + + if (Configurator.is_isInitialised() == false) + new TSLEngineFatalException("The TSL Engine is not initialized!"); + + LinkedHashMap tslResultC = checkchain(chain, cnt); + + //get first result + java.util.Map.Entry resultmap = tslResultC.entrySet().iterator().next(); + TSLResult tslresult = tslResultC.entrySet().iterator().next().getValue(); + + if (tslresult == null) { + log.info("Certificate: " + resultmap.getKey().getSubjectDN() + " not on the TSL"); + throw new TSLSearchException("Certificate: " + resultmap.getKey().getSubjectDN() + + " not on the TSL"); + } + + if (tslresult instanceof TSLResultEndEntity) { + TSLResultEndEntity ree = (TSLResultEndEntity) tslresult; + + List qualifier = ree.getQualifierList(); + + ListIterator qualifierlist = qualifier.listIterator(); + + String uri = ""; + + while (qualifierlist.hasNext()) { + uri = qualifierlist.next().getUri(); + + log.debug("Cert: " + resultmap.getKey().getSubjectDN() + " SSCD=" + uri); + + if (uri.contains(_QCSSCDURI)) { + return true; + } + else { + return false; + } + } + return false; + } + + else if (tslresult instanceof TSLResultImpl) { + + //TODO: Certificate is not of Type EndEntity (equal to QC check) + // Is FALSE the correct answer? + return false; + } + + throw new TSLEngineDiedException("TSL Result has an unknown Class type"); + } + + + + private LinkedHashMap checkchain(java.security.cert.X509Certificate[] chain, int cnt) + throws TSLSearchException, TSLEngineDiedException { + + File dbFile = new File(Configurator.get_dbFile()); + if(!dbFile.exists()) + throw new TSLEngineDiedException("Could not open data base file"); + + try { + + log.debug("### Connect to Database ###"); + TslSqlConnectionWrapper readConnection; + readConnection = DbTables.connectToDatabaBase(dbFile, MODE.READ_ONLY); + log.debug("### Connected ###"); + + TSLEngine tslEngine = new TSLEngine(dbFile, Configurator.get_TSLWorkingDirectoryPath(), + readConnection, false, false); + + XSecProvider.addAsProvider(false); + log.debug("### XSECT registered ###"); + // register the additional IAIK ECC provider + Security.addProvider(EccProviderAdapter.getEccProvider()); + log.debug("### ECC registered ###"); + + + TSLEvaluationContext context = new TSLEvaluationContext( + Configurator.get_TSLWorkingDirectoryPath(), + Configurator.is_sqlMultithreaded(), + Configurator.is_throwExceptions(), + Configurator.is_logExceptions(), + Configurator.is_throwWarnings(), + Configurator.is_logWarnings()); + + TSLCertEvaluator tslCertEvaluator = tslEngine.createEvaluator(context, + readConnection); + + Date signingTime = new Date(); + + // has to be later or equal + Date now = new Date(); + + LinkedHashMap tslResultC = tslCertEvaluator + .evaluate(TSLCertEvaluator.CHAIN_MODEL, chain, signingTime, now, context); + + return tslResultC; + + } catch (TSLEngineFatalException e1) { + throw new TSLEngineDiedException(e1); + } + + + } + + private static Map> loadCertificatesFromResource( + final String msTrustAnchorsPath, TSLEngine tslEngine, + TSLImportContext topLevelTslContext, Countries[] countriesWithNoCertsOnEuTsl) + throws TSLEngineDiedException { + Map> trustAnchorsMissingOnEuTsl; + trustAnchorsMissingOnEuTsl = + new HashMap>( + countriesWithNoCertsOnEuTsl.length); + + for (int i = 0; i < countriesWithNoCertsOnEuTsl.length; i++) { + Countries country = countriesWithNoCertsOnEuTsl[i]; + + final String mspath = msTrustAnchorsPath + country + "/"; + + ListIterator msCerts = + tslEngine.loadCertificatesFromResource(mspath, topLevelTslContext); + + trustAnchorsMissingOnEuTsl.put(country, msCerts); + } + return trustAnchorsMissingOnEuTsl; + } + + + private void copy(File source, File destination) throws TSLEngineDiedException { + try { + FileInputStream fileInputStream = new FileInputStream(source); + FileOutputStream fileOutputStream = new FileOutputStream(destination); + FileChannel inputChannel = fileInputStream.getChannel(); + FileChannel outputChannel = fileOutputStream.getChannel(); + + transfer(inputChannel, outputChannel, source.length(), false); + + fileInputStream.close(); + fileOutputStream.close(); + + destination.setLastModified(source.lastModified()); + } catch (Exception e) { + + throw new TSLEngineDiedException("Error during TSL database copy operation!."); + } + } + + private void transfer(FileChannel fileChannel, ByteChannel byteChannel, long lengthInBytes, boolean verbose) + throws IOException { + + long overallBytesTransfered = 0L; + long time = -System.currentTimeMillis(); + + while (overallBytesTransfered < lengthInBytes) { + long bytesTransfered = 0L; + bytesTransfered = fileChannel.transferTo(overallBytesTransfered, Math.min(1024 * 1024, lengthInBytes - overallBytesTransfered), byteChannel); + overallBytesTransfered += bytesTransfered; + if (verbose) { + System.out.println("overall bytes transfered: " + overallBytesTransfered + " progress " + (Math.round(overallBytesTransfered / ((double) lengthInBytes) * 100.0)) + "%"); + } + } + time += System.currentTimeMillis(); + + if (verbose) { + System.out.println("Transfered: " + overallBytesTransfered + " bytes in: " + (time / 1000) + " s -> " + (overallBytesTransfered / 1024.0) / (time / 1000.0) + " kbytes/s"); + } + } + + +// /** +// * @param tslResultC +// * @param context +// */ +// private static void printResultDetails( +// LinkedHashMap tslResultC, TSLContext context) { +// +// for (java.util.Map.Entry e : tslResultC +// .entrySet()) { +// +// TSLResult r = e.getValue(); +// +// if (r == null) { +// log.info("Certificate: " + e.getKey().getSubjectDN() +// + " not on the TSL"); +// continue; +// } +// +// if (r instanceof TSLResultEndEntity) { +// TSLResultEndEntity ree = (TSLResultEndEntity) r; +// +// String status = (String) ree.get(Service.C.status); +// +// Date startDate = context.getDate(ree.get(Service.C.startDate)); +// Long endDateL = (Long) ree.get(ServiceView.C.endDate); +// Date endDate = endDateL == null ? null : new Date(endDateL); +// +// String sType = (String) ree.get(Service.C.sType); +// +// List tslQual = ree.getQualifierList(); +// +// StringBuilder qualList = new StringBuilder(""); +// if (!tslQual.isEmpty()) { +// qualList.append("\n~~~~~~~~~~~~ TSL-Qualifiers ~~~~~~~~~~~~\n"); +// for (QualifierType qual : tslQual) { +// qualList.append(qual.getUri() + "\n"); +// } +// qualList.append("~~~~~~~~~~~~~~~~~ End ~~~~~~~~~~~~~~~~\n"); +// } +// +// log.info("############### EndEntity ###############\n" +// + _.printCertificate(e.getKey()) + qualList + "\nServiceProvider: " +// + ree.getSerivceProvider().getSubjectDN() + "\n" + Service.C.sType +// + ": " + sType + "\n" + Service.C.status + ": " + status + "\n" +// + Service.C.startDate + ": " + startDate + "\n" +// + ServiceView.C.endDate + ": " + endDate); +// log.info("############ ServiceProvider ############\n" +// + _.printCertificate(ree.getSerivceProvider())); +// log.info("################# END #################"); +// +// continue; +// } +// +// if (r instanceof TSLResultImpl) { +// TSLResultImpl ri = (TSLResultImpl) r; +// log.info("----------------- BEGIN -----------------\n" +// + "Certificate: " + e.getKey().getSubjectDN() + "\n" + ri.toString()); +// +// int i = 1; +// for (Iterator iter = ri.getRows().iterator(); iter.hasNext();) { +// Row row = (Row) iter.next(); +// // TSPServiceInformationType sInfo = +// // ((JAXBElement) +// // row.s_.get(Service.C.sInfo)).getValue(); +// String status = (String) row.s_.get(Service.C.status); +// +// Date startDate = context.getDate(row.s_.get(Service.C.startDate)); +// +// Date endDate = context.getDate(row.s_.get(ServiceView.C.endDate)); +// +// String sType = (String) row.s_.get(Service.C.sType); +// +// log.info("----------------- (" + (i++) + ") -----------------\n" +// + Service.C.sType + ": " + sType + " " + Service.C.status + ": " +// + status + "\n" + Service.C.startDate + ": " + startDate + "\n" +// + ServiceView.C.endDate + ": " + endDate + "\n" + row.s_); +// +// row.s_.get(Service.C.sExt); +// } +// log.info("----------------- END -----------------"); +// } +// } +// } +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnectorInterface.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnectorInterface.java new file mode 100644 index 000000000..4992f7563 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/connector/TSLConnectorInterface.java @@ -0,0 +1,95 @@ +package at.gv.egovernment.moa.spss.tsl.connector; + +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; +import iaik.xml.crypto.tsl.ex.TSLSearchException; + +import java.io.File; +import java.util.ArrayList; +import java.util.Date; + +import java.security.cert.X509Certificate; + +public interface TSLConnectorInterface { + + /** + * Initial the MOA TSL Connector.
+ * The hashcache directory must be set via "System-Property "iaik.xml.crypto.tsl.BinaryHashCache.DIR"!!! + * + * @author TLenz + * @param euTSLURL - URL to TrustList + * @param TSLWorkingDirectoryPath - Path to a folder which should be used by the TSL engine. (/A/B/.../) + * @param jdbcURL - ... + * @param jdbcDriverClass - ... + */ + void initialize(String euTSLURL, String TSLWorkingDirectoryPath, String jdbcURL, String jdbcDriverClass) throws TSLEngineDiedException; + + + /** + * Perform an update of all certificates which are on EU TSL and all MS TSLs and create an locale TSL database. + * The old locale TSL database is removed and a new database is created. + * + * @author TLenz + * @param dateTime - ... + * @param serviceLevelStatus - String Array of ServiceLevelStatus. For example new String[]{"accredited","undersupervision"} + * @return List of certificates with the selected properties + */ + ArrayList updateAndGetQualifiedCACertificates(Date dateTime, String[] serviceLevelStatus) + throws TSLEngineDiedException, TSLSearchException ; + + /** + * Perform an update of all certificates which are on EU TSL and all MS TSLs and create an locale TSL database. + * The old locale TSL database is removed and a new database is created. + * + * @author TLenz + * @param dateTime - ... + * @param countries - String Array of country codes. For example new Sting[]{"AT","IT","BE"} + * @param serviceLevelStatus - String Array of ServiceLevelStatus. For example new String[]{"accredited","undersupervision"} + * @return List of certificates with the selected properties + */ + ArrayList updateAndGetQualifiedCACertificates(Date dateTime, String[] countries, String[] serviceLevelStatus) + throws TSLEngineDiedException, TSLSearchException ; + + /** + * Check the http://uri.etis.org/TrstSvc/Svctype/CA/QC characteristic of a certificate by using the TSL information. + * This method uses information from the local TSL database. + * + * @author TLenz + * @param certificate - An X509 certificate. + * @return Return true, if the certificate comprises the http://uri.etis.org/TrstSvc/Svctype/CA/QC characteristic. + */ + boolean checkQC(X509Certificate[] certificate) throws TSLSearchException, TSLEngineDiedException; + + /** + * Check the http://uri.etis.org/TrstSvc/eSigDir-1999-93-ECTrustedList/SvcInfoExt/QCWithSSCD characteristic of a certificate by using the TSL information. + * This method uses information from the local TSL database. + * + * @author TLenz + * @param certificate - An X509 certificate. + * @return Return true, if the certificate comprises the http://uri.etis.org/TrstSvc/eSigDir-1999-93-ECTrustedList/SvcInfoExt/QCWithSSCD characteristic. + */ + boolean checkSSCD(X509Certificate[] certificate) throws TSLSearchException, TSLEngineDiedException; + + /** + * Get a list of certificates form the local TSL database with the selected properties. + * + * @author TLenz + * @param dateTime - ... + * @param serviceLevelStatus - String Array of ServiceLevelStatus. For example new String[]{"accredited","undersupervision"} + * @return List of certificates with the selected properties + */ + ArrayList getQualifiedCACertificates(Date dateTime, String[] serviceLevelStatus) + throws TSLEngineDiedException, TSLSearchException; + + /** + * Get a list of certificates form the local TSL database with the selected properties. + * + * @author TLenz + * @param dateTime - ... + * @param countries - String Array of countrie codes. For example new Sting[]{"AT","IT","BE"} + * @param serviceLevelStatus - String Array of ServiceLevelStatus. For example new String[]{"accredited","undersupervision"} + * @return List of certificates with the selected properties + */ + ArrayList getQualifiedCACertificates(Date dateTime, String[] countries, String[] serviceLevelStatus) + throws TSLEngineDiedException, TSLSearchException; + +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/exception/MitigatedTSLSecurityException.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/exception/MitigatedTSLSecurityException.java new file mode 100644 index 000000000..d58040539 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/exception/MitigatedTSLSecurityException.java @@ -0,0 +1,17 @@ +package at.gv.egovernment.moa.spss.tsl.exception; + +import iaik.xml.crypto.tsl.ex.TSLSecurityException; + +import org.xml.sax.Locator; + +public final class MitigatedTSLSecurityException extends + TSLSecurityException { + /** + * + */ + private static final long serialVersionUID = 1L; + + public MitigatedTSLSecurityException(Type t, Locator l) { + super(t, l); + } +} \ No newline at end of file diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/timer/TSLUpdaterTimerTask.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/timer/TSLUpdaterTimerTask.java new file mode 100644 index 000000000..6798a5db1 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/timer/TSLUpdaterTimerTask.java @@ -0,0 +1,150 @@ +package at.gv.egovernment.moa.spss.tsl.timer; + +import iaik.pki.store.certstore.CertStoreException; +import iaik.pki.store.truststore.TrustStoreException; +import iaik.xml.crypto.tsl.ex.TSLEngineDiedException; +import iaik.xml.crypto.tsl.ex.TSLSearchException; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.TimerTask; + +import at.gv.egovernment.moa.logging.LogMsg; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.MOAApplicationException; +import at.gv.egovernment.moa.spss.server.config.ConfigurationException; +import at.gv.egovernment.moa.spss.tsl.connector.TSLConnector; +import at.gv.egovernment.moa.spss.util.MessageProvider; + +public class TSLUpdaterTimerTask extends TimerTask { + + public static TSLConnector tslconnector_; + + @Override + public void run() { + + try { + update(); + } catch (TSLEngineDiedException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + + // TODO wenn update nicht erfolgreich, dann soll TSL-Trustprofil nicht zur + // Verfügung stehen. + + } catch (TSLSearchException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (ConfigurationException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (MOAApplicationException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (CertStoreException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (TrustStoreException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (CertificateException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (FileNotFoundException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } catch (IOException e) { + MessageProvider msg = MessageProvider.getInstance(); + Logger.error(new LogMsg(msg.getMessage("tsl.00", null)), e); + } + + } + + public static void update() throws TSLEngineDiedException, TSLSearchException, ConfigurationException, MOAApplicationException, CertStoreException, TrustStoreException, CertificateException, FileNotFoundException, IOException { +// MessageProvider msg = MessageProvider.getInstance(); +// +// //get TSl configuration +// ConfigurationProvider config = ConfigurationProvider.getInstance(); +// ConfigurationData configData = new IaikConfigurator().configure(config); +// TSLConfiguration tslconfig = config.getTSLConfiguration(); +// if (tslconfig != null) { +// +// Logger.info(new LogMsg(msg.getMessage("config.42", null))); +// +// // get certstore parameters +// CertStoreParameters[] certStoreParameters = configData.getPKIConfiguration().getCertStoreConfiguration().getParameters(); +// +// // iterate over all truststores +// Map mapTrustProfiles = config.getTrustProfiles(); +// Iterator it = mapTrustProfiles.entrySet().iterator(); +// while (it.hasNext()) { +// Map.Entry pairs = (Map.Entry)it.next(); +// TrustProfile tp = (TrustProfile) pairs.getValue(); +// if (tp.isTSLEnabled()) { +// TrustStoreProfile tsp = new TrustStoreProfileImpl(config, tp.getId()); +// TrustStoreProfile[] trustStoreProfiles = new TrustStoreProfile[1]; +// trustStoreProfiles[0] = tsp; +// +// Logger.debug(new LogMsg(msg.getMessage("config.43", new String[]{tp.getId()}))); +// +// TransactionId tid = new TransactionId("TSLConfigurator-" + tp.getId()); +// ArrayList tsl_certs = null; +// if (StringUtils.isEmpty(tp.getCountries())) { +// Logger.debug(new LogMsg(msg.getMessage("config.44", null))); +// +// // get certificates from TSL from all countries +// tsl_certs = tslconnector_.updateAndGetQualifiedCACertificates(new Date(), new String[]{"accredited","undersupervision"}); +// } +// else { +// Logger.debug(new LogMsg(msg.getMessage("config.44", null))); +// // get selected countries as array +// String countries = tp.getCountries(); +// String[] array = countries.split(","); +// for (int i = 0; i < array.length; i++) +// array[i] = array[i].trim(); +// +// // get certificates from TSL from given countries +// tsl_certs = tslconnector_.updateAndGetQualifiedCACertificates(new Date(), array, new String[]{"accredited","undersupervision"}); +// } +// +// // create store updater for each TSL enabled truststore +// Logger.debug(new LogMsg(msg.getMessage("config.45", null))); +// StoreUpdater storeUpdater = new StoreUpdater(certStoreParameters, trustStoreProfiles, tid); +// +// // convert ArrayList to X509Certificate[] +// X509Certificate[] addCertificates = new X509Certificate[tsl_certs.size()]; +// Iterator itcert = tsl_certs.iterator(); +// int i = 0; +// while(itcert.hasNext()) { +// File f = (File)itcert.next(); +// X509Certificate cert = new X509Certificate(new FileInputStream(f)); +// addCertificates[i] = cert; +// +// i++; +// } +// +// // get certificates to be removed +// X509Certificate[] removeCertificates = tp.getCertficatesToBeRemoved(); +// +// +// //Logger.debug(new LogMsg(msg.getMessage("config.44", null))); +// Logger.debug(new LogMsg("Remove " + removeCertificates.length + " certificates.")); +// storeUpdater.removeCertificatesFromTrustStores(removeCertificates, tid); +// +// +// Logger.debug(new LogMsg("Add " + addCertificates.length + " certificates.")); +// storeUpdater.addCertificatesToTrustStores(addCertificates, tid); +// +// // set the certifcates to be removed for the next TSL update +// tp.setCertificatesToBeRemoved(addCertificates); +// +// } +// } +// } + + + + } + +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/CertificateReader.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/CertificateReader.java new file mode 100644 index 000000000..763382aae --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/CertificateReader.java @@ -0,0 +1,155 @@ +package at.gv.egovernment.moa.spss.tsl.utils; +import iaik.pkcs.PKCS7CertList; +import iaik.pkcs.PKCSParsingException; +import iaik.security.provider.IAIK; +import iaik.utils.Util; +import iaik.x509.X509Certificate; +import iaik.xml.crypto.EccProviderAdapter; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.Security; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +// Copyright (C) 2011 IAIK +// http://jce.iaik.at +// +// Copyright (C) 2011 Stiftung Secure Information and +// Communication Technologies SIC +// http://www.sic.st +// +// All rights reserved. +// +// This source is provided for inspection purposes and recompilation only, +// unless specified differently in a contract with IAIK. This source has to +// be kept in strict confidence and must not be disclosed to any third party +// under any circumstances. Redistribution in source and binary forms, with +// or without modification, are permitted in any case! +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// + +public class CertificateReader { + + /** + * Filter for reading certificate files from a directory. + * The filter accepts a file if its name ends with + * ".cer", ".der", ".crt" + * or ".pem". + * + * @author Harald Bratko + * @author Konrad Lanz + */ + static class CertificateFileFilter implements FileFilter { + + /** + * Accepts a file if it is not a directory and its name ends with + * ".cer", ".der", ".crt" or ".pem". + * + * @see java.io.FileFilter#accept(java.io.File) + */ + public boolean accept(File file) { + String name = file.getName(); + if (name.endsWith(".der") || + name.endsWith(".cer") || + name.endsWith(".crt") || + name.endsWith(".pem")) + { + return true; + } else { + return false; + } + } + } + + + + /** + * Reads the certificates from the given directory and + * returns the certificates as sorted list (end user certificate first). + * @param directory + * @return + * @throws IOException + * @throws FileNotFoundException + * @throws CertificateException + * @throws Exception + */ + public static X509Certificate[] readCertificatesIntoArray(String directory) throws CertificateException, FileNotFoundException, IOException{ + File file = new File(directory); + File[] certificateFiles = file.listFiles(new CertificateFileFilter()); + int l = certificateFiles.length; + X509Certificate[] certs = new X509Certificate[l]; + for (int i=0; i readCertificates(String directory) throws CertificateException, FileNotFoundException, IOException{ + + return Arrays.asList(readCertificatesIntoArray(directory)); + } + + public static void main(String[] args) { + try { + + IAIK.addAsJDK14Provider(); + //IAIK.addAsProvider(); + //Security.addProvider(new IAIK()); + + // install ECC provider + Security.addProvider(EccProviderAdapter.getEccProvider()); + + String dir = "spec/examples/EU/AT/certs/on-tsl/chain/"; + List l = readCertificates(dir); + Iterator it = l.iterator(); + while (it.hasNext()) { + System.out.println(((X509Certificate)it.next()).getSubjectDN().getName()); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + + } + + public static X509Certificate[] p7read(File path) throws PKCSParsingException, FileNotFoundException, IOException { + PKCS7CertList p7certList = new PKCS7CertList( + new BufferedInputStream( + new FileInputStream( + path + ) + ) + ); + return p7certList.getCertificateList(); + } + } \ No newline at end of file diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/Mitigation.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/Mitigation.java new file mode 100644 index 000000000..a1635b86e --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/Mitigation.java @@ -0,0 +1,15 @@ +package at.gv.egovernment.moa.spss.tsl.utils; + +public class Mitigation extends iaik.xml.crypto.tsl.ex.SeverityAspect.Mitigation { + + String report_; + + public Mitigation(String report) { + report_ = report; + } + + @Override + public String getReport() { + return report_; + } +} \ No newline at end of file diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEUImportFromFileContext.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEUImportFromFileContext.java new file mode 100644 index 000000000..453ee2bb1 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEUImportFromFileContext.java @@ -0,0 +1,140 @@ +package at.gv.egovernment.moa.spss.tsl.utils; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URL; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import org.sqlite.SQLiteErrorCode; + +import iaik.util.logging.Log; +import iaik.util.logging._l; +import iaik.util.logging.Log.MultiThreadLoggingGroup; +import iaik.xml.crypto.tsl.DbTables; +import iaik.xml.crypto.tsl.TSLImportFromFileContext; +import iaik.xml.crypto.tsl.TSLOpenURIException; +import iaik.xml.crypto.tsl.constants.Countries; +import iaik.xml.crypto.tsl.ex.TSLExceptionB; +import iaik.xml.crypto.tsl.ex.ThrowableAndLocatorAndMitigation; +import iaik.xml.crypto.tsl.ex.SeverityAspect.Severity; +import iaik.xml.crypto.tsl.fetch.TopLevelTslFetchContext; + +public class TSLEUImportFromFileContext extends TopLevelTslFetchContext { + + public TSLEUImportFromFileContext( + Countries euTerritory, + URL euTslURL, + String workingdirectory, + boolean sqlMultithreaded, + boolean throwExceptions, + boolean logExceptions, + boolean throwWarnings, + boolean logWarnings, + boolean nullRedundancies) { + + super( + euTerritory, + euTslURL, + workingdirectory, + sqlMultithreaded, + throwExceptions, + logExceptions, + throwWarnings, + logWarnings, + nullRedundancies); + + } + + public List getErrorsAndWarnings() { + List errorsAndWarnings = new ArrayList(); + errorsAndWarnings.addAll(this.fatals_); + errorsAndWarnings.addAll(this.faildTransactions_); + errorsAndWarnings.addAll(this.warnings_); + + return errorsAndWarnings; + } + + @Override + public boolean normalizeXML() { + return true; + } + + @Override + public Object throwException(Throwable e, Method enclosingMethod, + Object thisObject, Object[] parameters) { + + if (enclosingMethod != null){ + if ( + e instanceof TSLOpenURIException && + enclosingMethod.getName().equals("processUrl") && + TSLImportFromFileContext.class.isAssignableFrom(enclosingMethod.getDeclaringClass()) && + parameters[1] instanceof File && + e.getCause() instanceof IOException && + parameters[0] instanceof URL + ){ + + _l.err("Ignoring download error using old: " + parameters[0],null); + wrapException(e); + return parameters[1]; + } + } + + //we allow each and every funny stuff from the EU as long as it's not insecure + if (e instanceof TSLExceptionB){ + TSLExceptionB ve = (TSLExceptionB) e; + Severity s = ve.getSeverity(); + if ( s != null && s.ordinal() < Severity.insecure.ordinal()){ + _l.err("Ignored Exception: ",ve); +// if(logExceptions_){ + warnings_.add( + new ThrowableAndLocatorAndMitigation( + ve, null, ve.getLocator(), ve.getMitigation() + ) + ); +// } + return null; + } + } + + + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + + @Override + public Boolean doesViolateRawHash(SQLException e, byte[] rawHash) { + + String msg = e.getMessage(); + return ( + msg.startsWith("["+SQLiteErrorCode.SQLITE_CONSTRAINT.name()+"]") && + msg.contains("column " + DbTables.TSLDownload.C.rawHash + " is not unique") + ); + } + + public MultiThreadLoggingGroup getLoggingGroup() { + return this; + } + + StringBuilder log = new StringBuilder(); + + public void flushLog() { + if (log != null && log.length() > 0) { + Thread currentThread = Thread.currentThread(); + String ncName = getNcName(currentThread); + + synchronized (log) { + print( + "<" + ncName + " state=\"" + currentThread.getState() + "\" " + " id=\"" + currentThread.getId() + "\">\n" + + log.toString() + "\n"); + log.setLength(0); + } + } + } + + public void print(Object msg) { + Log.print(msg); + } + +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEvaluationContext.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEvaluationContext.java new file mode 100644 index 000000000..a656f1177 --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLEvaluationContext.java @@ -0,0 +1,134 @@ +package at.gv.egovernment.moa.spss.tsl.utils; + +import iaik.util.logging.Log.MultiThreadLoggingGroup; +import iaik.util.logging.Log; +import iaik.util.logging._l; +import iaik.xml.crypto.tsl.BaseClass; +import iaik.xml.crypto.tsl.SIEExtensionChecker; +import iaik.xml.crypto.tsl.constants.Countries; +import iaik.xml.crypto.tsl.ex.TSLSIEExtensionException; +import iaik.xml.crypto.tsl.ex.SeverityAspect.Mitigation; +import iaik.xml.crypto.tsl.sie.gen.CriteriaListType; +import iaik.xml.crypto.tsl.sie.gen.KeyUsageBitType; +import iaik.xml.crypto.tsl.sie.gen.KeyUsageType; +import iaik.xml.crypto.tsl.sie.gen.ObjectFactory; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public final class TSLEvaluationContext extends iaik.xml.crypto.tsl.TSLEvaluationContext { + + public TSLEvaluationContext( + String workingdirectory, + boolean sqlMultithreaded, + boolean throwExceptions, + boolean logExceptions, + boolean throwWarnings, + boolean logWarnings) { + super(workingdirectory, + sqlMultithreaded, + throwExceptions, + logExceptions, + throwWarnings, + logWarnings); + } + + @Override + public Object throwException(Throwable e, Method enclosingMethod, + Object thisObject, Object[] parameters) { + + if (e instanceof TSLSIEExtensionException + && e.getMessage() == TSLSIEExtensionException.NO_KEYUSEAGE_NOR_POLICYSET) { + + CriteriaListType criteriaList = (CriteriaListType) parameters[1]; + + _l.warn(criteriaList.getDescription()); + + String description = criteriaList.getDescription(); + if (description + .trim() + .equals( + "This service issues qualified certificates for e-signing and " + + "e-authentication within the same process. The Relaying Party shall " + + "make distinction by inspection of keyUsage field contents - " + + "e-signature certificates have non-repudation bit set exclusively.")) { + criteriaList.setAssert(SIEExtensionChecker.Asssert.all.toString()); + + ObjectFactory of = new ObjectFactory(); + KeyUsageType ku = of.createKeyUsageType(); + KeyUsageBitType kb = of.createKeyUsageBitType(); + kb.setName(SIEExtensionChecker.KeyUseageBit.nonRepudiation + .toString()); + kb.setValue(true); + ku.getKeyUsageBit().add(kb); + criteriaList.getKeyUsage().add(ku); + + Object mitigatedResult = null; + try { + mitigatedResult = enclosingMethod.invoke(thisObject, parameters); + + } catch (IllegalAccessException e1) { + wrapException(e1); + } catch (InvocationTargetException e1) { + wrapException(e1); + } + + if (mitigatedResult != null) { + wrapException(e, criteriaList.sourceLocation(), new Mitigation() { + @Override + public String getReport() { + return "Fixed invalid criteria list"; + } + }); + return mitigatedResult; + } + + } + } + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + + @Override + protected long howLongWaitForThreads() { + return 10000; + } + + @Override + protected BaseClass getCurrentBaseClass() { + //TODO check whether we can avoid by redesign to focus this only on import + return null; + } + + @Override + public boolean normalizeXML() { + return true; + } + + public Countries getExpectedTerritory() { + return null; + } + + public MultiThreadLoggingGroup getLoggingGroup() { + return this; + } + + StringBuffer log = new StringBuffer(); + + public void flushLog() { + if (log != null && log.length() > 0) { + synchronized (System.out) { + Thread currentThread = Thread.currentThread(); + print("# # # " + getHint() + " Thread: " + + currentThread.getName() + "(" + currentThread.getId() + + ") collected logs - BEGIN # # #\n" + log.toString() + "# # # " + + getHint() + " Thread: " + currentThread.getName() + + "(" + currentThread.getId() + ") collected logs - END # # #\n"); + } + log = null; + } + } + + public void print(Object msg) { + Log.print(msg); + } +} \ No newline at end of file diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java new file mode 100644 index 000000000..f0dbd779e --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java @@ -0,0 +1,788 @@ +package at.gv.egovernment.moa.spss.tsl.utils; + +import iaik.util.logging._l; +import iaik.util.logging.Log.MultiThreadLoggingGroup; +import iaik.utils.RFC2253NameParserException; +import iaik.utils.Util; +import iaik.util._; +import iaik.xml.crypto.dsig.keyinfo.X509DataImpl; +import iaik.xml.crypto.tsl.DbTables; +import iaik.xml.crypto.tsl.TSLConstants; +import iaik.xml.crypto.tsl.TSLContext; +import iaik.xml.crypto.tsl.TSLEngine; +import iaik.xml.crypto.tsl.TSLImportContext; +import iaik.xml.crypto.tsl.TSLOpenURIException; +import iaik.xml.crypto.tsl.TSLThreadContext; +import iaik.xml.crypto.tsl.ValidationFixupFilter; +import iaik.xml.crypto.tsl.ValidationFixupFilter.AttributeValueFixup; +import iaik.xml.crypto.tsl.ValidationFixupFilter.ElementStringValueFixup; +import iaik.xml.crypto.tsl.ValidationFixupFilter.FixedSaxLevelValidationExcption; +import iaik.xml.crypto.tsl.ValidationFixupFilter.Fixup; +import iaik.xml.crypto.tsl.ValidationFixupFilter.LocalNameFixup; +import iaik.xml.crypto.tsl.constants.Countries; +import iaik.xml.crypto.tsl.ex.LocatorAspect; +import iaik.xml.crypto.tsl.ex.TSLEngineFatalException; +import iaik.xml.crypto.tsl.ex.TSLRuntimeWarning; +import iaik.xml.crypto.tsl.ex.TSLSecurityException; +import iaik.xml.crypto.tsl.ex.TSLVerificationException; +import iaik.xml.crypto.tsl.ex.ThrowableAndLocatorAndMitigation; +import iaik.xml.crypto.tsl.ex.TSLSecurityException.Type; +import iaik.xml.crypto.tsl.gen.DigitalIdentityType; +import iaik.xml.crypto.tsl.verify.TSLDOMErrorHandler; +import iaik.xml.crypto.tsl.verify.TSLValidationException; +import iaik.xml.crypto.tsl.verify.TslKeySelector; +import iaik.xml.crypto.utils.KeySelectorImpl.X509KeySelectorResultImpl; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import javax.xml.bind.Unmarshaller; +import javax.xml.crypto.AlgorithmMethod; +import javax.xml.crypto.KeySelectorException; +import javax.xml.crypto.dsig.keyinfo.X509Data; + +import org.apache.log4j.Logger; +import org.sqlite.SQLiteErrorCode; +import org.w3c.dom.DOMError; +import org.w3c.dom.Node; +import org.xml.sax.Locator; +import org.xml.sax.SAXParseException; + +import at.gv.egovernment.moa.spss.tsl.connector.TSLConnector; +import at.gv.egovernment.moa.spss.tsl.exception.MitigatedTSLSecurityException; + +/** + * + */ + +public class TSLImportFromFileContext extends iaik.xml.crypto.tsl.TSLImportFromFileContext { + + static Logger l = Logger.getLogger(TSLImportFromFileContext.class); + + public static final class ExceptionalMitigation extends Mitigation { + public ExceptionalMitigation(String report) { + super(report); + } + } + + public static final class FixedValidationMitigation extends Mitigation { + public FixedValidationMitigation(String report) { + super(report); + } + } + + private final String baseuri_; + private Map> + trustAnchorsWrongOnEuTsl_; + + public TSLImportFromFileContext( + Countries expectedTerritory, + URL url, + Number otherTslPointerId, + String workingdirectory, + boolean sqlMultithreaded, + boolean throwExceptions, + boolean logExceptions, + boolean throwWarnings, + boolean logWarnings, + boolean nullRedundancies, + String baseuri, + Map > trustAnchorsWrongOnEuTsl, + TSLThreadContext parentContext) { + super( + expectedTerritory, + url, + otherTslPointerId, + workingdirectory, + sqlMultithreaded, + throwExceptions, + logExceptions, + throwWarnings, + logWarnings, + nullRedundancies, + parentContext); + baseuri_ = baseuri; + trustAnchorsWrongOnEuTsl_ = trustAnchorsWrongOnEuTsl; + } + + public List getErrorsAndWarnings() { + List errorsAndWarnings = new ArrayList(); + errorsAndWarnings.addAll(this.fatals_); + errorsAndWarnings.addAll(this.faildTransactions_); + errorsAndWarnings.addAll(this.warnings_); + + return errorsAndWarnings; + } + + /* (non-Javadoc) + * @see iaik.xml.crypto.tsl.TSLImportFromFileContext#getbaseURI() + */ + @Override + public String getbaseURI() { + return this.baseuri_; + } + + //@Override + protected RuntimeException wrapException(Throwable t, Locator l, Mitigation m) { + return super.wrapException(t, l, m); + } + + @Override + public synchronized void throwException(Throwable e) { + + if (e instanceof TSLValidationException) { + // we do not throw dom validation errors for testing + // and just collect them + wrapException(e); + + } else if (e instanceof TSLVerificationException) { + // we do not throw verification errors for testing + // and just collect them + + if (Boolean.valueOf(_.getSysProperty(TSLSecurityException.Type.NO_TSL_SIGNATURE + .getClass().getName(), "true")) + && ((TSLVerificationException) e).getType() == TSLSecurityException.Type.NO_TSL_SIGNATURE) { + + //TSL with no signature are ignored!!!! + l.warn("TSL IS NOT SIGNED! " + + this.expectedTerritory_.name() + " TSL ignored."); + } + + if (Boolean.valueOf(_.getSysProperty(TSLSecurityException.Type.NON_CONFORMANT_REFERENCE_IN_TSL_SIGNATURE + .getClass().getName(), "true")) + && ((TSLVerificationException) e).getType() == TSLSecurityException.Type.NON_CONFORMANT_REFERENCE_IN_TSL_SIGNATURE) { + ((TSLVerificationException) e).setMitigation(Mitigation.IGNORED); + } + + if (Boolean.valueOf(_.getSysProperty(TSLSecurityException.Type.NON_CONFORMANT_TRANSFORMS_IN_TSL_SIGNATURE + .getClass().getName(), "true")) + && ((TSLVerificationException) e).getType() == TSLSecurityException.Type.NON_CONFORMANT_TRANSFORMS_IN_TSL_SIGNATURE) { + ((TSLVerificationException) e).setMitigation(Mitigation.IGNORED); + } + + if (Boolean.valueOf(_.getSysProperty(TSLSecurityException.Type.NON_CONFORMANT_TRANSFORM_IN_TSL_SIGNATURE + .getClass().getName(), "true")) + && ((TSLVerificationException) e).getType() == TSLSecurityException.Type.NON_CONFORMANT_TRANSFORM_IN_TSL_SIGNATURE) { + ((TSLVerificationException) e).setMitigation(Mitigation.IGNORED); + } + + if (Boolean.valueOf(_.getSysProperty(TSLSecurityException.Type.NON_CONFORMANT_C14N_IN_TSL_SIGNATURE + .getClass().getName(), "true")) + && ((TSLVerificationException) e).getType() == TSLSecurityException.Type.NON_CONFORMANT_C14N_IN_TSL_SIGNATURE) { + ((TSLVerificationException) e).setMitigation(Mitigation.IGNORED); + } + + wrapException(e); + + } else if (e instanceof FileNotFoundException) { + // we do not stop and continue processing + wrapException(e); + + } else if (e instanceof IllegalArgumentException) { + // we do not stop and continue processing + wrapException(e); + + } else { + // all other errors are treated as per default + super.throwException(e); + } + } + + /* (non-Javadoc) + * @see iaik.xml.crypto.tsl.TSLContext#throwException(java.lang.Exception, java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) + */ + @Override + public Object throwException( + Throwable e, Method enclosingMethod, Object thisObject, final Object[] parameters) { + + if (enclosingMethod != null){ + + if( + e instanceof FixedSaxLevelValidationExcption && + enclosingMethod.getDeclaringClass().equals(ValidationFixupFilter.class)){ + + + + wrapException(e, + ((LocatorAspect) e).getLocator(), + new FixedValidationMitigation("Performed SAX Level Fixup.")); + return null; + } + + if(e instanceof CertificateException && + enclosingMethod.getDeclaringClass().equals(TSLImportContext.class) && + enclosingMethod.getName().equals("parseCertificate")) { + + wrapException(e); + // ((DigitalIdentityType)parameters[1]).sourceLocation(); + + return null; + } + + if (e instanceof TSLValidationException&& + enclosingMethod.getDeclaringClass().equals(TSLDOMErrorHandler.class) && + enclosingMethod.getName().equals("handleError")) { + + if (parameters[0] instanceof DOMError) { + DOMError domError = (DOMError) parameters[0]; + + l.info(""+domError.getRelatedData()); + + // domError.getRelatedData().getClass().getField("") + + wrapException(e); + return Boolean.TRUE; + } + } + + if (e instanceof RFC2253NameParserException&& + enclosingMethod.getDeclaringClass().equals(TSLImportContext.class) && + enclosingMethod.getName().equals("getNormalizedDN") && + parameters[0] instanceof DigitalIdentityType ) { + + DigitalIdentityType digitalId = (DigitalIdentityType) parameters[0]; + + String subDN = digitalId.getX509SubjectName(); + + // String openSslRdnRegExp = "/([^=]+)=?(([^/]+)|\"([^\"]+)\""; + + String openSslRdnRegExp = "/([^=]+)=(\"([^\"]*)\"|([^/\"][^/]*)|(.{0}))"; + // 1 2 3 4 5 + // 1 matches Attribute + // 2 matches values + // 2 greedy matches properly quoted values + // 3 greedy matches values without quotes + // 4 matches the empty value + if (subDN.matches("^("+openSslRdnRegExp+")+$")){ + //trigger openSSL format error handling + + Object mitigatedResult = null; + + String[] rdns = subDN.substring(1, subDN.length()).split("/"); + + rdns = (String[]) _.reverseInPlace(rdns); + + subDN = "/"+_.implode("/", rdns); + + //for now we only support properly quoted values or such without quotes + + subDN = subDN.replaceAll(openSslRdnRegExp, "$1=\"$2$3\","); + subDN = subDN.substring(0, subDN.length()-1); + + digitalId.setX509SubjectName(subDN); + try { + mitigatedResult = enclosingMethod.invoke(thisObject, new Object[]{digitalId}); + + } catch (IllegalAccessException e1) { + wrapException(e1); + } catch (InvocationTargetException e1) { + wrapException(e1); + } + + if (mitigatedResult != null){ + wrapException(e, digitalId.sourceLocation(), new iaik.xml.crypto.tsl.ex.SeverityAspect.Mitigation() { + @Override + public String getReport() { + return "Converted OpenSSL SubjectDN"; + } + }); + return mitigatedResult; + } + } + + wrapException( + new TSLRuntimeWarning("Could not normalize :" + (digitalId).getX509SubjectName(), e), + digitalId.sourceLocation()); + + //if we cannot Normalize the DN we simply don't + return (digitalId).getX509SubjectName(); + } + + //TODO check if this is really needed for ESP TSL + if (e instanceof RFC2253NameParserException && + enclosingMethod.getDeclaringClass().equals(TSLImportContext.class) && + enclosingMethod.getName().equals("getNormalizedSubjectDN") && + parameters[0] instanceof X509Certificate ) { + + X509Certificate cert = (X509Certificate) parameters[0]; + + + wrapException(e, null); + //if we cannot Normalize the DN we simply don't + return cert.getSubjectDN().getName(); + } + + if ( + (expectedTerritory_ == Countries.MT || expectedTerritory_ == Countries.LT)&& + e instanceof TSLOpenURIException && + enclosingMethod.getDeclaringClass().equals(TSLImportFromFileContext.class) && + enclosingMethod.getName().equals("processUrl") && + parameters[1] instanceof File){ + + URL url = null; + if ( + e.getCause() instanceof FileNotFoundException && + parameters[0] instanceof URL && + (url =((URL)parameters[0])).getProtocol().equalsIgnoreCase("http") + ){ + try { + //Malta just changed their URL ... + if ("http://www.mca.org.mt/tsl/MT_TSL.xml".equalsIgnoreCase(url.toString())){ + url = new URL("http://www.mca.org.mt/sites/default/files/pageattachments/MT_TSL.xml"); + } else { + url = new URL("https", url.getHost(), url.getFile()); + } + } catch (MalformedURLException e1) { + wrapException(e1); + } + + Object mitigatedResult = null; + try { + + mitigatedResult = enclosingMethod.invoke(thisObject, new Object[]{url,parameters[1]}); + } catch (IllegalAccessException e1) { + wrapException(e1); + } catch (InvocationTargetException e1) { + wrapException(e1); + } + + if (mitigatedResult != null){ + wrapException(e, null, new iaik.xml.crypto.tsl.ex.SeverityAspect.Mitigation() { + @Override + public String getReport() { + return "Trying https:// ..."; + } + }); + return mitigatedResult; + } + } + + l.error("Ignoring download error using old: " + parameters[0], null); + wrapException(e); + return parameters[1]; + } + + if ( + e instanceof TSLSecurityException && + enclosingMethod.getDeclaringClass().equals(TSLContext.class) && + enclosingMethod.getName().equals("securityCheck") && + parameters[0] == TSLSecurityException.Type.UNTRUSTED_TSL_SIGNER && + trustAnchorsWrongOnEuTsl_.containsKey(expectedTerritory_) && + parameters[1] instanceof X509Certificate && + parameters[2] instanceof ListIterator + ) + { + final ListIterator trustAnchorsWrongOnEuTsl = + trustAnchorsWrongOnEuTsl_.get(expectedTerritory_); + + if (trustAnchorsWrongOnEuTsl != parameters[2]){ //prevents recursion + try { + enclosingMethod.invoke(thisObject, + new Object[]{parameters[0],parameters[1], trustAnchorsWrongOnEuTsl}); + } catch (IllegalAccessException e1) { + wrapException(e1); + } catch (InvocationTargetException e1) { + wrapException(e1); + } + wrapException(e, getLocator(), + new iaik.xml.crypto.tsl.ex.SeverityAspect.Mitigation(){ + @Override + public String getReport() { + return "make an exception for " + expectedTerritory_ + " who have the wrong certificate in " + + "the EU TSL and allow the certificate " + + parameters[1]; + } + }); + return null; + } + X509Certificate crt = (X509Certificate)parameters[1]; + + File f = new File("./wrong/"+expectedTerritory_+"/", + _.toHexString(getFingerPrint(crt, + new byte[TSLConstants.CertHash.LENGTH]))+".der"); + File parent = f.getParentFile(); + if(!parent.exists() && !parent.mkdirs()){ + throw new IllegalStateException("Couldn't create dir: " + parent); + } + + if (!f.exists()){ + try { + OutputStream os = new BufferedOutputStream( + new FileOutputStream(f) + ); + os.write(crt.getEncoded()); + os.close(); + } catch (Exception e1) { + e1.printStackTrace(); + System.exit(1); + } + } + + //continue ... + } + + if ( + ( expectedTerritory_ == Countries.SK || + expectedTerritory_ == Countries.SE || + expectedTerritory_ == Countries.NO || + expectedTerritory_ == Countries.PL) && + e instanceof KeySelectorException && + enclosingMethod.getDeclaringClass().equals(TslKeySelector.class) && + enclosingMethod.getName().equals("select") && + parameters[0] instanceof X509DataImpl){ + + X509DataImpl x509Data = (X509DataImpl) parameters[0]; + AlgorithmMethod method = (AlgorithmMethod) parameters[2]; + + List certificates = new ArrayList(); + + Iterator x509content = x509Data.getContent().iterator(); + while (x509content.hasNext()) { + Object element = x509content.next(); + if (element instanceof X509Certificate) { + X509Certificate rawCert = (X509Certificate)element; + certificates.add(rawCert); + } + } + + if (!certificates.isEmpty()) { + X509Certificate[] rawCertificates = new X509Certificate[certificates.size()]; + certificates.toArray(rawCertificates); + certificates.clear(); + Iterator certs = null; + try { + // convert the certificates to IAIK certifcates + iaik.x509.X509Certificate[] iaikCertificates = Util.convertCertificateChain(rawCertificates); + // sort the certificate chain + iaik.x509.X509Certificate[] sortedChain = Util.arrangeCertificateChain(iaikCertificates, false); + if (sortedChain == null) { + // chain could not be sorted; maybe there are two different certificates + // containing the same public key; use the unsorted chain + certificates = Arrays.asList(iaikCertificates); + certs = certificates.iterator(); + } else { + certs = (Collections.nCopies(1, sortedChain[0])).iterator(); + certificates = Arrays.asList(sortedChain); + } + } catch (CertificateException e1) { + //cannot handle this throw error + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + + PublicKey oldPublicKey = null; + while (certs.hasNext()) { + + iaik.x509.X509Certificate cert = (iaik.x509.X509Certificate)certs.next(); + + boolean hit = false; + + PublicKey publicKey = cert.getPublicKey(); + + // failReason_ = ""; + + // Does the certificate provide a key for the requested algorithm? + try { + KeyFactory kfac = KeyFactory.getInstance(method.getAlgorithm()); + kfac.translateKey(publicKey); + hit = true; + if (oldPublicKey != null) { + if (!publicKey.equals(oldPublicKey)) { + //cannot handle this throw error + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + } + oldPublicKey = publicKey; + } catch (NoSuchAlgorithmException e1) { + //cannot handle this throw error + return super.throwException(e, enclosingMethod, thisObject, parameters); + } catch (InvalidKeyException e1) { + //cannot handle this throw error + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + if (hit) { + //make an exception for SK, SE who violate XMLDSig ds:KeyInfo/ds:X509Data + wrapException(e, getLocator(), + new ExceptionalMitigation("make an exception for " + expectedTerritory_ + " who violate XMLDSig ds:KeyInfo")); + return new X509KeySelectorResultImpl(publicKey, certificates, null); + } + } + } + } + +// //TODO: CONSIDER, IF WE REALLY WANT THIS PART OF CODE! +// //ugly hack to accept a certificate which uses a crazy X509SubjectName!! +// if ( expectedTerritory_ == Countries.DK && +// e instanceof KeySelectorException && +// parameters[0] instanceof X509DataImpl){ +// if (e.getMessage().equals("KeyInfo X509SubjectName (CN=Adam Arndt Digst,serialNumber=CVR:34051178-RID:25902029,O=Digitaliseringsstyrelsen // CVR:34051178,C=DK) does not match SubjectDN (serialNumber=CVR:34051178-RID:25902029+CN=Adam Arndt Digst,O=Digitaliseringsstyrelsen // CVR:34051178,C=DK) of KeyInfo X509Certificate.\n"+ +// "Any X509IssuerSerial, X509SKI, and X509SubjectName elements that appear MUST refer to the certificate or certificates containing the validation key.")) { +// +// X509DataImpl x509DataImpl = (X509DataImpl) parameters[0]; +// +// Node child = x509DataImpl.getNode().getFirstChild().getNextSibling(); +// Node child1 = x509DataImpl.getNode().getFirstChild(); +// +// x509DataImpl.getNode().removeChild(child); +// x509DataImpl.getNode().removeChild(child1); +// +// +// parameters[0] = (X509Data) x509DataImpl +// +// Object mitigatedResult = null; +// try { +// +// mitigatedResult = enclosingMethod.invoke(thisObject, parameters); +// } catch (IllegalAccessException e1) { +// wrapException(e1); +// } catch (InvocationTargetException e1) { +// wrapException(e1); +// } +// +// if (mitigatedResult != null){ +// wrapException(e, null, new Mitigation(null) { +// @Override +// public String getReport() { +// return "Deleted wrong X509SubjectName from XMLDSIG Signature."; +// } +// }); +// return mitigatedResult; +// } +// } +// } + + + } else { + if (e instanceof MitigatedTSLSecurityException){ + // we allow to mitigate Security exceptions for testing + // and collect them + wrapException(e); + return null; + + } else if (e instanceof FixedSaxLevelValidationExcption) { + // we allow to mitigate Sax Level Fixup for testing + // and collect them + wrapException(e); + return null; + } + } + + return super.throwException(e, enclosingMethod, thisObject, parameters); + } + + + + @Override + public Unmarshaller createTSLUnmarshaller() + throws TSLEngineFatalException { + if (expectedTerritory_ == Countries.FI){ + //we cannot fix FI at SAX Level and re-validate + return TSLEngine.createTSLUnmarshaller(false); + } + return super.createTSLUnmarshaller(); + } + + @Override + public String compressStatus(String status) { + if(expectedTerritory_ == Countries.EL){ + //fix the whitespace in Greece TSL + status = status.trim(); + } + return super.compressStatus(status); + } + + + @Override + public String compressServiceType(String sType) { + if(expectedTerritory_ == Countries.EL){ + //fix the whitespace in Greece TSL + sType = sType.trim(); + } + return super.compressServiceType(sType); + } + + + @Override + public iaik.xml.crypto.tsl.ValidationFixupFilter.Fixup getSaxLevelValidationFixup(SAXParseException e) { + + if (expectedTerritory_ == Countries.ES && getDownloadLocation().toString().contains(".es/")){ + if (e.getMessage().equals("cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'tslx:CertSubjectDNAttributeType'.")){ + return new LocalNameFixup("CertSubjectDNAttributeType","CertSubjectDNAttribute",e, this); + } + } + + if (expectedTerritory_ == Countries.MT && getDownloadLocation().toString().contains(".mt/")){ + if (e.getMessage().equals("cvc-complex-type.2.4.a: Invalid content was found starting with element 'tsl:TSLPolicy'. One of '{\"http://uri.etsi.org/02231/v2#\":TSLLegalNotice}' is expected.")){ + return new LocalNameFixup("TSLPolicy","TSLLegalNotice",e, this); + } + } + + if (e.getMessage().equals("cvc-complex-type.3.2.2: Attribute 'assert' is not allowed to appear in element 'ecc:otherCriteriaList'.")){ + return new LocalNameFixup("otherCriteriaList","CriteriaList",e, this); + } else if (e.getMessage().startsWith("cvc-datatype-valid.1.2.1: '") && e.getMessage().endsWith("' is not a valid value for 'dateTime'.")){ + return new ElementStringValueFixup("-(.)-","-0$1-",e, this); + } else if (e.getMessage().startsWith("cvc-type.3.1.3: The value '") && e.getMessage().endsWith("' of element 'tsl:ListIssueDateTime' is not valid.")){ + // return new DateTimeFixup(); + } else if (e.getMessage().startsWith("cvc-datatype-valid.1.2.1: '") && e.getMessage().endsWith("' is not a valid value for 'base64Binary'.")){ + return new ElementStringValueFixup("(\\s)=([^=]+)","$1$2",e, this); + } else if (e.getMessage().startsWith("cvc-type.3.1.3: The value '") && e.getMessage().endsWith("' of element 'tsl:X509Certificate' is not valid.")){ + // return new Base64BinaryFixup(); + } else if (e.getMessage().startsWith("cvc-datatype-valid.1.2.1: '") && e.getMessage().endsWith("' is not a valid value for 'anyURI'.")){ + + //TODO only for sweden and find a better discriminatory than the URI +// if (expectedTerritory_ == Countries.SE){ +// return new ElementStringValueFixup( +// "-http://www.pts.se/upload/Ovrigt/Internet/Branschinformation/Trusted%20List%20SE%20MR.xml", +// "http://www.pts.se/upload/Ovrigt/Internet/Branschinformation/Trusted%20List%20SE%20MR.xml"); + return new ElementStringValueFixup("-http://www.pts.se/", "http://www.pts.se/", e, this); +// } + + + } else if (e.getMessage().startsWith("cvc-datatype-valid.1.2.1: '") && e.getMessage().endsWith("' is not a valid value for 'NCName'.")){ + if (expectedTerritory_ == Countries.CY || expectedTerritory_ == Countries.LV){ + return new AttributeValueFixup("","Id","(.+)","x$1",e, this); + } + } else if (e.getMessage().startsWith("cvc-complex-type.2.3: Element '") && e.getMessage().endsWith("' cannot have character [children], because the type's content type is element-only.")) { + //cvc-complex-type.2.3: Element 'tsl:ServiceDigitalIdentity' cannot have character [children], because the type's content type is element-only. + if (expectedTerritory_ == Countries.FI){ +// return new ElementStringValueFixup("(\\s*)-(\\s*)","$1$2",e, this); + return new Fixup(e, this){ + { + changed_ = true; + fixupPerformed(); + } + @Override + public String fixup(String input) { + return null; + } + + @Override + public Mitigation getMitigation() { + return new Mitigation("Ignored"); + } + + }; + } + } + + if (e.getMessage().startsWith("cvc-elt")){ + + } else if (e.getMessage().startsWith("cvc-type")) { + + } else if (e.getMessage().startsWith("cvc-complex-type")) { + + } else if (e.getMessage().startsWith("cvc-datatype-valid")) { + + } else if (e.getMessage().startsWith("cvc-attribute")) { + + } + //cvc-complex-type.2.4.a: Invalid content was found starting with element 'tsl:TSLPolicy'. One of '{"http://uri.etsi.org/02231/v2#":TSLLegalNotice}' is expected. + + //cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'ecc:PolicySet' + //cvc-complex-type.2.4.a: Invalid content was found starting with element 'ecc:Identifier'. One of '{"http://uri.etsi.org/02231/v2/additionaltypes#":AttributeOID}' is expected. + //cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 'tsl:ExtensionOID'. + //cvc-type.3.1.3: The value '-http://www.pts.se/upload/Ovrigt/Internet/Branschinformation/Trusted%20List%20SE%20MR.xml' of element 'tsl:URI' is not valid.,locator=[node=null,object=null,url=file:/C:/Gesichert/Development/projects/TSL/./hashcache/900BA6AB3702EC9518627496749AA28129C56100.tsl.xml,line=109,col=118,offset=-1]] + + return super.getSaxLevelValidationFixup(e); + } + + @Override + public void securityCheck(Type securityCheckType, + java.security.cert.X509Certificate[] certs, + ListIterator expectedTslSignerCerts) { + + //TODO check whether we always want to do that to make sure we use the endentity + try { + certs = Util.convertCertificateChain(certs); + } catch (CertificateException e) { + throwException(e); + } + certs = Util.arrangeCertificateChain((iaik.x509.X509Certificate[]) certs, false); + super.securityCheck(securityCheckType, certs, expectedTslSignerCerts); + } + + + @Override + public boolean doRollback() { + //accept each and every TSL ... even partially ... for testing + return false; +// return true; + } + + @Override + public Boolean doesViolateRawHash(SQLException e, byte[] rawHash) { + + String msg = e.getMessage(); + + l.info(msg); + return( + msg.startsWith("["+SQLiteErrorCode.SQLITE_CONSTRAINT.name()+"]") && + msg.contains("column " + DbTables.TSLDownload.C.rawHash + " is not unique") + ); + } + + @Override + protected Long getLocalLastModified(File targetFile) { + return super.getLocalLastModified(targetFile); + } + @Override + protected long howLongWaitForThreads() { + // TODO Auto-generated method stub + return 10000; + } + + @Override + protected boolean normalizeXML() { + return true; + } + public MultiThreadLoggingGroup getLoggingGroup() { + return this; + } + + StringBuilder log = new StringBuilder(); + + public void flushLog() { + if (log != null && log.length() > 0) { + Thread currentThread = Thread.currentThread(); + String ncName = getNcName(currentThread); + synchronized (log) { + parentContext_.print("<" + ncName + " state=\"" + currentThread.getState() + + "\" " + " id=\"" + currentThread.getId() + "\">\n" + log.toString() + "\n"); + parentContext_.flushLog(); + log.setLength(0); + } + } + } + + /** + * Collect all the logs for this context + * @see iaik.util.logging.Log.MultiThreadLoggingGroup#print(java.lang.Object) + */ + public void print(Object msg) { + synchronized (log) { + log.append(msg); + } + } + +} \ No newline at end of file diff --git a/spss/server/serverlib/src/main/resources/resources/properties/spss_messages_de.properties b/spss/server/serverlib/src/main/resources/resources/properties/spss_messages_de.properties index fbd0cd7c2..60786dc8a 100644 --- a/spss/server/serverlib/src/main/resources/resources/properties/spss_messages_de.properties +++ b/spss/server/serverlib/src/main/resources/resources/properties/spss_messages_de.properties @@ -80,6 +80,7 @@ 2280=Die Angabe XMLContent wird derzeit nicht unterstützt 2281=XML-Supplement kann nicht serialisiert werden (Reference="{0}") 2282=Datenobjekt mit der URI={0} wurde dem Request nicht bereit gestellt +2290=Fehler bei der QC bzw. SSCD Prüfung via TSL 2900=Interner Server-Fehler @@ -143,6 +144,16 @@ config.33=External URIs are allowed. Maybe a URI blacklist exists. config.34=Blacklisted URI: {0}. config.35=External URIs not allowed. config.36=No blacklisted URIs given. +config.37=Fehler beim Erstellen der TSL Konfiguration: Name des TSL Arbeits-Verzeichnisses konnte nicht in eine URL umgewandet werden (Wert="{0}") +config.38=Fehler beim Erstellen der TSL Konfiguration: Das TSL Arbeits-Verzeichnis zeigt nicht auf ein existierendes Objekt, das kein Verzeichnis ist (Wert="{0}") +config.39=TSL Konfguration: Kein Attribut "{0}" angegeben oder Attribut konnte nicht ausgewertet werden. Verwenden Default-Wert ("{1}") +config.40=Fehler beim Erstellen der TSL Konfiguration: Es wurde mindestens ein TrustProfile mit aktivierter TSL-Unterstützung konfiguriert. Die allgemeine TSL-Konfiguration ist jedoch fehlerhaft. +config.41=Initialisiere TSL Bibliothek +config.42=Start updating TSL enabled truststores +config.43=Update truststore with id "{0}" +config.44=Retrieve certificates from TSL +config.45=Create store updater +config.46=Start periodical TSL update task at {0} and then every {1} milliseconds handler.00=Starte neue Transaktion: TID={0}, Service={1} handler.01=Aufruf von Adresse={0} @@ -156,4 +167,6 @@ handler.07=SOAP Request empfangen: Request={0} invoker.00=Das Signature Environment konnte nicht validierend geparst werden invoker.01=Keine passende Transformationskette gefunden (Index={0}) invoker.02=Der Hashwert der Transformation stimmt nicht überein (Index={0}) -invoker.03=Signatorzertifikat aus Trustprofile mit id={0} konnte nicht geparst werden (Dateiname={1}) \ No newline at end of file +invoker.03=Signatorzertifikat aus Trustprofile mit id={0} konnte nicht geparst werden (Dateiname={1}) + +tsl.00=Aktulisierung der TSL konnte nicht durchgeführt werden. TrustProfile mit aktiviertem TSL-Support stehen nicht zur Verfügung. \ No newline at end of file diff --git a/spss/server/serverws/.classpath b/spss/server/serverws/.classpath index b8d52d398..af4743f8a 100644 --- a/spss/server/serverws/.classpath +++ b/spss/server/serverws/.classpath @@ -1,30 +1,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + diff --git a/spss/server/serverws/.settings/org.eclipse.wst.common.component b/spss/server/serverws/.settings/org.eclipse.wst.common.component index 784056e0f..b8a1c3877 100644 --- a/spss/server/serverws/.settings/org.eclipse.wst.common.component +++ b/spss/server/serverws/.settings/org.eclipse.wst.common.component @@ -5,6 +5,9 @@ uses + + uses + diff --git a/spss/server/serverws/.settings/org.eclipse.wst.common.project.facet.core.xml b/spss/server/serverws/.settings/org.eclipse.wst.common.project.facet.core.xml index a801c94a0..df66dd21b 100644 --- a/spss/server/serverws/.settings/org.eclipse.wst.common.project.facet.core.xml +++ b/spss/server/serverws/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -2,6 +2,6 @@ - - \ No newline at end of file + + diff --git a/spss/server/serverws/pom.xml b/spss/server/serverws/pom.xml index f18a75d15..dd0027df6 100644 --- a/spss/server/serverws/pom.xml +++ b/spss/server/serverws/pom.xml @@ -63,6 +63,10 @@ MOA moa-common + + iaik.prod + iaik_ixsil + iaik.prod diff --git a/spss/server/tools/.classpath b/spss/server/tools/.classpath index 8f14aea5e..a9bfad977 100644 --- a/spss/server/tools/.classpath +++ b/spss/server/tools/.classpath @@ -1,13 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3