/* * 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.config.webgui.validation.task.impl; import java.io.IOException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Timer; import java.util.regex.Pattern; import javax.net.ssl.SSLHandshakeException; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import at.gv.egiz.components.configuration.api.Configuration; 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.MOAIDWebGUIConfiguration; import at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationTaskValidationException; 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.exception.ValidationObjectIdentifier; import at.gv.egovernment.moa.id.config.webgui.helper.LanguageHelper; import at.gv.egovernment.moa.id.config.webgui.validation.task.AbstractTaskValidator; import at.gv.egovernment.moa.id.config.webgui.validation.task.IDynamicLoadableTaskValidator; import at.gv.egovernment.moa.id.config.webgui.validation.utils.MetaDataVerificationFilter; import at.gv.egovernment.moa.id.config.webgui.validation.utils.SchemaValidationFilter; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.MiscUtil; import iaik.x509.X509Certificate; /** * @author tlenz * */ public class ServicesProtocolPVP2XTask extends AbstractTaskValidator implements IDynamicLoadableTaskValidator { private static final Logger log = LoggerFactory.getLogger(ServicesProtocolPVP2XTask.class); private static final List KEYWHITELIST; static { ArrayList temp = new ArrayList(); KEYWHITELIST = Collections.unmodifiableList(temp); } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.ITaskValidator#getKeyPrefix() */ @Override public String getKeyPrefix() { return ""; } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.ITaskValidator#getName() */ @Override public String getName() { return "Service - General Configuration Task"; } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.ITaskValidator#postProcessing(java.util.Map, java.util.List, at.gv.egiz.components.configuration.api.Configuration) */ @Override public Map postProcessing(Map input, List keysToDelete, Configuration dbconfig) { Map newConfigValues = new HashMap(); String certBase64 = input.get(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); if (MiscUtil.isNotEmpty(certBase64)) { String[] splittet = certBase64.split(","); if (splittet.length > 1) { newConfigValues.put(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE, splittet[1]); log.debug("Extract PVP2X metadata validation certificate from GUI upload and add it to key: {}", MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); try { byte[] certSerialized = null; if (MiscUtil.isNotEmpty(splittet[1])) { certSerialized = Base64Utils.decode(splittet[1], true); X509Certificate cert = new X509Certificate(certSerialized); newConfigValues.put( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE_SUBJECT, cert.getSubjectDN().getName()); } } catch (IOException | CertificateException e) { log.error("PVP2X metadata signing certificate is not parseable.", e); } } } if (newConfigValues.isEmpty()) return null; else return newConfigValues; } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.AbstractTaskValidator#tastValidate(java.util.Map) */ @Override protected void taskValidate(Map input) throws ConfigurationTaskValidationException { List errors = new ArrayList(); Timer timer = null; MOAHttpClient httpClient = null; HTTPMetadataProvider httpProvider = null; String certBase64 = input.get(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); try { byte[] certSerialized = null; if (MiscUtil.isNotEmpty(certBase64) && !certBase64.equals(MOAIDConfigurationConstants.WEBGUI_EMPTY_ELEMENT)) { String[] splittet = certBase64.split(","); if (splittet.length > 1) certSerialized = Base64Utils.decode(splittet[1], true); else certSerialized = Base64Utils.decode(certBase64, true); } String metadataURL = input.get(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); if (MiscUtil.isNotEmpty(metadataURL)) { if (!ValidationHelper.validateURL(metadataURL)) { log.info("MetaDataURL has no valid form."); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata URL", LanguageHelper.getErrorString("validation.pvp2.metadataurl.valid"))); } else { if (certSerialized == null) { log.info("No certificate for metadata validation"); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE, "PVP2x - Metadata Certificate", LanguageHelper.getErrorString("validation.pvp2.certificate.notfound"))); } else { X509Certificate cert = new X509Certificate(certSerialized); BasicX509Credential credential = new BasicX509Credential(); credential.setEntityCertificate(cert); timer = new Timer(true); httpClient = new MOAHttpClient(); if (metadataURL.startsWith("https:")) try { MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( "MOAMetaDataProvider", MOAIDWebGUIConfiguration.getInstance().getCertStoreDirectory(), MOAIDWebGUIConfiguration.getInstance().getTrustStoreDirectory(), null, "pkix", true, new String[]{"crl"}, false); httpClient.setCustomSSLTrustStore( metadataURL, protoSocketFactory); } catch (MOAHttpProtocolSocketFactoryException e) { log.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); } catch (at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException e) { log.info("No MOA specific SSL-TrustStore configured. Use default Java TrustStore.", e); } List filterList = new ArrayList(); filterList.add(new MetaDataVerificationFilter(credential)); try { filterList.add(new SchemaValidationFilter( MOAIDWebGUIConfiguration.getInstance().isPVPMetadataSchemaValidationActive())); } catch (at.gv.egovernment.moa.id.config.webgui.exception.ConfigurationException e) { log.warn("Configuration access FAILED!", e); } MetadataFilterChain filter = new MetadataFilterChain(); filter.setFilters(filterList); httpProvider = new HTTPMetadataProvider(timer, httpClient, metadataURL); 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(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.validation"))); } } } } } catch (CertificateException e) { log.info("Uploaded Certificate can not be found", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.certificate.notfound"))); } catch (IOException e) { log.info("Metadata can not be loaded from URL", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadataurl.read"))); } catch (MetadataProviderException e) { try { if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) { log.info("SSL Server certificate not trusted.", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.ssl"))); } else if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) { log.info("MetaDate verification failed", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.verify.sig"))); } else if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { log.info("MetaDate verification failed", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.verify.schema"))); } else { log.info("MetaDate verification failed", e); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.verify.general"))); } } catch (Exception e1) { log.info("MetaDate verification failed", e1); errors.add(new ValidationObjectIdentifier( MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL, "PVP2x - Metadata", LanguageHelper.getErrorString("validation.pvp2.metadata.verify.general"))); } } finally { if (httpProvider != null) httpProvider.destroy(); if (timer != null) timer.cancel(); } if (!errors.isEmpty()) throw new ConfigurationTaskValidationException(errors); } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.AbstractTaskValidator#getAllAllowedKeys() */ @Override public List getAllAllowedPatterns() { return generatePatternsFromKeys(KEYWHITELIST); } /* (non-Javadoc) * @see at.gv.egovernment.moa.id.config.webgui.validation.task.IDynamicLoadableTaskValidator#getModulValidatorPrefix() */ @Override public List getModulValidatorPrefix() { return Arrays.asList( MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES_OA, MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES_IIDP ); } }