/******************************************************************************* * Copyright 2014 Federal Chancellery Austria * MOA-ID 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.id.configuration.validation.oa; import java.io.IOException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Timer; import javax.net.ssl.SSLHandshakeException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.httpclient.MOAHttpClient; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataFilter; import org.opensaml.saml2.metadata.provider.MetadataFilterChain; import org.opensaml.saml2.metadata.provider.MetadataProviderException; import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.x509.BasicX509Credential; import at.gv.egovernment.moa.id.commons.MOAIDConstants; import at.gv.egovernment.moa.id.commons.config.MOAIDConfigurationConstants; import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException; import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory; import at.gv.egovernment.moa.id.commons.validation.ValidationHelper; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException; import at.gv.egovernment.moa.id.config.webgui.exception.SchemaValidationException; import at.gv.egovernment.moa.id.config.webgui.exception.SignatureValidationException; import at.gv.egovernment.moa.id.config.webgui.validation.utils.SchemaValidationFilter; import at.gv.egovernment.moa.id.configuration.auth.pvp2.MetaDataVerificationFilter; import at.gv.egovernment.moa.id.configuration.config.ConfigurationProvider; import at.gv.egovernment.moa.id.configuration.data.oa.OAPVP2Config; import at.gv.egovernment.moa.id.configuration.helper.LanguageHelper; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.MiscUtil; import iaik.x509.X509Certificate; import lombok.extern.slf4j.Slf4j; @Slf4j public class OAPVP2ConfigValidation { public List validate(OAPVP2Config form, String oaID, HttpServletRequest request) { Timer timer = null; MOAHttpClient httpClient = null; HTTPMetadataProvider httpProvider = null; final List errors = new ArrayList<>(); try { byte[] certSerialized = null; if (form.getFileUpload() != null) { certSerialized = form.getCertificate(); } else { try { // Some databases does not allow the selection of a lob in SQL where expression final String dbDriver = ConfigurationProvider.getInstance().getConfigurationProperties() .getProperty("hibernate.connection.driver_class"); boolean backupVersion = false; if (MiscUtil.isNotEmpty(dbDriver)) { for (final String el : MOAIDConstants.JDBC_DRIVER_NEEDS_WORKAROUND) { if (dbDriver.startsWith(el)) { backupVersion = true; log.debug("JDBC driver '" + dbDriver + "' is blacklisted --> Switch to alternative DB access methode implementation."); } } } final Map oa = ConfigurationProvider.getInstance().getDbRead() .getOnlineApplicationKeyValueWithId(oaID, backupVersion); if (oa != null && MiscUtil.isNotEmpty(oa.get(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE))) { certSerialized = Base64Utils.decode(oa.get( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE), false); form.setStoredCert(certSerialized); } } catch (final ConfigurationException e) { log.error("MOA-ID-Configuration initialization FAILED.", e); } } final String check = form.getMetaDataURL(); if (MiscUtil.isNotEmpty(check)) { if (!ValidationHelper.validateURL(check)) { log.info("MetaDataURL has no valid form."); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadataurl.valid", request)); } else { if (certSerialized == null) { log.info("No certificate for metadata validation"); errors.add(LanguageHelper.getErrorString("validation.pvp2.certificate.notfound", request)); } else { if (form.getMetaDataURL().startsWith("http")) { final X509Certificate cert = new X509Certificate(certSerialized); final BasicX509Credential credential = new BasicX509Credential(); credential.setEntityCertificate(cert); timer = new Timer(); httpClient = new MOAHttpClient(); if (form.getMetaDataURL().startsWith("https:")) { try { final MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( "MOAMetaDataProvider", true, ConfigurationProvider.getInstance().getCertStoreDirectory(), ConfigurationProvider.getInstance().getTrustStoreDirectory(), null, "pkix", true, new String[] { "crl" }, false); httpClient.setCustomSSLTrustStore( form.getMetaDataURL(), protoSocketFactory); } catch (final MOAHttpProtocolSocketFactoryException e) { log.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); } catch (final ConfigurationException e) { log.info("No MOA specific SSL-TrustStore configured. Use default Java TrustStore."); } } final List filterList = new ArrayList<>(); filterList.add(new MetaDataVerificationFilter(credential)); try { filterList.add(new SchemaValidationFilter( ConfigurationProvider.getInstance().isPVPMetadataSchemaValidationActive())); } catch (final ConfigurationException e) { log.warn("Configuration access FAILED!", e); } final MetadataFilterChain filter = new MetadataFilterChain(); filter.setFilters(filterList); httpProvider = new HTTPMetadataProvider(timer, httpClient, form.getMetaDataURL()); httpProvider.setParserPool(new BasicParserPool()); httpProvider.setRequireValidMetadata(true); httpProvider.setMetadataFilter(filter); httpProvider.setMinRefreshDelay(1000 * 60 * 15); // 15 minutes httpProvider.setMaxRefreshDelay(1000 * 60 * 60 * 24); // 24 hours httpProvider.setRequireValidMetadata(true); httpProvider.initialize(); if (httpProvider.getMetadata() == null) { log.info("Metadata could be received but validation FAILED."); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.validation", request)); } } else { log.info("Metadata load validation skipped, because it's no http(s) metadata: " + form .getMetaDataURL()); } } } } } catch (final CertificateException e) { log.info("Uploaded Certificate can not be found", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.certificate.notfound", request)); } catch (final IOException e) { log.info("Metadata can not be loaded from URL", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadataurl.read", request)); } catch (final MetadataProviderException e) { try { if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { log.info("SSL Server certificate not trusted.", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.ssl", request)); } else if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { log.info("MetaDate verification failed", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.verify.sig", request)); } else if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { log.info("MetaDate verification failed", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.verify.schema", request)); } else { log.info("MetaDate verification failed", e); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.verify.general", request)); } } catch (final Exception e1) { log.info("MetaDate verification failed", e1); errors.add(LanguageHelper.getErrorString("validation.pvp2.metadata.verify.general", request)); } } finally { if (httpProvider != null) { httpProvider.destroy(); } if (timer != null) { timer.cancel(); } } return errors; } }