diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java index 0aa17223cbf..e54b681210a 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/GlassfishSSLSupport.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.enterprise.security.ssl; import com.sun.enterprise.security.SecurityLoggerInfo; @@ -112,11 +112,13 @@ public Object[] getPeerCertificateChain(boolean force) throws IOException { if (session == null) { return null; } + X509Certificate[] certs = null; certs = session.getPeerCertificateChain(); if (certs == null) { certs = new X509Certificate[0]; } + if (certs.length == 0 && force) { session.invalidate(); handshake(); @@ -127,6 +129,7 @@ public Object[] getPeerCertificateChain(boolean force) throws IOException { session = socket.getSession(); } } + return getX509Certs(); } @@ -134,6 +137,7 @@ public Integer getKeySize() throws IOException { if (session == null) { return null; } + Integer keySize = (Integer) session.getValue(KEY_SIZE_KEY); if (keySize == null) { int size = 0; @@ -147,6 +151,7 @@ public Integer getKeySize() throws IOException { keySize = size; session.putValue(KEY_SIZE_KEY, keySize); } + return keySize; } @@ -154,10 +159,12 @@ public String getSessionId() throws IOException { if (session == null) { return null; } + byte[] sessionId = session.getId(); if (sessionId == null) { return null; } + StringBuilder Id = new StringBuilder(); for (byte b : sessionId) { String digit = Integer.toHexString(b); @@ -168,6 +175,7 @@ public String getSessionId() throws IOException { } Id.append(digit); } + return Id.toString(); } diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java index 0f451ae1d4d..c2cd278de08 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java @@ -40,6 +40,8 @@ // Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.enterprise.security.ssl; +import static java.util.logging.Level.FINE; + import java.net.Socket; import java.security.Principal; import java.security.PrivateKey; @@ -56,6 +58,7 @@ import javax.net.ssl.X509ExtendedKeyManager; import javax.net.ssl.X509KeyManager; import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginContext; import com.sun.enterprise.security.SecurityLoggerInfo; @@ -79,15 +82,13 @@ public final class J2EEKeyManager /* implements X509KeyManager */ extends X509Ex private static final Logger _logger = SecurityLoggerInfo.getLogger(); - private X509KeyManager mgr = null; // delegate - - private String alias = null; - - private Map tokenName2MgrMap = null; - private boolean supportTokenAlias = false; + private X509KeyManager x509KeyManager; // delegate + private String alias; + private Map tokenName2MgrMap; + private boolean supportTokenAlias; public J2EEKeyManager(X509KeyManager mgr, String alias) { - this.mgr = mgr; + this.x509KeyManager = mgr; this.alias = alias; if (mgr instanceof UnifiedX509KeyManager) { @@ -106,7 +107,7 @@ public J2EEKeyManager(X509KeyManager mgr, String alias) { } public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) { - return mgr.chooseClientAlias(keyType, issuers, null); + return x509KeyManager.chooseClientAlias(keyType, issuers, null); } public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) { @@ -131,7 +132,7 @@ public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket so // if (im == null) { if (Util.getInstance().isNotServerOrACC()) { // standalone client - clientAlias = mgr.chooseClientAlias(keyType, issuers, socket); + clientAlias = x509KeyManager.chooseClientAlias(keyType, issuers, socket); } else { if (Util.getInstance().isACC()) { ClientSecurityContext ctx = ClientSecurityContext.getCurrent(); @@ -157,9 +158,9 @@ public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket so } else { clientAlias = this.alias; } - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "Choose client Alias :{0}", clientAlias); - } + + _logger.log(FINE, "Choose client Alias :{0}", clientAlias); + return clientAlias; } @@ -177,12 +178,12 @@ public String chooseServerAlias(String keyType, Principal[] issuers, Socket sock if (this.alias != null) { serverAlias = this.alias; } else { - serverAlias = mgr.chooseServerAlias(keyType, issuers, socket); + serverAlias = x509KeyManager.chooseServerAlias(keyType, issuers, socket); } if (_logger.isLoggable(Level.FINE)) { _logger.log(Level.FINE, "Choosing server alias :{0}", serverAlias); } - + return serverAlias; } @@ -193,16 +194,16 @@ public String chooseServerAlias(String keyType, Principal[] issuers, Socket sock * @return the chain of X509 Certificates. */ public X509Certificate[] getCertificateChain(String alias) { - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "Getting certificate chain"); - } + _logger.log(FINE, "Getting certificate chain"); + X509KeyManager keyMgr = getManagerFromToken(alias); + if (keyMgr != null) { String aliasName = alias.substring(alias.indexOf(':') + 1); return keyMgr.getCertificateChain(aliasName); - } else { - return mgr.getCertificateChain(alias); } + + return x509KeyManager.getCertificateChain(alias); } /** @@ -213,10 +214,9 @@ public X509Certificate[] getCertificateChain(String alias) { * @return the array of aliases. */ public String[] getClientAliases(String keyType, Principal[] issuers) { - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "Getting client aliases"); - } - return mgr.getClientAliases(keyType, issuers); + _logger.log(FINE, "Getting client aliases"); + + return x509KeyManager.getClientAliases(keyType, issuers); } /** @@ -227,10 +227,9 @@ public String[] getClientAliases(String keyType, Principal[] issuers) { * @return the array of aliases. */ public String[] getServerAliases(String keyType, Principal[] issuers) { - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "Getting server aliases"); - } - return mgr.getServerAliases(keyType, issuers); + _logger.log(FINE, "Getting server aliases"); + + return x509KeyManager.getServerAliases(keyType, issuers); } /** @@ -240,16 +239,17 @@ public String[] getServerAliases(String keyType, Principal[] issuers) { * @return the private key. */ public PrivateKey getPrivateKey(String alias) { - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "Getting private key for alias:{0}", alias); - } + _logger.log(FINE, "Getting private key for alias:{0}", alias); + X509KeyManager keyMgr = getManagerFromToken(alias); + if (keyMgr != null) { String aliasName = alias.substring(alias.indexOf(':') + 1); return keyMgr.getPrivateKey(aliasName); - } else { - return mgr.getPrivateKey(alias); } + + return x509KeyManager.getPrivateKey(alias); + } /** @@ -278,14 +278,16 @@ private X509KeyManager getManagerFromToken(String tokenAlias) { * @param CallbackHandler the callback handler to gather user information. * @exception LoginException the exception thrown by the callback handler. */ - public static Subject doClientLogin(int type, javax.security.auth.callback.CallbackHandler jaasHandler) throws LoginException { - final javax.security.auth.callback.CallbackHandler handler = jaasHandler; + public static Subject doClientLogin(int type, CallbackHandler jaasHandler) throws LoginException { + final CallbackHandler handler = jaasHandler; + // the subject will actually be filled in with a PasswordCredential // required by the csiv2 layer in the LoginModule. // we create the dummy credential here and call the // set security context. Thus, we have 2 credentials, one each for // the csiv2 layer and the other for the RI. final Subject subject = new Subject(); + // V3:Commented : TODO uncomment later for Appcontainer if (type == SecurityConstants.USERNAME_PASSWORD) { AppservAccessController.doPrivileged(new PrivilegedAction() { diff --git a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java index e211fb23b66..1362c2dcbe1 100644 --- a/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java +++ b/nucleus/security/core/src/main/java/com/sun/enterprise/security/ssl/SSLUtils.java @@ -40,6 +40,8 @@ // Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.enterprise.security.ssl; +import static java.util.logging.Level.FINE; + import java.io.IOException; import java.security.AccessControlException; import java.security.AccessController; @@ -54,7 +56,6 @@ import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.PropertyPermission; -import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; @@ -84,32 +85,34 @@ @Service @Singleton public final class SSLUtils implements PostConstruct { + + private static final Logger _logger = SecurityLoggerInfo.getLogger(); + 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 SecuritySupport securitySupport; - private boolean hasKey = false; - private KeyStore mergedTrustStore = null; - private AppClientSSL appclientSsl = null; - private SSLContext ctx = null; + private boolean hasKey; + private KeyStore mergedTrustStore; + private AppClientSSL appclientSsl; + private SSLContext sslContext; public void postConstruct() { try { // TODO: To check the right implementation once we support EE. - if (secSupp == null) { - secSupp = SecuritySupport.getDefaultInstance(); + if (securitySupport == null) { + securitySupport = SecuritySupport.getDefaultInstance(); } + KeyStore[] keyStores = getKeyStores(); + if (keyStores != null) { for (KeyStore keyStore : keyStores) { - Enumeration aliases = keyStore.aliases(); + Enumeration aliases = keyStore.aliases(); while (aliases.hasMoreElements()) { - String alias = (String) aliases.nextElement(); - if (keyStore.isKeyEntry(alias)) { + if (keyStore.isKeyEntry(aliases.nextElement())) { hasKey = true; break; } @@ -119,12 +122,11 @@ public void postConstruct() { } } } - mergedTrustStore = mergingTrustStores(secSupp.getTrustStores()); + + mergedTrustStore = mergingTrustStores(securitySupport.getTrustStores()); getSSLContext(null, null, null); } catch (Exception ex) { - if (_logger.isLoggable(Level.FINE)) { - _logger.log(Level.FINE, "SSLUtils static init fails.", ex); - } + _logger.log(FINE, "SSLUtils static init fails.", ex); throw new IllegalStateException(ex); } } @@ -140,31 +142,35 @@ SSLContext getSSLContext(String protocol, String algorithm, String trustAlgorith if (protocol == null) { protocol = DEFAULT_SSL_PROTOCOL; } - ctx = SSLContext.getInstance(protocol); + + sslContext = 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); + + KeyManager[] keyManagers = getKeyManagers(algorithm); + if (keyAlias != null && keyAlias.length() > 0 && keyManagers != null) { + for (int i = 0; i < keyManagers.length; i++) { + keyManagers[i] = new J2EEKeyManager((X509KeyManager) keyManagers[i], keyAlias); } } - ctx.init(kMgrs, getTrustManagers(trustAlgorithm), null); + sslContext.init(keyManagers, getTrustManagers(trustAlgorithm), null); - HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory()); - // refer issue :http://java.net/jira/browse/GLASSFISH-15369 - SSLContext.setDefault(ctx); + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); + + // See https://github.com/eclipse-ee4j/glassfish/issues/15369 + SSLContext.setDefault(sslContext); } catch (Exception e) { throw new Error(e); } - return ctx; + + return sslContext; } - public boolean verifyMasterPassword(final char[] masterPass) { - return secSupp.verifyMasterPassword(masterPass); + public boolean verifyMasterPassword(char[] masterPass) { + return securitySupport.verifyMasterPassword(masterPass); } public KeyStore[] getKeyStores() throws IOException { - return secSupp.getKeyStores(); + return securitySupport.getKeyStores(); } public KeyStore getKeyStore() throws IOException { @@ -172,7 +178,7 @@ public KeyStore getKeyStore() throws IOException { } public KeyStore[] getTrustStores() throws IOException { - return secSupp.getTrustStores(); + return securitySupport.getTrustStores(); } public KeyStore getTrustStore() throws IOException { @@ -190,9 +196,8 @@ public KeyManager[] getKeyManagers() throws Exception { return getKeyManagers(null); } - public KeyManager[] getKeyManagers(String algorithm) - throws IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { - return secSupp.getKeyManagers(algorithm); + public KeyManager[] getKeyManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { + return securitySupport.getKeyManagers(algorithm); } public TrustManager[] getTrustManagers() throws Exception { @@ -200,7 +205,7 @@ public TrustManager[] getTrustManagers() throws Exception { } public TrustManager[] getTrustManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException { - return secSupp.getTrustManagers(algorithm); + return securitySupport.getTrustManagers(algorithm); } public void setAppclientSsl(AppClientSSL ssl) { @@ -240,7 +245,7 @@ public boolean isTokenKeyAlias(String certNickname) throws Exception { int count = -1; String aliasName = null; if (ind != -1) { - String[] tokens = secSupp.getTokenNames(); + String[] tokens = securitySupport.getTokenNames(); String tokenName = certNickname.substring(0, ind); aliasName = certNickname.substring(ind + 1); for (int i = 0; i < tokens.length; i++) { @@ -279,7 +284,7 @@ public PrivateKeyEntry getPrivateKeyEntryFromTokenAlias(String certNickname) thr int count = -1; String aliasName = certNickname; if (ind != -1) { - String[] tokens = secSupp.getTokenNames(); + String[] tokens = securitySupport.getTokenNames(); String tokenName = certNickname.substring(0, ind); aliasName = certNickname.substring(ind + 1); for (int i = 0; i < tokens.length; i++) { @@ -290,14 +295,14 @@ public PrivateKeyEntry getPrivateKeyEntryFromTokenAlias(String certNickname) thr } if (count != -1 && kstores.length >= count) { - PrivateKey privKey = secSupp.getPrivateKeyForAlias(aliasName, count); + PrivateKey privKey = securitySupport.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); + PrivateKey privKey = securitySupport.getPrivateKeyForAlias(aliasName, i); if (privKey != null) { Certificate[] certs = kstores[i].getCertificateChain(aliasName); privKeyEntry = new PrivateKeyEntry(privKey, certs); @@ -313,19 +318,19 @@ public PrivateKeyEntry getPrivateKeyEntryFromTokenAlias(String certNickname) thr 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()) { + if (Util.isEmbeddedServer() || Util.getDefaultHabitat() == null || Util.getInstance().isACC() || Util.getInstance().isNotServerOrACC()) { return; } - Permission perm = new RuntimePermission("SSLPassword"); - AccessController.checkPermission(perm); + + AccessController.checkPermission(new RuntimePermission("SSLPassword")); } catch (AccessControlException e) { String message = e.getMessage(); - Permission perm = new PropertyPermission(key, "read"); + Permission permission = new PropertyPermission(key, "read"); if (message != null) { - message = message.replace(e.getPermission().toString(), perm.toString()); + message = message.replace(e.getPermission().toString(), permission.toString()); } - throw new AccessControlException(message, perm); + + throw new AccessControlException(message, permission); } } @@ -334,23 +339,22 @@ public String[] getSupportedCipherSuites() { return HttpsURLConnection.getDefaultSSLSocketFactory().getSupportedCipherSuites(); } - private KeyStore mergingTrustStores(KeyStore[] trustStores) - throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { + private KeyStore mergingTrustStores(KeyStore[] trustStores) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { KeyStore mergedStore; try { - mergedStore = secSupp.loadNullStore("CaseExactJKS", secSupp.getKeyStores().length - 1); + mergedStore = securitySupport.loadNullStore("CaseExactJKS", securitySupport.getKeyStores().length - 1); } catch (KeyStoreException ex) { - mergedStore = secSupp.loadNullStore("JKS", secSupp.getKeyStores().length - 1); + mergedStore = securitySupport.loadNullStore("JKS", securitySupport.getKeyStores().length - 1); } - String[] tokens = secSupp.getTokenNames(); + String[] tokens = securitySupport.getTokenNames(); for (int i = 0; i < trustStores.length; i++) { - Enumeration aliases = trustStores[i].aliases(); + 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 + // Need to preserve the token:alias name format String alias2 = (i < tokens.length - 1) ? tokens[i] + ":" + alias : alias; String alias3 = alias2; @@ -369,6 +373,7 @@ private KeyStore mergingTrustStores(KeyStore[] trustStores) } } } + return mergedStore; } @@ -395,16 +400,18 @@ public SSLContext getAdminSSLContext(String alias, String protocol) { 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); + + SSLContext adminSSLContextxt = SSLContext.getInstance(protocol); + + KeyManager[] keyManagers = getKeyManagers(); + if (alias != null && alias.length() > 0 && keyManagers != null) { + for (int i = 0; i < keyManagers.length; i++) { + keyManagers[i] = new J2EEKeyManager((X509KeyManager) keyManagers[i], alias); } } - cntxt.init(kMgrs, getTrustManagers(), null); + adminSSLContextxt.init(keyManagers, getTrustManagers(), null); - return cntxt; + return adminSSLContextxt; } catch (Exception e) { throw new RuntimeException(e); } diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java index 8e93802b2a8..d2955a77421 100644 --- a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java +++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/MasterPasswordImpl.java @@ -37,40 +37,43 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.enterprise.security.ssl.impl; -import com.sun.enterprise.security.store.IdentityManagement; -import com.sun.enterprise.security.store.PasswordAdapter; import java.io.IOException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; + import javax.inject.Inject; import javax.inject.Singleton; + import org.glassfish.security.common.MasterPassword; import org.jvnet.hk2.annotations.Optional; import org.jvnet.hk2.annotations.Service; +import com.sun.enterprise.security.store.IdentityManagement; +import com.sun.enterprise.security.store.PasswordAdapter; + /** - * A contract to pass the Glassfish master password between the admin module and - * the security module. + * A contract to pass the Payara master password between the admin module and the security module. * * @author Sudarsan Sridhar */ -@Service(name="Security SSL Password Provider Service") +@Service(name = "Security SSL Password Provider Service") @Singleton public class MasterPasswordImpl implements MasterPassword { - @Inject @Optional IdentityManagement idm; + @Inject + @Optional + IdentityManagement identityManagement; @Override public PasswordAdapter getMasterPasswordAdapter() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException { - char pw[] = idm == null ? null : idm.getMasterPassword(); - return new PasswordAdapter(pw); + return new PasswordAdapter(identityManagement == null ? null : identityManagement.getMasterPassword()); } - + public char[] getMasterPassword() { - return idm == null ? null : idm.getMasterPassword(); + return identityManagement == null ? null : identityManagement.getMasterPassword(); } } \ No newline at end of file diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java index 3e6ee075d36..060e204571e 100644 --- a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java +++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/security/ssl/impl/SecuritySupportImpl.java @@ -40,59 +40,68 @@ // Portions Copyright [2018] [Payara Foundation and/or its affiliates]" 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 static java.lang.System.getProperty; +import static java.util.Arrays.asList; +import static java.util.Arrays.copyOf; +import static java.util.logging.Level.FINE; +import static java.util.logging.Level.FINEST; +import static java.util.logging.Level.SEVERE; + 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.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.Permission; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.Enumeration; +import java.util.List; +import java.util.Map; import java.util.PropertyPermission; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; + +import javax.inject.Inject; +import javax.inject.Singleton; 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.api.admin.ServerEnvironment; import org.glassfish.hk2.api.ServiceLocator; -import org.glassfish.internal.embedded.Server; import org.glassfish.internal.api.Globals; +import org.glassfish.internal.embedded.Server; 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.Optional; import org.jvnet.hk2.annotations.Service; -import javax.inject.Singleton; -import org.glassfish.api.admin.ServerEnvironment; -import org.jvnet.hk2.annotations.Optional; +import com.sun.enterprise.security.ssl.manager.UnifiedX509KeyManager; +import com.sun.enterprise.security.ssl.manager.UnifiedX509TrustManager; +//V3:Commented import com.sun.enterprise.config.ConfigContext; +import com.sun.enterprise.server.pluggable.SecuritySupport; /** * This implements SecuritySupport used in PluggableFeatureFactory. + * * @author Shing Wai Chan */ // TODO: when we have two SecuritySupport implementations, @@ -100,41 +109,44 @@ @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); + 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 final String DEFAULT_KEYSTORE_PASS = "changeit"; + private static final String DEFAULT_TRUSTSTORE_PASS = "changeit"; - @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 final Map> keyStores = new ConcurrentHashMap<>(); + private static final Map> trustStores = new ConcurrentHashMap<>(); + private static final Map> keyStorePasswords = new ConcurrentHashMap<>(); + private static final Map> tokenNames = new ConcurrentHashMap<>(); - 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 static final String DEFAULT_MAP_KEY = "key"; + + private static boolean instantiated; + private static boolean initialized; + private Date initDate = new Date(); @Inject - private ServiceLocator habitat; + private ServiceLocator serviceLocator; + @Inject - private ProcessEnvironment penv; - - @Inject @Optional - private ServerEnvironment senv; + private ProcessEnvironment processEnvironment; + + @Inject + @Optional + private ServerEnvironment serverEnvironment; + + private MasterPasswordImpl masterPasswordHelper; public SecuritySupportImpl() { this(true); @@ -145,86 +157,311 @@ protected SecuritySupportImpl(boolean init) { initJKS(); } } + - private void initJKS() { - String keyStoreFileName = null; - String trustStoreFileName = null; + // --- implements SecuritySupport --- + + /** + * This method returns an array of keystores containing keys and certificates. + */ + @Override + public KeyStore[] getKeyStores() { + List keyStoresList = keyStores.get(DEFAULT_MAP_KEY); + + return keyStoresList.toArray(new KeyStore[keyStoresList.size()]); + } + + /** + * This method returns an array of truststores containing certificates. + */ + @Override + public KeyStore[] getTrustStores() { + List trustStoresList = trustStores.get(DEFAULT_MAP_KEY); + + return trustStoresList.toArray(new KeyStore[trustStoresList.size()]); + } + + /** + * This method returns an array of token names in order corresponding to array of keystores. + */ + @Override + public String[] getTokenNames() { + List tokenNamesList = tokenNames.get(DEFAULT_MAP_KEY); + + return tokenNamesList.toArray(new String[tokenNamesList.size()]); + } + + /** + * @param token + * @return a keystore + */ + @Override + public KeyStore getKeyStore(String token) { + int tokenIndex = getTokenIndex(token); + if (tokenIndex < 0) { + return null; + } + + return keyStores.get(DEFAULT_MAP_KEY).get(tokenIndex); + } + + /** + * @param token + * @return a truststore + */ + @Override + public KeyStore getTrustStore(String token) { + int tokenIndex = getTokenIndex(token); + if (tokenIndex < 0) { + return null; + } + + return trustStores.get(DEFAULT_MAP_KEY).get(tokenIndex); + } + + @Override + public void reset() { + // Get store passwords from the master helper first + char[] keyStorePass = masterPasswordHelper.getMasterPassword(); + char[] trustStorePass = keyStorePass; + + // Re-load stores (which looks at the system properties for the file names and potentially passwords) + initStores(keyStorePass, trustStorePass); + } + + @Override + public KeyStore loadNullStore(String type, int index) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { + KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(null, keyStorePasswords.get(DEFAULT_MAP_KEY).get(index)); + + return keyStore; + } + + @Override + public KeyManager[] getKeyManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { + KeyStore[] keyStores = getKeyStores(); + + ArrayList keyManagers = new ArrayList(); + for (int i = 0; i < keyStores.length; i++) { + checkCertificateDates(keyStores[i]); + + KeyManager[] keyManagersPerStore = getKeyManagerFactory(keyStores[i], keyStorePasswords.get(DEFAULT_MAP_KEY).get(i), algorithm).getKeyManagers(); + if (keyManagersPerStore != null) { + keyManagers.addAll(asList(keyManagersPerStore)); + } + } + + KeyManager keyManager = new UnifiedX509KeyManager( + keyManagers.toArray(new X509KeyManager[keyManagers.size()]), + getTokenNames()); + + return new KeyManager[] { keyManager }; + } + + @Override + public TrustManager[] getTrustManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException { + + ArrayList trustManagers = new ArrayList(); + for (KeyStore trustStore : getTrustStores()) { + checkCertificateDates(trustStore); + + TrustManager[] trustManagersPerStore = getTrustManagerFactory(trustStore, algorithm).getTrustManagers(); + if (trustManagersPerStore != null) { + trustManagers.addAll(asList(trustManagersPerStore)); + } + } + + TrustManager trustManager; + if (trustManagers.size() == 1) { + trustManager = trustManagers.get(0); + } else { + trustManager = new UnifiedX509TrustManager(trustManagers.toArray(new X509TrustManager[trustManagers.size()])); + } + + return new TrustManager[] { trustManager }; + } + + @Override + public boolean verifyMasterPassword(char[] masterPass) { + return Arrays.equals(masterPass, keyStorePasswords.get(DEFAULT_MAP_KEY).get(0)); + } + + @Override + public void synchronizeKeyFile(Object configContext, String fileRealmName) throws Exception { + // throw new UnsupportedOperationException("Not supported yet in V3."); + } + + @Override + public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { + checkPermission(KEYSTORE_PASS_PROP); + + Key key = keyStores + .get(DEFAULT_MAP_KEY) + .get(keystoreIndex) + .getKey( + alias, + keyStorePasswords + .get(DEFAULT_MAP_KEY) + .get(keystoreIndex)); + + if (key instanceof PrivateKey) { + return (PrivateKey) key; + } + + return null; + } + + @Override + public void checkPermission(String key) { + try { + // Checking a random permission to check if it is server. + if (isEmbeddedServer() || serviceLocator == null || isACC() || isNotServerORACC()) { + return; + } + + AccessController.checkPermission(new RuntimePermission("SSLPassword")); + } catch (AccessControlException e) { + Permission permission = new PropertyPermission(key, "read"); + + String message = e.getMessage(); + if (message != null) { + message = message.replace(e.getPermission().toString(), permission.toString()); + } + + throw new AccessControlException(message, permission); + } + } + + /** + * @return returned index + */ + private int getTokenIndex(String token) { + int tokenIndex = -1; + if (token != null) { + tokenIndex = tokenNames.get(DEFAULT_MAP_KEY).indexOf(token); + if (tokenIndex < 0 && _logger.isLoggable(FINEST)) { + _logger.log(FINEST, "token {0} is not found", token); + } + } - keyStoreFileName = System.getProperty(keyStoreProp); - trustStoreFileName = System.getProperty(trustStoreProp); + return tokenIndex; + } + + public boolean isACC() { + return processEnvironment == null ? false : processEnvironment.getProcessType().equals(ProcessType.ACC); + } + public boolean isNotServerORACC() { + return processEnvironment.getProcessType().equals(ProcessType.Other); + } + + private void initJKS() { char[] keyStorePass = null; char[] trustStorePass = null; + if (!isInstantiated()) { - if (habitat == null) { - habitat = Globals.getDefaultHabitat(); + if (serviceLocator == null) { + serviceLocator = Globals.getDefaultHabitat(); } - if (masterPasswordHelper == null && habitat != null) { - masterPasswordHelper = habitat.getService(MasterPasswordImpl.class); + + if (masterPasswordHelper == null && serviceLocator != null) { + masterPasswordHelper = serviceLocator.getService(MasterPasswordImpl.class); } + if (masterPasswordHelper != null) { keyStorePass = masterPasswordHelper.getMasterPassword(); trustStorePass = keyStorePass; } } - if (penv == null && habitat != null) { - penv = habitat.getService(ProcessEnvironment.class); - } - - if (senv == null && habitat != null) { - senv = habitat.getService(ServerEnvironment.class); + + if (processEnvironment == null && serviceLocator != null) { + processEnvironment = serviceLocator.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() || (senv != null && senv.isMicro())) { - 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 (serverEnvironment == null && serviceLocator != null) { + serverEnvironment = serviceLocator.getService(ServerEnvironment.class); } 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, ' '); + initStores(keyStorePass, trustStorePass); initialized = true; } } - - private boolean isEmbeddedServer() { - List servers = Server.getServerNames(); - if (!servers.isEmpty()) { - return true; + + /** + * This method will get the keystore and trust store files and optionally the passwords from system properties, + * and then load both the keystore and truststore and add them into their corresponding list. + * + * @param keyStorePass the password for the keystore, may be null, may be ignored. + * @param trustStorePass the password for the truststore, may be null, may be ignored. + */ + private void initStores(char[] keyStorePassIn, char[] trustStorePassIn) { + String keyStoreFileName = System.getProperty(keyStoreProp); + String trustStoreFileName = System.getProperty(trustStoreProp); + + // Initially consider the passwords that are passed-in + char[] keyStorePass = keyStorePassIn; + char[] trustStorePass = trustStorePassIn; + + // Under certain conditions, try get passwords from system properties instead + if (shouldGetPassFromProperty(keyStorePass)) { + keyStorePass = getKeyStorePass(keyStorePass); + trustStorePass = getTrustStorePass(trustStorePass); } - return false; + + initStores(keyStoreFileName, keyStorePass, trustStoreFileName, trustStorePass); } - - private static synchronized boolean isInstantiated() { - if (!instantiated) { - instantiated = true; - return false; + + /** + * This method will load keystore and truststore and add into corresponding list. + * + * @param keyStoreFileName + * @param keyStorePass + * @param trustStoreFileName + * @param trustStorePass + */ + private static void initStores(String keyStoreFileName, char[] keyStorePass, String trustStoreFileName, char[] trustStorePass) { + try { + + // Create the initial lists to store the various data items + + List keyStoresList = new ArrayList(); + List trustStoresList = new ArrayList(); + List keyStorePasswordsList = new ArrayList(); + List tokenNamesList = new ArrayList(); + + // Add the first item to each list + + keyStoresList.add(loadStore(getProperty(KEYSTORE_TYPE_PROP, KeyStore.getDefaultType()), null, keyStoreFileName, keyStorePass)); + trustStoresList.add(loadStore(getProperty(TRUSTSTORE_TYPE_PROP, KeyStore.getDefaultType()), null, trustStoreFileName, trustStorePass)); + keyStorePasswordsList.add(copyOf(keyStorePass, keyStorePass.length)); + tokenNamesList.add(null); // This is slightly weird, but the original code did this too. + + // Atomically put each list in the concurrent maps holding that list + // Note: this can either be the first insert for when this service is first initialized, or can + // refresh existing ones. + + keyStores.put(DEFAULT_MAP_KEY, keyStoresList); + trustStores.put(DEFAULT_MAP_KEY, trustStoresList); + keyStorePasswords.put(DEFAULT_MAP_KEY, keyStorePasswordsList); + tokenNames.put(DEFAULT_MAP_KEY, tokenNamesList); + + } catch (Exception ex) { + _logger.severe("Failed to load key stores " + ex.getMessage()); + throw new IllegalStateException(ex); + } finally { + + // Clear out the passwords (and ignore they already have been assigned many times to various strings) + + Arrays.fill(keyStorePass, ' '); + Arrays.fill(trustStorePass, ' '); } - return true; + } /** - * This method will load keystore and truststore and add into - * corresponding list. + * This method will load keystore and truststore and add into corresponding list. + * * @param tokenName * @param provider * @param keyStorePass @@ -234,252 +471,126 @@ private static synchronized boolean isInstantiated() { * @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) { - + 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); + keyStores.get(DEFAULT_MAP_KEY).add(loadStore(keyStoreType, provider, keyStoreFile, keyStorePass)); + trustStores.get(DEFAULT_MAP_KEY).add(loadStore(trustStoreType, provider, trustStoreFile, trustStorePass)); + keyStorePasswords.get(DEFAULT_MAP_KEY).add(Arrays.copyOf(keyStorePass, keyStorePass.length)); + tokenNames.get(DEFAULT_MAP_KEY).add(tokenName); } catch (Exception ex) { _logger.severe("Failed to load key stores " + ex.getMessage()); 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. + * This method loads a single 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; + private static KeyStore loadStore(String keyStoreType, Provider provider, String keyStoreFile, char[] keyStorePass) throws Exception { + KeyStore keyStore = null; + if (provider != null) { - ks = KeyStore.getInstance(keyStoreType, provider); + keyStore = KeyStore.getInstance(keyStoreType, provider); } else { - ks = KeyStore.getInstance(keyStoreType); + keyStore = 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; - } + if (keyStoreFile != null) { + try (BufferedInputStream stream = new BufferedInputStream(new FileInputStream(keyStoreFile))) { - 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}; - } + if (_logger.isLoggable(FINE)) { + _logger.log(FINE, "Loading keystoreFile = {0}, keystorePass = {1}", new Object[] { keyStoreFile, keyStorePass }); + } - 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)); + keyStore.load(stream, keyStorePass); } - } - 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); - } - } + keyStore.load(null, keyStorePass); } - } - /** - * This method returns an array of truststores containing certificates. - */ - public KeyStore[] getTrustStores() { - return trustStores.toArray(new KeyStore[trustStores.size()]); + return keyStore; } - - public boolean verifyMasterPassword(final char[] masterPass) { - return Arrays.equals(masterPass, keyStorePasswords.get(0)); + + private boolean isEmbeddedServer() { + return !Server.getServerNames().isEmpty(); } - - /** - * This method returns an array of token names in order corresponding to - * array of keystores. + + /* + * 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. */ - public String[] getTokenNames() { - return tokenNames.toArray(new String[tokenNames.size()]); + private boolean shouldGetPassFromProperty(char[] keyStorePass) { + return keyStorePass == null || isACC() || (serverEnvironment != null && serverEnvironment.isMicro()); } - - /** - * @param token - * @return a keystore - */ - public KeyStore getKeyStore(String token) { - int idx = getTokenIndex(token); - if (idx < 0) { - return null; + + private char[] getKeyStorePass(char[] keyStorePass) { + String keyStorePassOverride = System.getProperty(KEYSTORE_PASS_PROP, DEFAULT_KEYSTORE_PASS); + if (keyStorePassOverride == null) { + return keyStorePass; } - return keyStores.get(idx); + + return keyStorePassOverride.toCharArray(); } - - /** - * @param token - * @return a truststore - */ - public KeyStore getTrustStore(String token) { - int idx = getTokenIndex(token); - if (idx < 0) { - return null; + + private char[] getTrustStorePass(char[] trustStorePass) { + String trustStorePassOverride = System.getProperty(TRUSTSTORE_PASS_PROP, DEFAULT_TRUSTSTORE_PASS); + if (trustStorePassOverride == null) { + return trustStorePass; } - return trustStores.get(idx); + + return trustStorePassOverride.toCharArray(); } - /** - * @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); - } + private static synchronized boolean isInstantiated() { + if (!instantiated) { + instantiated = true; + return false; } - return idx; - } - public void synchronizeKeyFile(Object configContext, String fileRealmName) throws Exception { - //throw new UnsupportedOperationException("Not supported yet in V3."); + return true; } - - 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()); + + /* + * Check X509 certificates in a store for expiration. + */ + private void checkCertificateDates(KeyStore keyStore) throws KeyStoreException { + Enumeration aliases = keyStore.aliases(); + + while (aliases.hasMoreElements()) { + Certificate certificate = keyStore.getCertificate(aliases.nextElement()); + if (certificate instanceof X509Certificate) { + if (((X509Certificate) certificate).getNotAfter().before(initDate)) { + _logger.log(SEVERE, SSL_CERT_EXPIRED, certificate); + } } - 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); + + private TrustManagerFactory getTrustManagerFactory(KeyStore trustStore, String algorithm) throws NoSuchAlgorithmException, KeyStoreException { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + algorithm != null ? algorithm : TrustManagerFactory.getDefaultAlgorithm()); + + trustManagerFactory.init(trustStore); + + return trustManagerFactory; } - - 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; - } + + private KeyManagerFactory getKeyManagerFactory(KeyStore keyStore, char[] keyStorePassword, String algorithm) throws NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException { + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance( + algorithm != null ? algorithm : KeyManagerFactory.getDefaultAlgorithm()); + + keyManagerFactory.init(keyStore, keyStorePassword); + + return keyManagerFactory; } + } diff --git a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java index 1e4cd3eeaca..c68d8763140 100644 --- a/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java +++ b/nucleus/security/ssl-impl/src/main/java/com/sun/enterprise/server/pluggable/SecuritySupport.java @@ -37,13 +37,12 @@ * only if the new code is made subject to such option by the copyright * holder. */ - +// Portions Copyright [2018] [Payara Foundation and/or its affiliates] package com.sun.enterprise.server.pluggable; import com.sun.enterprise.security.ssl.impl.SecuritySupportImpl; import java.io.IOException; import java.security.KeyStore; -//V3:Commented import com.sun.enterprise.config.ConfigContext; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; @@ -54,8 +53,15 @@ import org.jvnet.hk2.annotations.Contract; /** - * SecuritySupport is part of PluggableFeature that provides access to - * internal services managed by application server. + * SecuritySupport is part of PluggableFeature that provides access to internal services managed by application server. + * + *

+ * SecuritySupport deals with loading, caching and providing access to key stores and trust stores, including their managers. + * + *

+ * This is mainly used via the com.sun.enterprise.security.ssl.SSLUtils facade, though various other classes + * such as the BaseContainerCallbackHandler use this directly. + * * @author Shing Wai Chan */ @Contract @@ -77,10 +83,8 @@ public static SecuritySupport getDefaultInstance() { return defaultInstance; } - /** - * This method returns an array of keystores containing keys and - * certificates. + * This method returns an array of keystores containing keys and certificates. */ abstract public KeyStore[] getKeyStores(); @@ -90,31 +94,17 @@ public static SecuritySupport getDefaultInstance() { abstract public KeyStore[] getTrustStores(); /** - * @param token + * @param token * @return a keystore. If token is null, return the the first keystore. */ abstract public KeyStore getKeyStore(String token); /** - * @param token + * @param token * @return a truststore. If token is null, return the first truststore. */ abstract public KeyStore getTrustStore(String token); - /** - * @param type - * @param index - * @return load a null keystore of given type. - */ - abstract public KeyStore loadNullStore(String type, int index) throws KeyStoreException, - IOException, NoSuchAlgorithmException, CertificateException; - - /** - * @param masterPass - * @return result whether the given master password is correct. - */ - abstract public boolean verifyMasterPassword(final char[] masterPass); - /** * @param algorithm * @return KeyManagers for the specified algorithm. @@ -123,8 +113,7 @@ abstract public KeyStore loadNullStore(String type, int index) throws KeyStoreEx * @throws NoSuchAlgorithmException * @throws UnrecoverableKeyException */ - abstract public KeyManager[] getKeyManagers(String algorithm) throws IOException, - KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException; + abstract public KeyManager[] getKeyManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException; /** * @param algorithm @@ -133,12 +122,34 @@ abstract public KeyManager[] getKeyManagers(String algorithm) throws IOException * @throws KeyStoreException * @throws NoSuchAlgorithmException */ - abstract public TrustManager[] getTrustManagers(String algorithm) throws IOException, - KeyStoreException, NoSuchAlgorithmException; + abstract public TrustManager[] getTrustManagers(String algorithm) throws IOException, KeyStoreException, NoSuchAlgorithmException; + + /** + * Resets the security instance by effectively re-initializing it. + * + *

+ * This means the default keystores and truststores will be reloaded from their default locations (which may be configured + * by system properties, such as with the default SecuritySupport instance). + */ + public void reset() { + // Do nothing by default + } + + /** + * @param type + * @param index + * @return load a null keystore of given type. + */ + abstract public KeyStore loadNullStore(String type, int index) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException; /** - * Gets the PrivateKey for specified alias from the corresponding keystore - * indicated by the index. + * @param masterPass + * @return result whether the given master password is correct. + */ + abstract public boolean verifyMasterPassword(final char[] masterPass); + + /** + * Gets the PrivateKey for specified alias from the corresponding keystore indicated by the index. * * @param alias Alias for which the PrivateKey is desired. * @param keystoreIndex Index of the keystore. @@ -147,31 +158,29 @@ abstract public TrustManager[] getTrustManagers(String algorithm) throws IOExcep * @throws NoSuchAlgorithmException * @throws UnrecoverableKeyException */ - abstract public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex) - throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException; + abstract public PrivateKey getPrivateKeyForAlias(String alias, int keystoreIndex) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException; /** - * This method returns an array of token names in order corresponding to - * array of keystores. + * This method returns an array of token names in order corresponding to array of keystores. */ abstract public String[] getTokenNames(); /** * This method synchronize key file for given realm. + * * @param config the ConfigContextx * @param fileRealmName * @exception if fail to synchronize, a known exception is - * com.sun.enterprise.ee.synchronization.SynchronizationException + * com.sun.enterprise.ee.synchronization.SynchronizationException */ /** TODO:V3:Cluster ConfigContext is no longer present so find out what this needs to be */ - //public void synchronizeKeyFile(ConfigContext config, String fileRealmName) - abstract public void synchronizeKeyFile(Object configContext, String fileRealmName) - throws Exception; + abstract public void synchronizeKeyFile(Object configContext, String fileRealmName) throws Exception; /** * Check permission for the given key. + * * @param key */ abstract public void checkPermission(String key); - + }