com.sun.enterprise.security.ssl.impl.SecuritySupportImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project for IBM JDK
/*
* 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.impl;
import com.sun.enterprise.security.ssl.manager.UnifiedX509KeyManager;
import com.sun.enterprise.security.ssl.manager.UnifiedX509TrustManager;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.KeyStore;
import java.security.Provider;
//V3:Commented import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.server.pluggable.SecuritySupport;
import java.io.IOException;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.Key;
import java.security.Permission;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.PropertyPermission;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.embedded.Server;
import org.glassfish.internal.api.Globals;
import org.glassfish.logging.annotation.LogMessageInfo;
import org.glassfish.logging.annotation.LogMessagesResourceBundle;
import org.glassfish.logging.annotation.LoggerInfo;
import javax.inject.Inject;
import org.jvnet.hk2.annotations.Service;
import javax.inject.Singleton;
/**
* This implements SecuritySupport used in PluggableFeatureFactory.
* @author Shing Wai Chan
*/
// TODO: when we have two SecuritySupport implementations,
// we create Habitat we'll select which SecuritySupport implementation to use.
@Service
@Singleton
public class SecuritySupportImpl extends SecuritySupport {
private static final String DEFAULT_KEYSTORE_PASS = "changeit";
private static final String DEFAULT_TRUSTSTORE_PASS = "changeit";
@LogMessagesResourceBundle
public static final String SHARED_LOGMESSAGE_RESOURCE = "com.sun.enterprise.security.ssl.LogMessages";
@LoggerInfo(subsystem = "SECURITY - SSL", description = "Security - SSL", publish = true)
public static final String SEC_SSL_LOGGER = "javax.enterprise.system.security.ssl";
protected static final Logger _logger =
Logger.getLogger(SEC_SSL_LOGGER, SHARED_LOGMESSAGE_RESOURCE);
@LogMessageInfo(
message = "The SSL certificate has expired: {0}",
level = "SEVERE",
cause = "Certificate expired.",
action = "Check the expiration date of the certicate.")
private static final String SSL_CERT_EXPIRED = "NCLS-SECURITY-05054";
private static boolean initialized = false;
protected static final List keyStores = new ArrayList();
protected static final List trustStores = new ArrayList();
protected static final List keyStorePasswords = new ArrayList();
protected static final List tokenNames = new ArrayList();
private MasterPasswordImpl masterPasswordHelper = null;
private static boolean instantiated = false;
private Date initDate = new Date();
@Inject
private ServiceLocator habitat;
@Inject
private ProcessEnvironment penv;
public SecuritySupportImpl() {
this(true);
}
protected SecuritySupportImpl(boolean init) {
if (init) {
initJKS();
}
}
private void initJKS() {
String keyStoreFileName = null;
String trustStoreFileName = null;
keyStoreFileName = System.getProperty(keyStoreProp);
trustStoreFileName = System.getProperty(trustStoreProp);
char[] keyStorePass = null;
char[] trustStorePass = null;
if (!isInstantiated()) {
if (habitat == null) {
habitat = Globals.getDefaultHabitat();
}
if (masterPasswordHelper == null && habitat != null) {
masterPasswordHelper = habitat.getService(MasterPasswordImpl.class);
}
if (masterPasswordHelper != null) {
keyStorePass = masterPasswordHelper.getMasterPassword();
trustStorePass = keyStorePass;
}
}
if (penv == null && habitat != null) {
penv = habitat.getService(ProcessEnvironment.class);
}
/*
* If we don't have a keystore password yet check the properties.
* Always do so for the app client case whether the passwords have been
* found from master password helper or not.
*/
if (keyStorePass == null || isACC()) {
final String keyStorePassOverride = System.getProperty(KEYSTORE_PASS_PROP, DEFAULT_KEYSTORE_PASS);
if (keyStorePassOverride != null) {
keyStorePass = keyStorePassOverride.toCharArray();
}
final String trustStorePassOverride = System.getProperty(TRUSTSTORE_PASS_PROP, DEFAULT_TRUSTSTORE_PASS);
if (trustStorePassOverride != null){
trustStorePass = trustStorePassOverride.toCharArray();
}
}
if (!initialized) {
loadStores(
null,
null,
keyStoreFileName,
keyStorePass,
System.getProperty(KEYSTORE_TYPE_PROP, KeyStore.getDefaultType()),
trustStoreFileName,
trustStorePass,
System.getProperty(TRUSTSTORE_TYPE_PROP, KeyStore.getDefaultType()));
Arrays.fill(keyStorePass, ' ');
Arrays.fill(trustStorePass, ' ');
initialized = true;
}
}
private boolean isEmbeddedServer() {
List servers = Server.getServerNames();
if (!servers.isEmpty()) {
return true;
}
return false;
}
private static synchronized boolean isInstantiated() {
if (!instantiated) {
instantiated = true;
return false;
}
return true;
}
/**
* This method will load keystore and truststore and add into
* corresponding list.
* @param tokenName
* @param provider
* @param keyStorePass
* @param keyStoreFile
* @param keyStoreType
* @param trustStorePass
* @param trustStoreFile
* @param trustStoreType
*/
/*protected synchronized static void loadStores(String tokenName,
String storeType, Provider provider,
String keyStoreFile, String keyStorePass,
String trustStoreFile, String trustStorePass) {*/
protected synchronized static void loadStores(
String tokenName,
Provider provider,
String keyStoreFile,
char[] keyStorePass,
String keyStoreType,
String trustStoreFile,
char[] trustStorePass,
String trustStoreType) {
try {
KeyStore keyStore = loadKS(keyStoreType, provider, keyStoreFile,
keyStorePass);
KeyStore trustStore = loadKS(trustStoreType, provider, trustStoreFile,
trustStorePass);
keyStores.add(keyStore);
trustStores.add(trustStore);
keyStorePasswords.add(Arrays.copyOf(keyStorePass, keyStorePass.length));
tokenNames.add(tokenName);
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
/**
* This method load keystore with given keystore file and
* keystore password for a given keystore type and provider.
* It always return a non-null keystore.
* @param keyStoreType
* @param provider
* @param keyStoreFile
* @param keyStorePass
* @retun keystore loaded
*/
private static KeyStore loadKS(String keyStoreType, Provider provider,
String keyStoreFile, char[] keyStorePass)
throws Exception {
KeyStore ks = null;
if (provider != null) {
ks = KeyStore.getInstance(keyStoreType, provider);
} else {
ks = KeyStore.getInstance(keyStoreType);
}
char[] passphrase = keyStorePass;
FileInputStream istream = null;
BufferedInputStream bstream = null;
try {
if (keyStoreFile != null) {
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "Loading keystoreFile = {0}, keystorePass = {1}",
new Object[]{keyStoreFile, keyStorePass});
}
istream = new FileInputStream(keyStoreFile);
bstream = new BufferedInputStream(istream);
}
ks.load(bstream, passphrase);
} finally {
if (bstream != null) {
bstream.close();
}
if (istream != null) {
istream.close();
}
}
return ks;
}
// --- implements SecuritySupport ---
/**
* This method returns an array of keystores containing keys and
* certificates.
*/
public KeyStore[] getKeyStores() {
return keyStores.toArray(new KeyStore[keyStores.size()]);
}
public KeyStore loadNullStore(String type, int index) throws KeyStoreException,
IOException, NoSuchAlgorithmException, CertificateException {
KeyStore ret = KeyStore.getInstance(type);
ret.load(null, keyStorePasswords.get(index));
return ret;
}
public KeyManager[] getKeyManagers(String algorithm) throws IOException,
KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
KeyStore[] kstores = getKeyStores();
ArrayList keyManagers = new ArrayList();
for (int i = 0; i < kstores.length; i++) {
checkCertificateDates(kstores[i]);
KeyManagerFactory kmf = KeyManagerFactory.getInstance(
(algorithm != null) ? algorithm : KeyManagerFactory.getDefaultAlgorithm());
kmf.init(kstores[i], keyStorePasswords.get(i));
KeyManager[] kmgrs = kmf.getKeyManagers();
if (kmgrs != null) {
keyManagers.addAll(Arrays.asList(kmgrs));
}
}
KeyManager keyManager = new UnifiedX509KeyManager(
keyManagers.toArray(new X509KeyManager[keyManagers.size()]),
getTokenNames());
return new KeyManager[]{keyManager};
}
public TrustManager[] getTrustManagers(String algorithm) throws IOException,
KeyStoreException, NoSuchAlgorithmException {
KeyStore[] tstores = getTrustStores();
ArrayList trustManagers = new ArrayList();
for (KeyStore tstore : tstores) {
checkCertificateDates(tstore);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
(algorithm != null) ? algorithm : TrustManagerFactory.getDefaultAlgorithm());
tmf.init(tstore);
TrustManager[] tmgrs = tmf.getTrustManagers();
if (tmgrs != null) {
trustManagers.addAll(Arrays.asList(tmgrs));
}
}
TrustManager trustManager;
if (trustManagers.size() == 1) {
trustManager = trustManagers.get(0);
} else {
trustManager = new UnifiedX509TrustManager(trustManagers.toArray(new X509TrustManager[trustManagers.size()]));
}
return new TrustManager[]{trustManager};
}
/*
* Check X509 certificates in a store for expiration.
*/
private void checkCertificateDates(KeyStore store)
throws KeyStoreException {
Enumeration aliases = store.aliases();
while (aliases.hasMoreElements()) {
Certificate cert = store.getCertificate(aliases.nextElement());
if (cert instanceof X509Certificate) {
if (((X509Certificate) cert).getNotAfter().before(initDate)) {
_logger.log(Level.SEVERE, SSL_CERT_EXPIRED, cert);
}
}
}
}
/**
* This method returns an array of truststores containing certificates.
*/
public KeyStore[] getTrustStores() {
return trustStores.toArray(new KeyStore[trustStores.size()]);
}
public boolean verifyMasterPassword(final char[] masterPass) {
return Arrays.equals(masterPass, keyStorePasswords.get(0));
}
/**
* This method returns an array of token names in order corresponding to
* array of keystores.
*/
public String[] getTokenNames() {
return tokenNames.toArray(new String[tokenNames.size()]);
}
/**
* @param token
* @return a keystore
*/
public KeyStore getKeyStore(String token) {
int idx = getTokenIndex(token);
if (idx < 0) {
return null;
}
return keyStores.get(idx);
}
/**
* @param token
* @return a truststore
*/
public KeyStore getTrustStore(String token) {
int idx = getTokenIndex(token);
if (idx < 0) {
return null;
}
return trustStores.get(idx);
}
/**
* @return returned index
*/
private int getTokenIndex(String token) {
int idx = -1;
if (token != null) {
idx = tokenNames.indexOf(token);
if (idx < 0 && _logger.isLoggable(Level.FINEST)) {
_logger.log(Level.FINEST, "token {0} is not found", token);
}
}
return idx;
}
public void synchronizeKeyFile(Object configContext, String fileRealmName) throws Exception {
//throw new UnsupportedOperationException("Not supported yet in V3.");
}
public void checkPermission(String key) {
try {
// Checking a random permission to check if it is server.
if(isEmbeddedServer() || habitat == null
|| isACC() || 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 boolean isACC() {
return (penv == null ? false : penv.getProcessType().equals(ProcessType.ACC));
}
public boolean isNotServerORACC() {
return penv.getProcessType().equals(ProcessType.Other);
}
public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
checkPermission(KEYSTORE_PASS_PROP);
Key key = keyStores.get(keystoreIndex).getKey(alias, keyStorePasswords.get(keystoreIndex));
if (key instanceof PrivateKey) {
return (PrivateKey) key;
} else {
return null;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy