All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.enterprise.security.ssl.SSLUtils Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.enterprise.security.ssl;

import com.sun.enterprise.security.SecurityLoggerInfo;
import com.sun.enterprise.security.common.Util;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.security.cert.Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;


//V3:Commented import com.sun.enterprise.config.clientbeans.Ssl
import com.sun.enterprise.server.pluggable.SecuritySupport;
//V3:Commented import com.sun.web.security.SSLSocketFactory;
import com.sun.enterprise.security.integration.AppClientSSL;
import java.util.logging.*;
import com.sun.logging.*;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Permission;
import java.util.PropertyPermission;
import javax.net.ssl.SSLSocketFactory;
import org.jvnet.hk2.annotations.Service;
import javax.inject.Inject;
import org.glassfish.hk2.api.PostConstruct;

import javax.inject.Singleton;

/**
 *  Handy class containing static functions.
 * @author Harpreet Singh
 * @author Vivek Nagar
 * @author Shing Wai Chan
 */
@Service
@Singleton
public final class SSLUtils implements PostConstruct {
    private static final String DEFAULT_OUTBOUND_KEY_ALIAS = "s1as";
    public static final String HTTPS_OUTBOUND_KEY_ALIAS = "com.sun.enterprise.security.httpsOutboundKeyAlias";
    private static final String DEFAULT_SSL_PROTOCOL = "TLS";

    private static final Logger _logger = SecurityLoggerInfo.getLogger();

    @Inject
    private SecuritySupport secSupp;

    private boolean hasKey = false;
    private KeyStore mergedTrustStore = null;
    private AppClientSSL appclientSsl = null;
    private SSLContext ctx = null;
    
    public void postConstruct() {
        try {
            //TODO: To check the right implementation once we support EE.
            if(secSupp == null){
                secSupp = SecuritySupport.getDefaultInstance();
            }
            KeyStore[] keyStores = getKeyStores();
            if (keyStores != null) {
                for (KeyStore keyStore : keyStores) {
                    Enumeration aliases = keyStore.aliases();
                    while (aliases.hasMoreElements()) {
                        String alias = (String) aliases.nextElement();
                        if (keyStore.isKeyEntry(alias)) {
                            hasKey = true;
                            break;
                        }
                    }
                    if (hasKey) {
                        break;
                    }
                }
            }
            mergedTrustStore = mergingTrustStores(secSupp.getTrustStores());
            getSSLContext(null, null, null);
        } catch(Exception ex) {
            if (_logger.isLoggable(Level.FINE)) {
                _logger.log(Level.FINE, "SSLUtils static init fails.", ex);
            }
            throw new IllegalStateException(ex);
        }
    }

    SSLContext getSSLContext(String protocol, String algorithm, String trustAlgorithm) {
        try {
            //V3:Commented to break dependency on WebTier.
            //The SSLSocketFactory CTOR will now take care of setting the kmgr and tmgr
            //SSLSocketFactory.setManagers(getKeyManagers(), getTrustManagers());

            // Creating a default SSLContext and HttpsURLConnection for clients
            // that use Https
            if (protocol == null) {
                protocol = DEFAULT_SSL_PROTOCOL;
            }
            ctx = SSLContext.getInstance(protocol);
            String keyAlias = System.getProperty(HTTPS_OUTBOUND_KEY_ALIAS);
            KeyManager[] kMgrs = getKeyManagers(algorithm);
            if (keyAlias != null && keyAlias.length() > 0 && kMgrs != null) {
                for (int i = 0; i < kMgrs.length; i++) {
                    kMgrs[i] = new J2EEKeyManager((X509KeyManager)kMgrs[i], keyAlias);
                }
            }
            ctx.init(kMgrs, getTrustManagers(trustAlgorithm), null);

            HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
            //refer issue :http://java.net/jira/browse/GLASSFISH-15369
            SSLContext.setDefault(ctx);
        } catch (Exception e) {
            throw new Error(e);
        }
        return ctx;
    }

    public boolean verifyMasterPassword(final char[] masterPass) {
        return secSupp.verifyMasterPassword(masterPass);
    }

