com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.sonatype.nexus.ssl.plugin.internal.TrustStoreImpl.java

Source

/*
 * Sonatype Nexus (TM) Open Source Version
 * Copyright (c) 2008-present Sonatype, Inc.
 * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
 *
 * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
 * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
 *
 * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
 * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
 * Eclipse Foundation. All other trademarks are the property of their respective owners.
 */
package com.sonatype.nexus.ssl.plugin.internal;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Collection;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import org.sonatype.goodies.common.ComponentSupport;
import org.sonatype.nexus.common.event.EventManager;
import org.sonatype.nexus.orient.freeze.DatabaseFreezeService;
import org.sonatype.nexus.ssl.CertificateCreatedEvent;
import org.sonatype.nexus.ssl.CertificateDeletedEvent;
import org.sonatype.nexus.ssl.CertificateUtil;
import org.sonatype.nexus.ssl.KeyStoreManager;
import org.sonatype.nexus.ssl.KeystoreException;
import org.sonatype.nexus.ssl.TrustStore;

import com.google.common.base.Throwables;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * {@link TrustStore} implementation.
 *
 * @since ssl 1.0
 */
@Named
@Singleton
public class TrustStoreImpl extends ComponentSupport implements TrustStore {
    public static final SecureRandom DEFAULT_RANDOM = null;

    private final DatabaseFreezeService databaseFreezeService;

    private final EventManager eventManager;

    private final KeyManager[] keyManagers;

    private final TrustManager[] trustManagers;

    private final KeyStoreManager keyStoreManager;

    private volatile SSLContext sslcontext;

    @Inject
    public TrustStoreImpl(final EventManager eventManager, @Named("ssl") final KeyStoreManager keyStoreManager,
            final DatabaseFreezeService databaseFreezeService) throws Exception {
        this.eventManager = checkNotNull(eventManager);
        this.keyStoreManager = checkNotNull(keyStoreManager);
        this.databaseFreezeService = checkNotNull(databaseFreezeService);
        this.keyManagers = getSystemKeyManagers();
        this.trustManagers = getTrustManagers(keyStoreManager);
    }

    @Override
    public Certificate importTrustCertificate(final Certificate certificate, final String alias)
            throws KeystoreException {
        databaseFreezeService.checkUnfrozen("Unable to import a certificate while database is frozen.");
        keyStoreManager.importTrustCertificate(certificate, alias);

        eventManager.post(new CertificateCreatedEvent(alias, certificate));

        return certificate;
    }

    @Override
    public Certificate importTrustCertificate(final String certificateInPEM, final String alias)
            throws KeystoreException, CertificateException {
        databaseFreezeService.checkUnfrozen("Unable to import a certificate while database is frozen.");
        final Certificate certificate = CertificateUtil.decodePEMFormattedCertificate(certificateInPEM);
        keyStoreManager.importTrustCertificate(certificate, alias);

        eventManager.post(new CertificateCreatedEvent(alias, certificate));

        return certificate;
    }

    @Override
    public Certificate getTrustedCertificate(final String alias) throws KeystoreException {
        return keyStoreManager.getTrustedCertificate(alias);
    }

    @Override
    public Collection<Certificate> getTrustedCertificates() throws KeystoreException {
        return keyStoreManager.getTrustedCertificates();
    }

    @Override
    public void removeTrustCertificate(final String alias) throws KeystoreException {
        databaseFreezeService.checkUnfrozen("Unable to remove a certificate while database is frozen.");
        Certificate certificate = getTrustedCertificate(alias);
        keyStoreManager.removeTrustCertificate(alias);
        sslcontext = null;

        eventManager.post(new CertificateDeletedEvent(alias, certificate));
    }

    @Override
    public SSLContext getSSLContext() {
        SSLContext _sslcontext = this.sslcontext; // local variable allows concurrent removeTrustCertificate
        if (_sslcontext == null) {
            try {
                _sslcontext = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
                _sslcontext.init(keyManagers, trustManagers, DEFAULT_RANDOM);
                this.sslcontext = _sslcontext;
            } catch (Exception e) {
                log.debug("Could not create SSL context", e);
                Throwables.throwIfUnchecked(e);
                throw new RuntimeException(e);
            }
        }
        return _sslcontext;
    }

