package at.gv.egovernment.moa.id.configuration.config; import iaik.x509.X509Certificate; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Properties; import java.util.Timer; import javax.servlet.http.HttpServletRequest; import org.apache.commons.httpclient.HttpClient; import org.apache.log4j.Logger; import org.opensaml.DefaultBootstrap; import org.opensaml.saml2.metadata.provider.HTTPMetadataProvider; import org.opensaml.xml.parse.BasicParserPool; import org.opensaml.xml.security.x509.BasicX509Credential; import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; import at.gv.egovernment.moa.id.configuration.Constants; import at.gv.egovernment.moa.id.configuration.auth.pvp2.MetaDataVerificationFilter; import at.gv.egovernment.moa.id.configuration.exception.ConfigurationException; import at.gv.egovernment.moa.id.configuration.utils.UserRequestCleaner; import at.gv.egovernment.moa.util.MiscUtil; public class ConfigurationProvider { private static final Logger log = Logger.getLogger(ConfigurationProvider.class); private static final String SYSTEM_PROP_CONFIG = "moa.id.webconfig"; private static ConfigurationProvider instance; private Properties props; private String configFileName; private String configRootDir; private HTTPMetadataProvider idpMetadataProvider = null; private KeyStore keyStore = null; private String publicURLPreFix = null; private boolean pvp2logininitialzied = false; public static ConfigurationProvider getInstance() throws ConfigurationException { if (instance == null) { instance = new ConfigurationProvider(); } return instance; } private ConfigurationProvider() throws ConfigurationException { inizialize(); } private void inizialize() throws ConfigurationException { configFileName = System.getProperty(SYSTEM_PROP_CONFIG); if (configFileName == null) { throw new ConfigurationException("config.01"); } // determine the directory of the root config file configRootDir = new File(configFileName).getParent(); log.info("Loading MOA-ID-AUTH configuration " + configFileName); //Initial Hibernate Framework log.trace("Initializing Hibernate framework."); //Load MOAID-2.0 properties file File propertiesFile = new File(configFileName); FileInputStream fis; props = new Properties(); try { fis = new FileInputStream(propertiesFile); props.load(fis); // initialize hibernate synchronized (ConfigurationProvider.class) { //Initial config Database ConfigurationDBUtils.initHibernate(props); } log.trace("Hibernate initialization finished."); DefaultBootstrap.bootstrap(); log.info("OPENSAML initialized"); //TODO: start CleanUP Thread UserRequestCleaner.start(); } catch (FileNotFoundException e) { throw new ConfigurationException("config.01", e); } catch (IOException e) { throw new ConfigurationException("config.02", e); } catch (MOADatabaseException e) { throw new ConfigurationException("config.03", e); } catch (org.opensaml.xml.ConfigurationException e) { throw new ConfigurationException("config.04", e); } } public String getPublicUrlPreFix(HttpServletRequest request) { publicURLPreFix = props.getProperty("general.publicURLContext"); if (MiscUtil.isEmpty(publicURLPreFix) && request != null) { String url = request.getRequestURL().toString(); String contextpath = request.getContextPath(); int index = url.indexOf(contextpath); publicURLPreFix = url.substring(0, index + contextpath.length() + 1); } return publicURLPreFix; } public int getUserRequestCleanUpDelay() { String delay = props.getProperty("general.userrequests.cleanup.delay"); return Integer.getInteger(delay, 12); } public String getContactMailAddress() { return props.getProperty("general.contact.mail"); } public String getSSOLogOutURL() { return props.getProperty("general.login.pvp2.idp.sso.logout.url"); } public KeyStore getPVP2KeyStore() throws ConfigurationException, IOException, NoSuchAlgorithmException, CertificateException, KeyStoreException { if (keyStore == null) { String keystoretype = getPVP2MetadataKeystoreType(); if (MiscUtil.isEmpty(keystoretype)) { log.debug("No KeyStoreType defined. Using default KeyStoreType."); keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); } else { log.debug("Using " + keystoretype + " KeyStoreType."); keyStore = KeyStore.getInstance(keystoretype); } String file = getPVP2MetadataKeystoreURL(); log.debug("Load KeyStore from URL " + file); if (MiscUtil.isEmpty(file)) { log.info("Metadata KeyStoreURL is empty"); throw new ConfigurationException("Metadata KeyStoreURL is empty"); } FileInputStream inputStream = new FileInputStream(file); keyStore.load(inputStream, getPVP2MetadataKeystorePassword().toCharArray()); inputStream.close(); } return keyStore; } public String getConfigFile() { return configFileName; } public String getConfigRootDir() { return configRootDir; } public boolean isLoginDeaktivated() { String result = props.getProperty("general.login.deaktivate", "false"); return Boolean.parseBoolean(result); } public boolean isOATargetVerificationDeaktivated() { String result = props.getProperty("general.OATargetVerification.deaktivate", "false"); return Boolean.parseBoolean(result); } //PVP2 Login configuration public void initializePVP2Login() throws ConfigurationException { if (!pvp2logininitialzied) initalPVP2Login(); } public boolean isPVP2LoginActive() { if (!pvp2logininitialzied) return false; String result = props.getProperty("general.login.pvp2.isactive", "false"); return Boolean.parseBoolean(result); } public boolean isPVP2LoginBusinessService() { String result = props.getProperty("general.login.pvp2.isbusinessservice", "false"); return Boolean.parseBoolean(result); } public String getPVP2LoginTarget() { return props.getProperty("general.login.pvp2.target"); } public String getPVP2LoginIdenificationValue() { return props.getProperty("general.login.pvp2.identificationvalue"); } public String getPVP2MetadataEntitiesName() { return props.getProperty("general.login.pvp2.metadata.entities.name"); } public String getPVP2MetadataKeystoreURL() { return props.getProperty("general.login.pvp2.keystore.url"); } public String getPVP2MetadataKeystorePassword() { return props.getProperty("general.login.pvp2.keystore.password"); } public String getPVP2MetadataKeystoreType() { return props.getProperty("general.login.pvp2.keystore.type"); } public String getPVP2KeystoreMetadataKeyAlias() { return props.getProperty("general.login.pvp2.keystore.metadata.key.alias"); } public String getPVP2KeystoreMetadataKeyPassword() { return props.getProperty("general.login.pvp2.keystore.metadata.key.password"); } public String getPVP2KeystoreAuthRequestKeyAlias() { return props.getProperty("general.login.pvp2.keystore.authrequest.key.alias"); } public String getPVP2KeystoreAuthRequestKeyPassword() { return props.getProperty("general.login.pvp2.keystore.authrequest.key.password"); } public String getPVP2IDPMetadataURL() { return props.getProperty("general.login.pvp2.idp.metadata.url"); } public String getPVP2IDPMetadataCertificate() { return props.getProperty("general.login.pvp2.idp.metadata.certificate"); } public String getPVP2IDPMetadataEntityName() { return props.getProperty("general.login.pvp2.idp.metadata.entityID"); } public HTTPMetadataProvider getMetaDataProvier() { return idpMetadataProvider; } //SMTP Server public String getSMTPMailHost() { return props.getProperty("general.mail.host"); } public String getSMTPMailPort() { return props.getProperty("general.mail.host.port"); } public String getSMTPMailUsername() { return props.getProperty("general.mail.host.username"); } public String getSMTPMailPassword() { return props.getProperty("general.mail.host.password"); } //Mail Configuration public String getMailFromName() { return props.getProperty("general.mail.from.name"); } public String getMailFromAddress() { return props.getProperty("general.mail.from.address"); } public String getMailUserAcountVerificationSubject() { return props.getProperty("general.mail.useraccountrequest.verification.subject"); } public String getMailUserAcountVerificationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.verification.template"); if (MiscUtil.isNotEmpty(url)) { if (url.startsWith(Constants.FILEPREFIX)) return url; else return configRootDir + "/" + url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailUserAcountVerificationTemplate is empty"); } } public String getMailUserAcountActivationSubject() { return props.getProperty("general.mail.useraccountrequest.isactive.subject"); } public String getMailUserAcountActivationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.isactive.template"); if (MiscUtil.isNotEmpty(url)) { if (url.startsWith(Constants.FILEPREFIX)) return url; else return configRootDir + "/" + url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailUserAcountActivationTemplate is empty"); } } public String getMailOAActivationSubject() { return props.getProperty("general.mail.createOArequest.isactive.subject"); } public String getMailOAActivationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.createOArequest.isactive.template"); if (MiscUtil.isNotEmpty(url)) { if (url.startsWith(Constants.FILEPREFIX)) return url; else return configRootDir + "/" + url; } else { log.warn("MailOAActivationTemplate is empty"); throw new ConfigurationException("MailOAActivationTemplate is empty"); } } public String getMailUserAcountRevocationTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.useraccountrequest.rejected.template"); if (MiscUtil.isNotEmpty(url)) { if (url.startsWith(Constants.FILEPREFIX)) return url; else return configRootDir + "/" + url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailUserAcountRevocationTemplate is empty"); } } public String getMailAdminSubject() { return props.getProperty("general.mail.admin.subject"); } public String getMailAdminTemplate() throws ConfigurationException { String url = props.getProperty("general.mail.admin.adresses.template"); if (MiscUtil.isNotEmpty(url)) { if (url.startsWith(Constants.FILEPREFIX)) return url; else return configRootDir + "/" + url; } else { log.warn("MailUserAcountVerificationTemplate is empty"); throw new ConfigurationException("MailAdminTemplate is empty"); } } public String getMailAdminAddress() { return props.getProperty("general.mail.admin.adress"); } private void initalPVP2Login() throws ConfigurationException { try { String metadataCert = getPVP2IDPMetadataCertificate(); if (MiscUtil.isEmpty(metadataCert)) { log.info("NO IDP Certificate to verify IDP Metadata"); throw new ConfigurationException("NO IDP Certificate to verify IDP Metadata"); } InputStream certstream = new FileInputStream(metadataCert); X509Certificate cert = new X509Certificate(certstream); BasicX509Credential idpCredential = new BasicX509Credential(); idpCredential.setEntityCertificate(cert); log.debug("IDP Certificate loading finished"); String metadataurl = getPVP2IDPMetadataURL(); if (MiscUtil.isEmpty(metadataurl)) { log.info("NO IDP Metadata URL."); throw new ConfigurationException("NO IDP Metadata URL."); } idpMetadataProvider = new HTTPMetadataProvider(new Timer(), new HttpClient(), metadataurl); idpMetadataProvider.setRequireValidMetadata(true); idpMetadataProvider.setParserPool(new BasicParserPool()); idpMetadataProvider.setMetadataFilter(new MetaDataVerificationFilter(idpCredential)); idpMetadataProvider.setMaxRefreshDelay(1000 * 3600 * 12 ); //refresh Metadata every 12h idpMetadataProvider.initialize(); pvp2logininitialzied = true; } catch (Exception e) { log.warn("PVP2 authentification can not be initialized."); throw new ConfigurationException("PVP2 authentification can not be initialized.", e); } } }