001/* 
002 * Copyright (C) 2016 Hobrasoft s.r.o.
003 *
004 * This program is free software: you can redistribute it and/or modify
005 * it under the terms of the GNU Affero General Public License as published by
006 * the Free Software Foundation, either version 3 of the License, or
007 * (at your option) any later version.
008 *
009 * This program is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012 * GNU Affero General Public License for more details.
013 *
014 * You should have received a copy of the GNU Affero General Public License
015 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
016 */
017package cz.hobrasoft.pdfmu.operation.signature;
018
019import cz.hobrasoft.pdfmu.error.ErrorType;
020import cz.hobrasoft.pdfmu.operation.OperationException;
021import java.io.File;
022import java.util.AbstractMap;
023import java.util.logging.Logger;
024import org.apache.commons.io.FilenameUtils;
025
026/**
027 * SSL keystore (that is TrustStore or private KeyStore) configurator.
028 *
029 * @author <a href="mailto:filip.bartek@hobrasoft.cz">Filip Bartek</a>
030 * @see
031 * <a href="https://access.redhat.com/documentation/en-US/Fuse_MQ_Enterprise/7.1/html/Security_Guide/files/SSL-SysProps.html">Configuring
032 * JSSE System Properties</a>
033 * @see
034 * <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#KeyStore">KeyStore
035 * Types</a>
036 * @see
037 * <a href="http://docs.oracle.com/cd/E19509-01/820-3503/6nf1il6er/index.html">Generating
038 * a KeyStore and TrustStore</a>
039 */
040public enum SslKeystore {
041    /**
042     * The keystore that contains the private keys used for authorization. The
043     * respective system property keys start with the prefix
044     * {@code javax.net.ssl.keyStore}.
045     */
046    PRIVATE("javax.net.ssl.keyStore",
047            "javax.net.ssl.keyStorePassword",
048            "javax.net.ssl.keyStoreType",
049            "SSL KeyStore",
050            ErrorType.SSL_KEYSTORE_NOT_FOUND),
051    /**
052     * The keystore that contains the certificates of the trusted certificate
053     * authorities. The respective system property keys start with the prefix
054     * {@code javax.net.ssl.trustStore}.
055     */
056    TRUSTSTORE("javax.net.ssl.trustStore",
057            "javax.net.ssl.trustStorePassword",
058            "javax.net.ssl.trustStoreType",
059            "SSL TrustStore",
060            ErrorType.SSL_TRUSTSTORE_NOT_FOUND);
061
062    private static final Logger LOGGER = Logger.getLogger(SslKeystore.class.getName());
063
064    private final String keyLocation;
065    private final String keyPassword;
066    private final String keyType;
067    private final String name;
068    private final ErrorType errorTypeNotFound;
069
070    private SslKeystore(String location,
071            String password,
072            String type,
073            String name,
074            ErrorType errorTypeNotFound) {
075        this.keyLocation = location;
076        this.keyPassword = password;
077        this.keyType = type;
078        this.name = name;
079        this.errorTypeNotFound = errorTypeNotFound;
080    }
081
082    /**
083     * @return a short description of this keystore
084     */
085    public String getName() {
086        return name;
087    }
088
089    /**
090     * Set the system properties that configure this SSL keystore.
091     *
092     * @param file the keystore file
093     * @param type the type of the keystore
094     * @param password the password of the keystore
095     * @throws OperationException if the keystore file does not exist
096     */
097    public void setSystemProperties(File file, String type, String password) throws OperationException {
098        if (file != null) {
099            // https://access.redhat.com/documentation/en-US/Fuse_MQ_Enterprise/7.1/html/Security_Guide/files/SSL-SysProps.html
100            // > On Windows, the specified pathname must use forward slashes, /, in place of backslashes, \.
101            String location = FilenameUtils.separatorsToUnix(file.getPath());
102            if (!file.exists()) {
103                throw new OperationException(errorTypeNotFound,
104                        new AbstractMap.SimpleEntry<String, Object>("location", location));
105            }
106            LOGGER.info(String.format("%s: Configuring to use the keystore file %s.", name, location));
107            System.setProperty(keyLocation, location);
108        }
109
110        if (type != null) {
111            if (file == null) {
112                LOGGER.warning(String.format("%s: Type has been specified but location has not.", name));
113            }
114            // TODO: Warn if `file` extension is inconsistent with `type`
115            System.setProperty(keyType, type);
116        }
117
118        if (password != null) {
119            if (file == null) {
120                LOGGER.warning(String.format("%s: Password has been specified but location has not.", name));
121            }
122            System.setProperty(keyPassword, password);
123        }
124    }
125}