    private static TrustManager[] getTrustManagers(final KeyStoreManager keyStoreManager) throws Exception {
        final X509TrustManager managedTrustManager = getManagedTrustManager(checkNotNull(keyStoreManager));
        final TrustManager[] systemTrustManagers = getSystemTrustManagers();

        if (systemTrustManagers != null && managedTrustManager != null) {
            final TrustManager[] trustManagers = new TrustManager[systemTrustManagers.length];
            for (int i = 0; i < systemTrustManagers.length; i++) {
                final TrustManager tm = trustManagers[i] = systemTrustManagers[i];
                if (tm instanceof X509TrustManager) {
                    trustManagers[i] = new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(final X509Certificate[] chain, final String authType)
                                throws CertificateException {
                            ((X509TrustManager) tm).checkClientTrusted(chain, authType);
                        }

                        @Override
                        public void checkServerTrusted(final X509Certificate[] chain, final String authType)
                                throws CertificateException {
                            try {
                                ((X509TrustManager) tm).checkServerTrusted(chain, authType);
                            } catch (CertificateException e) {
                                try {
                                    managedTrustManager.checkServerTrusted(chain, authType);
                                } catch (CertificateException ignore) {
                                    throw e;
                                }
                            }
                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return ((X509TrustManager) tm).getAcceptedIssuers();
                        }
                    };
                }
            }
            return trustManagers;
        }
        return null;
    }

    private static X509TrustManager getManagedTrustManager(final KeyStoreManager keyStoreManager)
            throws KeystoreException {
        final TrustManager[] managedTrustManagers = keyStoreManager.getTrustManagers();
        if (managedTrustManagers != null) {
            for (TrustManager tm : managedTrustManagers) {
                if (tm instanceof X509TrustManager) {
                    return (X509TrustManager) tm;
                }
            }
        }
        return null;
    }

    private static KeyManager[] getSystemKeyManagers() throws Exception {
        KeyManagerFactory keyManagerFactory;

        String keyAlgorithm = System.getProperty("ssl.KeyManagerFactory.algorithm");
        if (keyAlgorithm == null) {
            keyAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        }
        String keyStoreType = System.getProperty("javax.net.ssl.keyStoreType");
        if (keyStoreType == null) {
            keyStoreType = KeyStore.getDefaultType();
        }
        if ("none".equalsIgnoreCase(keyStoreType)) {
            keyManagerFactory = KeyManagerFactory.getInstance(keyAlgorithm);
        } else {
            final String keyStoreFileName = System.getProperty("javax.net.ssl.keyStore");
            if (keyStoreFileName != null) {
                File keyStoreFile = new File(keyStoreFileName);
                keyManagerFactory = KeyManagerFactory.getInstance(keyAlgorithm);
                String keyStoreProvider = System.getProperty("javax.net.ssl.keyStoreProvider");
                KeyStore keyStore;
                if (keyStoreProvider != null) {
                    keyStore = KeyStore.getInstance(keyStoreType, keyStoreProvider);
                } else {
                    keyStore = KeyStore.getInstance(keyStoreType);
                }
                String password = System.getProperty("javax.net.ssl.keyStorePassword");
                try (FileInputStream in = new FileInputStream(keyStoreFile)) {
                    keyStore.load(in, password != null ? password.toCharArray() : null);
                }
                keyManagerFactory.init(keyStore, password != null ? password.toCharArray() : null);
            } else {
                return null;
            }
        }

        return keyManagerFactory.getKeyManagers();
    }

    private static TrustManager[] getSystemTrustManagers() throws Exception {
        TrustManagerFactory trustManagerFactory;

        String trustAlgorithm = System.getProperty("ssl.TrustManagerFactory.algorithm");
        if (trustAlgorithm == null) {
            trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        }
        String trustStoreType = System.getProperty("javax.net.ssl.trustStoreType");
        if (trustStoreType == null) {
            trustStoreType = KeyStore.getDefaultType();
        }
        if ("none".equalsIgnoreCase(trustStoreType)) {
            trustManagerFactory = TrustManagerFactory.getInstance(trustAlgorithm);
        } else {
            File trustStoreFile;
            KeyStore trustStore;

            String trustStoreFileName = System.getProperty("javax.net.ssl.trustStore");
            if (trustStoreFileName != null) {
                trustStoreFile = new File(trustStoreFileName);
                trustManagerFactory = TrustManagerFactory.getInstance(trustAlgorithm);
                final String trustStoreProvider = System.getProperty("javax.net.ssl.trustStoreProvider");
                if (trustStoreProvider != null) {
                    trustStore = KeyStore.getInstance(trustStoreType, trustStoreProvider);
                } else {
                    trustStore = KeyStore.getInstance(trustStoreType);
                }
            } else {
                File javaHome = new File(System.getProperty("java.home"));
                File file = new File(javaHome, "lib/security/jssecacerts");
                if (!file.exists()) {
                    file = new File(javaHome, "lib/security/cacerts");
                    trustStoreFile = file;
                } else {
                    trustStoreFile = file;
                }

                trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            }
            final String password = System.getProperty("javax.net.ssl.trustStorePassword");
            try (FileInputStream in = new FileInputStream(trustStoreFile)) {
                trustStore.load(in, password != null ? password.toCharArray() : null);
            }
            trustManagerFactory.init(trustStore);
        }
        return trustManagerFactory.getTrustManagers();
    }
}