    public KeyStore[] getKeyStores() throws IOException{
        return secSupp.getKeyStores();
    }

    public KeyStore getKeyStore() throws IOException{
        return getKeyStores()[0];
    }

    public KeyStore[] getTrustStores() throws IOException{
        return secSupp.getTrustStores();
    }

    public KeyStore getTrustStore() throws IOException{
        return getTrustStores()[0];
    }

    /**
     * This API is for temporary purpose.  It will be removed once JSR 196
     * is updated.
     */
    public KeyStore getMergedTrustStore() {
        return mergedTrustStore;
    }

    public KeyManager[] getKeyManagers() throws Exception{
        return getKeyManagers(null);
    }
    public KeyManager[] getKeyManagers(String algorithm) throws IOException,
            KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException{
        return secSupp.getKeyManagers(algorithm);
    } 
    public TrustManager[] getTrustManagers() throws Exception{
        return getTrustManagers(null);
    }
    public TrustManager[] getTrustManagers(String algorithm) throws IOException,
            KeyStoreException, NoSuchAlgorithmException{
        return secSupp.getTrustManagers(algorithm);
    }

    
    public void setAppclientSsl(AppClientSSL ssl){
        appclientSsl = ssl;
    }

    public  AppClientSSL getAppclientSsl() {
        return appclientSsl;
    }

    public static String getKeyStoreType() {
        return System.getProperty(SecuritySupport.KEYSTORE_TYPE_PROP, KeyStore.getDefaultType());
    }

    public static String getTrustStoreType() {
        return System.getProperty(SecuritySupport.TRUSTSTORE_TYPE_PROP, KeyStore.getDefaultType());
    }

    /**
     * This method checks whether a private key is available or not.
     */
    public boolean isKeyAvailable() {
        return hasKey;
    }

    /**
     * Check whether given String is of the form [<TokenName>:]alias
     * where alias is an key entry.
     * @param certNickname
     * @return boolean
     */ 
    public boolean isTokenKeyAlias(String certNickname) throws Exception {
        boolean isTokenKeyAlias = false;
        if (certNickname != null) {
            int ind = certNickname.indexOf(':');
            KeyStore[] kstores = getKeyStores();
            int count = -1;
            String aliasName = null;
            if (ind != -1) {
                String[] tokens = secSupp.getTokenNames();
                String tokenName = certNickname.substring(0, ind);
                aliasName = certNickname.substring(ind + 1);
                for (int i = 0; i < tokens.length; i++) {
                    if (tokenName.equals(tokens[i])) {
                        count = i;
                    }
                }
            }

            if (count != -1) {
                isTokenKeyAlias = kstores[count].isKeyEntry(aliasName);
            } else {
                for (KeyStore kstore : kstores) {
                    if (kstore.isKeyEntry(certNickname)) {
                        isTokenKeyAlias = true;
                        break;
                    }
                }
            }
        }
        return isTokenKeyAlias;
    }

    /**
     * Get a PrivateKeyEntry with certNickName is of the form
     * [<TokenName>:]alias where alias is an key entry.
     * @param certNickname
     * @return PrivateKeyEntry
     */ 
    public PrivateKeyEntry getPrivateKeyEntryFromTokenAlias(
            String certNickname) throws Exception {
        checkPermission(SecuritySupport.KEYSTORE_PASS_PROP);
        PrivateKeyEntry privKeyEntry = null;
        if (certNickname != null) {
            int ind = certNickname.indexOf(':');
            KeyStore[] kstores = getKeyStores();
            int count = -1;
            String aliasName = certNickname;
            if (ind != -1) {
                String[] tokens = secSupp.getTokenNames();
                String tokenName = certNickname.substring(0, ind);
                aliasName = certNickname.substring(ind + 1);
                for (int i = 0; i < tokens.length; i++) {
                    if (tokenName.equals(tokens[i])) {
                        count = i;
                    }
                }
            }

            if (count != -1 && kstores.length >= count) {
                PrivateKey privKey = secSupp.getPrivateKeyForAlias(aliasName, count);
                if (privKey != null) {
                    Certificate[] certs = kstores[count].getCertificateChain(
                            aliasName);
                    privKeyEntry = new PrivateKeyEntry(privKey, certs);
                }
            } else {
                for (int i = 0; i < kstores.length; i++) {
                    PrivateKey privKey = secSupp.getPrivateKeyForAlias(aliasName, i);
                    if (privKey != null) {
                       Certificate[] certs =
                                kstores[i].getCertificateChain(
                                aliasName);
                        privKeyEntry = new PrivateKeyEntry(privKey, certs);
                        break;
                    }
                }
            }
        }

        return privKeyEntry;
    }

