be.fedict.eid.dss.model.bean.IdentityServiceSingletonBean.java Source code

Java tutorial

Introduction

Here is the source code for be.fedict.eid.dss.model.bean.IdentityServiceSingletonBean.java

Source

/*
 * eID Digital Signature Service Project.
 * Copyright (C) 2010 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.eid.dss.model.bean;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import sun.security.pkcs11.SunPKCS11;
import be.fedict.eid.dss.model.ConfigProperty;
import be.fedict.eid.dss.model.Configuration;
import be.fedict.eid.dss.model.DSSIdentityConfig;
import be.fedict.eid.dss.model.KeyStoreType;
import be.fedict.eid.dss.model.exception.KeyStoreLoadException;

@Singleton
@Startup
public class IdentityServiceSingletonBean {

    private static final Log LOG = LogFactory.getLog(IdentityServiceSingletonBean.class);

    private PrivateKeyEntry identity;
    private DSSIdentityConfig identityConfig;

    @EJB
    private Configuration configuration;

    @PostConstruct
    public void init() {

        if (isIdentityConfigured()) {
            try {
                reloadIdentity();
            } catch (KeyStoreLoadException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * @return if an active identity is configured
     */
    public boolean isIdentityConfigured() {
        return null != this.configuration.getValue(ConfigProperty.ACTIVE_IDENTITY, String.class);
    }

    /**
     * @return list of all identity configurations's names
     */
    public List<String> getIdentities() {

        return this.configuration.getIndexes(ConfigProperty.KEY_STORE_TYPE);
    }

    /**
     * Set new active identity
     * 
     * @param name
     *            new active identity's name
     * @throws KeyStoreLoadException
     *             failed to load keystore
     */
    public void setActiveIdentity(String name) throws KeyStoreLoadException {

        LOG.debug("set active identity: " + name);
        DSSIdentityConfig dssIdentityConfig = findIdentityConfig(name);

        if (null == dssIdentityConfig) {
            throw new KeyStoreLoadException("Identity config \"" + name + "\" not found!");
        }

        this.configuration.setValue(ConfigProperty.ACTIVE_IDENTITY, name);

        this.identity = loadIdentity(dssIdentityConfig);
        this.identityConfig = dssIdentityConfig;
        LOG.debug("private key entry reloaded");
    }

    /**
     * Reload current active identity
     * 
     * @throws KeyStoreLoadException
     *             failed to load keystore
     */
    public void reloadIdentity() throws KeyStoreLoadException {

        DSSIdentityConfig dssIdentityConfig = findIdentityConfig(findActiveIdentityName());

        this.identity = loadIdentity(dssIdentityConfig);
        this.identityConfig = dssIdentityConfig;
        LOG.debug("private key entry reloaded");
    }

    /**
     * Load identity keystore with specified name
     * 
     * @param name
     *            identity name
     * @return DSS identity
     * @throws KeyStoreLoadException
     *             failed to load keystore
     */
    public PrivateKeyEntry loadIdentity(String name) throws KeyStoreLoadException {

        DSSIdentityConfig dssIdentityConfig = findIdentityConfig(name);
        return loadIdentity(dssIdentityConfig);
    }

    /**
     * Load identity keystore
     * 
     * @param dssIdentityConfig
     *            identity configuration
     * @return private key entry of identity
     * @throws KeyStoreLoadException
     *             failed to load keystore
     */
    public PrivateKeyEntry loadIdentity(DSSIdentityConfig dssIdentityConfig) throws KeyStoreLoadException {

        try {

            if (null == dssIdentityConfig) {
                throw new KeyStoreLoadException("Identity config is empty!");
            }

            FileInputStream keyStoreInputStream = null;
            if (dssIdentityConfig.getKeyStoreType().equals(KeyStoreType.PKCS11)) {
                Security.addProvider(new SunPKCS11(dssIdentityConfig.getKeyStorePath()));
            } else {
                try {
                    keyStoreInputStream = new FileInputStream(dssIdentityConfig.getKeyStorePath());
                } catch (FileNotFoundException e) {
                    throw new KeyStoreLoadException("Can't load keystore from config-specified location: "
                            + dssIdentityConfig.getKeyStorePath(), e);
                }
            }

            // load keystore
            KeyStore keyStore = KeyStore.getInstance(dssIdentityConfig.getKeyStoreType().getJavaKeyStoreType());
            char[] password;
            if (null != dssIdentityConfig.getKeyStorePassword()
                    && !dssIdentityConfig.getKeyStorePassword().isEmpty()) {
                password = dssIdentityConfig.getKeyStorePassword().toCharArray();
            } else {
                password = null;
            }
            keyStore.load(keyStoreInputStream, password);

            // find entry alias
            Enumeration<String> aliases = keyStore.aliases();
            if (!aliases.hasMoreElements()) {
                throw new KeyStoreLoadException("no keystore aliases present");
            }

            String alias;
            if (null != dssIdentityConfig.getKeyEntryAlias()
                    && !dssIdentityConfig.getKeyEntryAlias().trim().isEmpty()) {
                boolean found = false;
                while (aliases.hasMoreElements()) {
                    if (aliases.nextElement().equals(dssIdentityConfig.getKeyEntryAlias())) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new KeyStoreLoadException(
                            "no keystore entry with alias \"" + dssIdentityConfig.getKeyEntryAlias() + "\"");
                }
                alias = dssIdentityConfig.getKeyEntryAlias();
            } else {
                alias = aliases.nextElement();
            }
            LOG.debug("keystore alias: " + alias);

            // get keystore entry
            char[] entryPassword;
            if (null != dssIdentityConfig.getKeyEntryPassword()
                    && !dssIdentityConfig.getKeyEntryPassword().isEmpty()) {
                entryPassword = dssIdentityConfig.getKeyEntryPassword().toCharArray();
            } else {
                entryPassword = null;
            }

            KeyStore.Entry entry = keyStore.getEntry(alias, new KeyStore.PasswordProtection(entryPassword));
            if (!(entry instanceof PrivateKeyEntry)) {
                throw new KeyStoreLoadException("private key entry expected");
            }
            return (PrivateKeyEntry) entry;
        } catch (KeyStoreException e) {
            throw new KeyStoreLoadException(e);
        } catch (CertificateException e) {
            throw new KeyStoreLoadException(e);
        } catch (NoSuchAlgorithmException e) {
            throw new KeyStoreLoadException(e);
        } catch (UnrecoverableEntryException e) {
            throw new KeyStoreLoadException(e);
        } catch (IOException e) {
            throw new KeyStoreLoadException(e);
        }
    }

    /**
     * @return current DSS Identity or <code>null</code> if none.
     */
    public PrivateKeyEntry findIdentity() {

        // check identity config changed in dbase, if so reload!
        DSSIdentityConfig databaseIdentityConfig = findIdentityConfig();

        if (null != databaseIdentityConfig) {
            if (!databaseIdentityConfig.equals(this.identityConfig)) {
                try {
                    this.identity = loadIdentity(databaseIdentityConfig);
                } catch (KeyStoreLoadException e) {
                    throw new RuntimeException(e);
                }
                this.identityConfig = databaseIdentityConfig;
            }
        }
        return this.identity;
    }

    /**
     * @return current identity's configuration or <codE>null</code> if none.
     */
    public DSSIdentityConfig findIdentityConfig() {

        String activeIdentity = findActiveIdentityName();
        if (null == activeIdentity) {
            return null;
        }
        DSSIdentityConfig dssIdentityConfig = findIdentityConfig(activeIdentity);
        if (null == dssIdentityConfig) {
            throw new EJBException("Identity config " + activeIdentity + " not found!");
        }
        return dssIdentityConfig;
    }

    /**
     * @param name
     *            identity name
     * @return identity config or <code>null</code> if not found.
     */
    public DSSIdentityConfig findIdentityConfig(String name) {

        KeyStoreType keyStoreType = this.configuration.getValue(ConfigProperty.KEY_STORE_TYPE, name,
                KeyStoreType.class);
        if (null == keyStoreType) {
            return null;
        }
        String keyStorePath = this.configuration.getValue(ConfigProperty.KEY_STORE_PATH, name, String.class);
        String keyStoreSecret = this.configuration.getValue(ConfigProperty.KEY_STORE_SECRET, name, String.class);
        String keyEntrySecret = this.configuration.getValue(ConfigProperty.KEY_ENTRY_SECRET, name, String.class);
        String keyEntryAlias = this.configuration.getValue(ConfigProperty.KEY_ENTRY_ALIAS, name, String.class);

        DSSIdentityConfig idPIdentityConfig = new DSSIdentityConfig(name, keyStoreType, keyStorePath,
                keyStoreSecret, keyEntrySecret, keyEntryAlias);

        String activeIdentity = findActiveIdentityName();
        if (null != activeIdentity) {
            idPIdentityConfig.setActive(idPIdentityConfig.getName().equals(activeIdentity));
        }

        return idPIdentityConfig;
    }

    private String findActiveIdentityName() {

        return this.configuration.getValue(ConfigProperty.ACTIVE_IDENTITY, String.class);
    }

    /**
     * Add/update identity from specified configuration
     * 
     * @param dssIdentityConfig
     *            identity configuration
     * @return DSS Identity
     * @throws KeyStoreLoadException
     *             failed to load keystore
     */
    public PrivateKeyEntry setIdentity(DSSIdentityConfig dssIdentityConfig) throws KeyStoreLoadException {

        LOG.debug("set identity: " + dssIdentityConfig.getName());

        this.configuration.setValue(ConfigProperty.KEY_STORE_TYPE, dssIdentityConfig.getName(),
                dssIdentityConfig.getKeyStoreType());
        this.configuration.setValue(ConfigProperty.KEY_STORE_PATH, dssIdentityConfig.getName(),
                dssIdentityConfig.getKeyStorePath());
        this.configuration.setValue(ConfigProperty.KEY_STORE_SECRET, dssIdentityConfig.getName(),
                dssIdentityConfig.getKeyStorePassword());
        this.configuration.setValue(ConfigProperty.KEY_ENTRY_SECRET, dssIdentityConfig.getName(),
                dssIdentityConfig.getKeyEntryPassword());
        if (null != dssIdentityConfig.getKeyEntryAlias()) {
            this.configuration.setValue(ConfigProperty.KEY_ENTRY_ALIAS, dssIdentityConfig.getName(),
                    dssIdentityConfig.getKeyEntryAlias());
        }

        return loadIdentity(dssIdentityConfig.getName());
    }

    /**
     * Remove identity configuration
     * 
     * @param name
     *            name of identity config to remove
     */
    public void removeIdentityConfig(String name) {

        LOG.debug("remove identity: " + name);

        String activeIdentity = findActiveIdentityName();
        if (null != activeIdentity && activeIdentity.equals(name)) {
            this.configuration.removeValue(ConfigProperty.ACTIVE_IDENTITY);
            this.identity = null;
            this.identityConfig = null;
        }

        this.configuration.removeValue(ConfigProperty.KEY_STORE_TYPE, name);
        this.configuration.removeValue(ConfigProperty.KEY_STORE_PATH, name);
        this.configuration.removeValue(ConfigProperty.KEY_STORE_SECRET, name);
        this.configuration.removeValue(ConfigProperty.KEY_ENTRY_SECRET, name);
        this.configuration.removeValue(ConfigProperty.KEY_ENTRY_ALIAS, name);
    }
}