/******************************************************************************* * 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.protocols.pvp2x.metadata; import java.io.IOException; import java.net.MalformedURLException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MOAHttpClient; import org.apache.commons.httpclient.params.HttpClientParams; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.xml.parse.BasicParserPool; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import at.gv.egiz.eaaf.core.api.idp.ISPConfiguration; import at.gv.egiz.eaaf.core.exceptions.EAAFConfigurationException; import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.AbstractChainingMetadataProvider; import at.gv.egiz.eaaf.modules.pvp2.impl.metadata.MetadataFilterChain; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.PVPEntityCategoryFilter; import at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata.SchemaValidationFilter; import at.gv.egovernment.moa.id.commons.api.AuthConfiguration; 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.config.auth.OAAuthParameterDecorator; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.InterfederatedIDPPublicServiceFilter; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MetadataSignatureFilter; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.Base64Utils; import at.gv.egovernment.moa.util.MiscUtil; @Service("PVPMetadataProvider") public class MOAMetadataProvider extends AbstractChainingMetadataProvider { @Autowired(required=true) AuthConfiguration moaAuthConfig; @Override protected String getMetadataURL(String entityId) throws EAAFConfigurationException { ISPConfiguration oaParam = authConfig.getServiceProviderConfiguration(entityId); if (oaParam != null) return oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); else { Logger.debug("Can not process PVP2X metadata: NO onlineApplication with Id: " + entityId); return null; } } @Override protected MetadataProvider createNewMetadataProvider(String entityId) throws EAAFConfigurationException, IOException, CertificateException { ISPConfiguration oaParam = authConfig.getServiceProviderConfiguration(entityId); if (oaParam != null) { String metadataURL = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); String certBase64 = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_CERTIFICATE); if (MiscUtil.isNotEmpty(certBase64)) { byte[] cert = Base64Utils.decode(certBase64, false); String oaFriendlyName = oaParam.getUniqueIdentifier(); return createNewSimpleMetadataProvider(metadataURL, buildMetadataFilterChain(oaParam, metadataURL, cert), oaFriendlyName, getTimer(), new BasicParserPool(), createHttpClient(metadataURL)); } else Logger.debug("Can not refresh PVP2X metadata: NO PVP2X metadata certificate for OA with Id: " + entityId); } Logger.debug("Can not process PVP2X metadata: NO onlineApplication with Id: " + entityId); return null; } @Override protected List getAllMetadataURLsFromConfiguration() throws EAAFConfigurationException { List metadataURLs = new ArrayList(); Map allOAs = moaAuthConfig.getConfigurationWithWildCard( MOAIDConfigurationConstants.PREFIX_MOAID_SERVICES + ".%." + MOAIDConfigurationConstants.SERVICE_UNIQUEIDENTIFIER); if (allOAs != null) { Iterator> oaInterator = allOAs.entrySet().iterator(); while (oaInterator.hasNext()) { Entry oaKeyPair = oaInterator.next(); ISPConfiguration oaParam = authConfig.getServiceProviderConfiguration(oaKeyPair.getValue()); if (oaParam != null) { String metadataurl = oaParam.getConfigurationValue(MOAIDConfigurationConstants.SERVICE_PROTOCOLS_PVP2X_URL); if (MiscUtil.isNotEmpty(metadataurl)) metadataURLs.add(metadataurl); else Logger.trace("OA: " + oaParam.getUniqueIdentifier() + " has NO PVP2 metadata URL"); } else Logger.warn("Something is suspect! OA is in Set of OAs, but no specific OA configuration is found."); } } else Logger.debug("No OA configuration found."); return metadataURLs; } private HttpClient createHttpClient(String metadataURL) { MOAHttpClient httpClient = new MOAHttpClient(); HttpClientParams httpClientParams = new HttpClientParams(); httpClientParams.setSoTimeout(AuthConfiguration.CONFIG_PROPS_METADATA_SOCKED_TIMEOUT); httpClient.setParams(httpClientParams); if (metadataURL.startsWith("https:")) { try { //FIX: change hostname validation default flag to true when httpClient is updated to > 4.4 MOAHttpProtocolSocketFactory protoSocketFactory = new MOAHttpProtocolSocketFactory( PVPConstants.SSLSOCKETFACTORYNAME, moaAuthConfig.getTrustedCACertificates(), null, AuthConfiguration.DEFAULT_X509_CHAININGMODE, moaAuthConfig.isTrustmanagerrevoationchecking(), moaAuthConfig.getRevocationMethodOrder(), moaAuthConfig.getBasicMOAIDConfigurationBoolean( AuthConfiguration.PROP_KEY_SSL_HOSTNAME_VALIDATION, false)); httpClient.setCustomSSLTrustStore(metadataURL, protoSocketFactory); } catch (MOAHttpProtocolSocketFactoryException | MalformedURLException e) { Logger.warn("MOA SSL-TrustStore can not initialized. Use default Java TrustStore.", e); } } return httpClient; } private MetadataFilterChain buildMetadataFilterChain(ISPConfiguration oaParam, String metadataURL, byte[] certificate) throws CertificateException{ MetadataFilterChain filterChain = new MetadataFilterChain(); filterChain.getFilters().add(new SchemaValidationFilter(moaAuthConfig.isPVPSchemaValidationActive())); filterChain.getFilters().add(new MetadataSignatureFilter(metadataURL, certificate)); filterChain.getFilters().add( new PVPEntityCategoryFilter(authConfig.getBasicMOAIDConfigurationBoolean( AuthConfiguration.PROP_KEY_PROTOCOL_PVP_METADATA_ENTITYCATEGORY_RESOLVER, false))); if ((new OAAuthParameterDecorator(oaParam)).isInderfederationIDP()) { Logger.info("Online-Application is an interfederated IDP. Add addional Metadata policies"); filterChain.getFilters().add(new InterfederatedIDPPublicServiceFilter(metadataURL, oaParam.hasBaseIdTransferRestriction())); } return filterChain; } }