    public static void checkPermission(String key) {
        try {
            // Checking a random permission to check if it is server.
            if(Util.isEmbeddedServer() || Util.getDefaultHabitat() == null
                    || Util.getInstance().isACC() || Util.getInstance().isNotServerOrACC()){
                return;
            }
            Permission perm = new RuntimePermission("SSLPassword");
            AccessController.checkPermission(perm);
        } catch (AccessControlException e) {
            String message = e.getMessage();
            Permission perm = new PropertyPermission(key, "read");
            if (message != null) {
                message = message.replace(e.getPermission().toString(), perm.toString());
            }
            throw new AccessControlException(message, perm);
        }
    }
    
    public String[] getSupportedCipherSuites() {
         //postConstruct is already setting this.
         return  HttpsURLConnection.getDefaultSSLSocketFactory().getSupportedCipherSuites();
    }
    
    private KeyStore mergingTrustStores(KeyStore[] trustStores)
            throws IOException, KeyStoreException,
            NoSuchAlgorithmException, CertificateException {
        KeyStore mergedStore;
        try {
            mergedStore = secSupp.loadNullStore("CaseExactJKS", secSupp.getKeyStores().length - 1);
        } catch(KeyStoreException ex) {
            mergedStore = secSupp.loadNullStore("JKS", secSupp.getKeyStores().length - 1);
        }

        String[] tokens = secSupp.getTokenNames();
        for (int i = 0; i < trustStores.length; i++) {
            Enumeration aliases = trustStores[i].aliases();
            while (aliases.hasMoreElements()) {
                String alias = (String)aliases.nextElement();
                Certificate cert = trustStores[i].getCertificate(alias);

                //need to preserve the token:alias name format
                String alias2 = (i < tokens.length - 1)? tokens[i] + ":" + alias : alias;

                String alias3 = alias2;
                boolean alreadyInStore = false;
                Certificate aCert;
                int count = 1;
                while ((aCert = mergedStore.getCertificate(alias3)) != null) {
                    if (aCert.equals(cert)) {
                        alreadyInStore = true;
                        break;
                    }
                    alias3 = alias2 + "__" + count++;
                }
                if (!alreadyInStore) {
                    mergedStore.setCertificateEntry(alias3, cert);
                }
            }
        }
        return mergedStore;
     }

    /**
     * 
     *
     * @param alias  the admin key alias
     * @param protocol the protocol or null, uses "TLS" if this argument is null.
     * @return the SSLSocketFactory from the initialized SSLContext
     */
    public SSLSocketFactory getAdminSocketFactory(String alias, String protocol) {
        return getAdminSSLContext(alias, protocol).getSocketFactory();
    }

    /*
    * @param alias  the admin key alias
    * @param protocol the protocol or null, uses "TLS" if this argument is null.
    * @return the initialized SSLContext
    */
    public SSLContext getAdminSSLContext(String alias, String protocol) {
        try {
            if (protocol == null) {
                protocol = "TLS";
            }
            SSLContext cntxt = SSLContext.getInstance(protocol);
            KeyManager[] kMgrs = getKeyManagers();
            if (alias != null && alias.length() > 0 && kMgrs != null) {
                for (int i = 0; i < kMgrs.length; i++) {
                    kMgrs[i] = new J2EEKeyManager((X509KeyManager)kMgrs[i], alias);
                }
            }
            cntxt.init(kMgrs, getTrustManagers(), null);

            return cntxt;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy