From da64c825de6ad061f5c734630faf0d6e9606dc12 Mon Sep 17 00:00:00 2001 From: Christian Maierhofer Date: Thu, 23 Jun 2016 10:06:40 +0200 Subject: Added Profile configuration validation --- .../pdfas/common/exceptions/ErrorConstants.java | 4 + .../PdfAsSettingsValidationException.java | 49 ++++++++ .../at/gv/egiz/pdfas/lib/api/PdfAsFactory.java | 25 +++- .../impl/configuration/ConfigValidatorLoader.java | 108 +++++++++++++++++ pdf-as-pdfbox-2/build.gradle | 4 + .../pdfbox2/configuration/ProfileValidator.java | 131 +++++++++++++++++++++ ....pdfas.lib.configuration.ConfigurationValidator | 1 + .../egiz/pdfas/web/servlets/ExternSignServlet.java | 17 ++- 8 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsSettingsValidationException.java create mode 100644 pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/configuration/ConfigValidatorLoader.java create mode 100644 pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/configuration/ProfileValidator.java create mode 100644 pdf-as-pdfbox-2/src/main/resources/META-INF/services/at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/ErrorConstants.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/ErrorConstants.java index 7c2fb03c..d99299a9 100644 --- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/ErrorConstants.java +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/ErrorConstants.java @@ -22,8 +22,12 @@ public interface ErrorConstants { // Verification Errors + // Configuration Errors: public static final long ERROR_SET_INVALID_SETTINGS_OBJ = 13001; public static final long ERROR_INVALID_CERTIFICATE = 13002; public static final long ERROR_INVALID_PLACEHOLDER_MODE = 13003; + + //Validation Errors + public static final long ERROR_NO_CONF_VALIDATION_BACKEND = 14001; } diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsSettingsValidationException.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsSettingsValidationException.java new file mode 100644 index 00000000..869855ef --- /dev/null +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsSettingsValidationException.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright 2014 by E-Government Innovation Center EGIZ, Graz, Austria + * PDF-AS has been contracted by the E-Government Innovation Center EGIZ, a + * joint initiative of the Federal Chancellery Austria 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.egiz.pdfas.common.exceptions; + +/** + * Created with IntelliJ IDEA. + * User: afitzek + * Date: 9/10/13 + * Time: 10:54 AM + * To change this template use File | Settings | File Templates. + */ +public class PdfAsSettingsValidationException extends PdfAsException { + + /** + * + */ + private static final long serialVersionUID = 3277787631624822104L; + + + public PdfAsSettingsValidationException(String msgId) { + super(msgId); + } + + + public PdfAsSettingsValidationException(String msgId, Throwable e) { + super(msgId, e); + } +} diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java index cd0a4699..72d182ed 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/api/PdfAsFactory.java @@ -37,9 +37,10 @@ import java.io.OutputStream; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; -import java.lang.reflect.Field; import java.security.Provider; import java.security.Security; +import java.util.Map; +import java.util.Map.Entry; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -49,12 +50,16 @@ import javax.crypto.Cipher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException; import at.gv.egiz.pdfas.common.settings.ISettings; import at.gv.egiz.pdfas.lib.api.sign.SignParameter; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter; +import at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator; import at.gv.egiz.pdfas.lib.impl.PdfAsImpl; import at.gv.egiz.pdfas.lib.impl.SignParameterImpl; import at.gv.egiz.pdfas.lib.impl.VerifyParameterImpl; +import at.gv.egiz.pdfas.lib.impl.configuration.ConfigValidatorLoader; public class PdfAsFactory implements IConfigurationConstants { @@ -359,4 +364,22 @@ public class PdfAsFactory implements IConfigurationConstants { Package pack = PdfAsFactory.class.getPackage(); return pack.getImplementationVersion(); } + + /** + * Execute all loaded Configuration Validators + * + * @throws PdfAsSettingsValidationException + */ + public static void validateConfiguration(ISettings configuration) throws PdfAsSettingsValidationException{ + Map availableValidators = ConfigValidatorLoader.getAvailableValidators(); + if(availableValidators.isEmpty()){ + logger.info("No configuration validators available"); + } + for(Entry validatorEntry : availableValidators.entrySet()){ + logger.info("Running configuration validator: "+validatorEntry.getKey()); + validatorEntry.getValue().validate(configuration); + } + logger.info("All configuration validators succeded."); + + } } diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/configuration/ConfigValidatorLoader.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/configuration/ConfigValidatorLoader.java new file mode 100644 index 00000000..0e1e2580 --- /dev/null +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/configuration/ConfigValidatorLoader.java @@ -0,0 +1,108 @@ +package at.gv.egiz.pdfas.lib.impl.configuration; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.ServiceLoader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.ErrorConstants; +import at.gv.egiz.pdfas.common.exceptions.PDFASError; +import at.gv.egiz.pdfas.lib.api.Configuration; +import at.gv.egiz.pdfas.lib.backend.PDFASBackend; +import at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator; + +public class ConfigValidatorLoader implements ErrorConstants{ + /** The Constant logger. */ + private static final Logger logger = LoggerFactory + .getLogger(ConfigValidatorLoader.class); + + /** The configuration verifier loader. */ + private static ServiceLoader configurationValidator = ServiceLoader.load(ConfigurationValidator.class); + + /** The available verification backends. */ + private static Map availableValidators = new HashMap(); + + /** The Constant VALIDATOR_CONFIG. */ + public static final String VALIDATOR_CONFIG = "runtime.config.validator"; + + /** The default validator. */ + private static ConfigurationValidator defaultValidator = null; + + static { + logger.debug("building Configuration Validator"); + + Iterator backendIterator = configurationValidator.iterator(); + + while(backendIterator.hasNext()) { + ConfigurationValidator backend = backendIterator.next(); + logger.debug("Loading " + backend.getName() + " [" + backend.getClass().getName() + "]"); + availableValidators.put(backend.getName(), backend); + logger.debug("PDF-Backend added " + backend.getName()); + if(backend.usedAsDefault()) { + defaultValidator = backend; + logger.debug("PDF-Backend added as default " + backend.getName()); + } + } + + logger.debug("Configuration Validator Backends constructed"); + + if(defaultValidator != null) { + logger.debug("Default backend is " + defaultValidator.getName()); + } + } + + /** + * Gets the Configuration valdiator. + * + * @param configuration the configuration + * @return the validator backend + * @throws PDFASError the PDFAS error + */ + public static ConfigurationValidator getConfigurationValidator(Configuration configuration) throws PDFASError { + String backendName = configuration.getValue(VALIDATOR_CONFIG); + return getConfigurationValidator(backendName); + } + + /** + * Gets the Validator by name. + * + * @param name the name + * @return the validator backend + * @throws PDFASError the PDFAS error + */ + public static ConfigurationValidator getConfigurationValidator(String name) throws PDFASError { + if(name != null) { + if(availableValidators.containsKey(name)) { + return availableValidators.get(name); + } + throw new PDFASError(ERROR_NO_CONF_VALIDATION_BACKEND); + } + + if(defaultValidator != null) { + return defaultValidator; + } + + throw new PDFASError(ERROR_NO_CONF_VALIDATION_BACKEND); + } + + /** + * Gets the Configuration Validator. + * + * @return the validator backend + * @throws PDFASError the PDFAS error + */ + public static ConfigurationValidator getConfigurationValidator() throws PDFASError { + if(defaultValidator != null) { + return defaultValidator; + } + + throw new PDFASError(ERROR_NO_CONF_VALIDATION_BACKEND); + } + + public static Map getAvailableValidators(){ + return availableValidators; + } +} diff --git a/pdf-as-pdfbox-2/build.gradle b/pdf-as-pdfbox-2/build.gradle index 4fe4b427..f62604a3 100644 --- a/pdf-as-pdfbox-2/build.gradle +++ b/pdf-as-pdfbox-2/build.gradle @@ -25,9 +25,13 @@ dependencies { compile 'org.slf4j:jcl-over-slf4j:1.7.18' compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.2' compile group: 'org.apache.pdfbox', name: 'pdfbox-tools', version: '2.0.2' + testCompile group: 'org.apache.pdfbox', name: 'preflight', version: '2.0.2' compile group: 'commons-io', name: 'commons-io', version: '2.4' compile group: 'ognl', name: 'ognl', version: '3.0.6' testCompile group: 'junit', name: 'junit', version: '4.+' + compile group: 'com.github.jai-imageio', name: 'jai-imageio-jpeg2000', version: '1.3.0' + compile group: 'com.github.jai-imageio', name: 'jai-imageio-core', version: '1.3.1' + compile group: 'com.levigo.jbig2', name: 'levigo-jbig2-imageio', version: '1.6.5' } test { diff --git a/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/configuration/ProfileValidator.java b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/configuration/ProfileValidator.java new file mode 100644 index 00000000..8d02d1b3 --- /dev/null +++ b/pdf-as-pdfbox-2/src/main/java/at/gv/egiz/pdfas/lib/impl/pdfbox2/configuration/ProfileValidator.java @@ -0,0 +1,131 @@ +package at.gv.egiz.pdfas.lib.impl.pdfbox2.configuration; + +import iaik.asn1.ObjectID; +import iaik.asn1.structures.Name; +import iaik.x509.X509Certificate; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException; +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.common.settings.SignatureProfileSettings; +import at.gv.egiz.pdfas.lib.api.ByteArrayDataSource; +import at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator; +import at.gv.egiz.pdfas.lib.impl.pdfbox2.PDFBOXObject; +import at.gv.egiz.pdfas.lib.impl.stamping.TableFactory; +import at.gv.egiz.pdfas.lib.impl.stamping.pdfbox2.PDFBoxTable; +import at.gv.egiz.pdfas.lib.impl.status.ICertificateProvider; +import at.gv.egiz.pdfas.lib.impl.status.OperationStatus; +import at.knowcenter.wag.egov.egiz.table.Table; + +public class ProfileValidator implements ConfigurationValidator{ + + private static final String NAME = "PDFBOX_2_PROFILE_VALIDATOR"; + + private static final Logger logger = LoggerFactory + .getLogger(ProfileValidator.class); + + @Override + public void validate(ISettings settings) throws PdfAsSettingsValidationException{ + Set profileIds = new HashSet(); + + Iterator itKeys = settings.getFirstLevelKeys("sig_obj.types.") + .iterator(); + while (itKeys.hasNext()) { + String key = itKeys.next(); + String profile = key.substring("sig_obj.types.".length()); + + if (settings.getValue(key).equals("on")) { + profileIds.add(profile); + } + } + logger.debug("Validating "+profileIds.size()+ " Profiles."); + + ArrayList profileSettings = new ArrayList(); + + OperationStatus opState = new OperationStatus(settings, null, null); + + X509Certificate dummyCert = new X509Certificate(); + dummyCert.setSerialNumber(new BigInteger("123")); + Name n = new Name(); + n.addRDN(ObjectID.country, "AT"); + n.addRDN(ObjectID.locality, "Graz"); + n.addRDN(ObjectID.organization ,"test"); + n.addRDN(ObjectID.organizationalUnit ,"test"); + n.addRDN(ObjectID.commonName ,"testca"); + dummyCert.setIssuerDN(n); + dummyCert.setSubjectDN(n); + + ICertificateProvider certProvider = new DummyCertificateProvider(dummyCert); + + PDFBOXObject pdfBoxObject = new PDFBOXObject(opState); + PDDocument origDoc = new PDDocument(); + origDoc.addPage(new PDPage(PDRectangle.A4)); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + + origDoc.save(baos); + baos.close(); + origDoc.close(); + + pdfBoxObject.setOriginalDocument(new ByteArrayDataSource(baos.toByteArray())); + } catch (IOException e1) { + logger.info("Configuration Validation failed!"); + throw new PdfAsSettingsValidationException("Configuration Validationfailed!", e1); + } + + + for(String id:profileIds){ + SignatureProfileSettings profileSetting = new SignatureProfileSettings(id, settings); + profileSettings.add(profileSetting); + if(profileSetting.getValue("isvisible")!=null){ + if(profileSetting.getValue("isvisible").equals("false")){ + continue; + } + } + Table t; + try { + t = TableFactory.createSigTable(profileSetting, "main", opState, certProvider); + new PDFBoxTable(t, null, settings, pdfBoxObject); + } catch (Exception e) { + logger.info("Configuration Validation for profile "+id+" failed!"); + throw new PdfAsSettingsValidationException("Configuration Validation for profile "+id+" failed!", e); + } + + } + } + + @Override + public boolean usedAsDefault() { + return true; + } + + @Override + public String getName() { + return NAME; + } + + private class DummyCertificateProvider implements ICertificateProvider { + private X509Certificate cert; + public DummyCertificateProvider(X509Certificate cert) { + this.cert = cert; + } + public X509Certificate getCertificate() { + return cert; + } + + } + +} diff --git a/pdf-as-pdfbox-2/src/main/resources/META-INF/services/at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator b/pdf-as-pdfbox-2/src/main/resources/META-INF/services/at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator new file mode 100644 index 00000000..ac38ebbf --- /dev/null +++ b/pdf-as-pdfbox-2/src/main/resources/META-INF/services/at.gv.egiz.pdfas.lib.configuration.ConfigurationValidator @@ -0,0 +1 @@ +at.gv.egiz.pdfas.lib.impl.pdfbox2.configuration.ProfileValidator \ No newline at end of file diff --git a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java index b70539a4..f21447dd 100644 --- a/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java +++ b/pdf-as-web/src/main/java/at/gv/egiz/pdfas/web/servlets/ExternSignServlet.java @@ -40,6 +40,10 @@ import org.slf4j.LoggerFactory; import at.gv.egiz.pdfas.common.exceptions.PDFASError; import at.gv.egiz.pdfas.common.exceptions.PdfAsException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsException; +import at.gv.egiz.pdfas.common.exceptions.PdfAsSettingsValidationException; +import at.gv.egiz.pdfas.common.settings.ISettings; +import at.gv.egiz.pdfas.lib.api.PdfAsFactory; import at.gv.egiz.pdfas.lib.api.verify.VerifyParameter.SignatureVerificationLevel; import at.gv.egiz.pdfas.web.config.WebConfiguration; import at.gv.egiz.pdfas.web.exception.PdfAsWebException; @@ -49,10 +53,10 @@ import at.gv.egiz.pdfas.web.helper.PdfAsHelper; import at.gv.egiz.pdfas.web.helper.PdfAsParameterExtractor; import at.gv.egiz.pdfas.web.helper.RemotePDFFetcher; import at.gv.egiz.pdfas.web.stats.StatisticEvent; -import at.gv.egiz.pdfas.web.stats.StatisticFrontend; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Operation; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Source; import at.gv.egiz.pdfas.web.stats.StatisticEvent.Status; +import at.gv.egiz.pdfas.web.stats.StatisticFrontend; /** * Servlet implementation class Sign @@ -71,8 +75,9 @@ public class ExternSignServlet extends HttpServlet { /** * Default constructor. + */ - public ExternSignServlet() { + public ExternSignServlet(){ String webconfig = System.getProperty(PDF_AS_WEB_CONF); if(webconfig == null) { @@ -82,6 +87,14 @@ public class ExternSignServlet extends HttpServlet { WebConfiguration.configure(webconfig); PdfAsHelper.init(); + + try { + PdfAsFactory.validateConfiguration((ISettings)PdfAsHelper.getPdfAsConfig()); + } catch (PdfAsSettingsValidationException e) { + // TODO Auto-generated catch block + logger.error(e.getLocalizedMessage(),e.getCause()); + //e.printStackTrace(); + } } protected void doGet(HttpServletRequest request, -- cgit v1.2.3