diff --git a/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java b/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java index 22ad3f23f7..762b6ce7d0 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/GhidraRun.java @@ -32,7 +32,6 @@ import ghidra.framework.main.FrontEndTool; import ghidra.framework.model.*; import ghidra.framework.plugintool.dialog.ExtensionUtils; import ghidra.framework.project.DefaultProjectManager; -import ghidra.framework.remote.InetNameLookup; import ghidra.framework.store.LockException; import ghidra.program.database.ProgramDB; import ghidra.util.*; @@ -94,9 +93,6 @@ public class GhidraRun implements GhidraLaunchable { }); }; - // Automatically disable reverse name lookup if failure occurs - InetNameLookup.setDisableOnFailure(true); - // Start main thread in GhidraThreadGroup Thread mainThread = new Thread(new GhidraThreadGroup(), mainTask, "Ghidra"); mainThread.start(); diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java index 192d049774..a2fd22595a 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/RepositoryManager.java @@ -25,9 +25,9 @@ import java.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ghidra.framework.remote.InetNameLookup; import ghidra.framework.store.local.IndexedLocalFileSystem; import ghidra.framework.store.local.LocalFileSystem; +import ghidra.server.remote.InetNameLookup; import ghidra.server.remote.RepositoryServerHandleImpl; import ghidra.util.NamingUtilities; import ghidra.util.StringUtilities; diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java index f0bb2ad17e..2a92791fa7 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java @@ -751,6 +751,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan // keystore has not been identified - use self-signed certificate ApplicationKeyManagerFactory.setDefaultIdentity( new X500Principal("CN=GhidraServer")); + ApplicationKeyManagerFactory.addSubjectAlternativeName(hostname); } if (!ApplicationKeyManagerFactory.initialize()) { log.fatal("Failed to initialize PKI/SSL keystore"); diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/InetNameLookup.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/InetNameLookup.java similarity index 98% rename from Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/InetNameLookup.java rename to Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/InetNameLookup.java index 1283125523..b8197af577 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/remote/InetNameLookup.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/InetNameLookup.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ghidra.framework.remote; +package ghidra.server.remote; import java.net.InetAddress; import java.net.UnknownHostException; diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ClientUtil.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ClientUtil.java index af1056cb44..dffbef38a4 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ClientUtil.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ClientUtil.java @@ -18,7 +18,6 @@ package ghidra.framework.client; import java.awt.Component; import java.io.IOException; import java.net.Authenticator; -import java.net.UnknownHostException; import java.rmi.*; import java.security.GeneralSecurityException; import java.util.Arrays; @@ -50,7 +49,7 @@ public class ClientUtil { /** * Set client authenticator - * @param authenticator + * @param authenticator client authenticator instance */ public static synchronized void setClientAuthenticator(ClientAuthenticator authenticator) { clientAuthenticator = authenticator; @@ -106,14 +105,6 @@ public class ClientUtil { // ensure that default callback is setup if possible getClientAuthenticator(); - host = host.trim().toLowerCase(); - try { - host = InetNameLookup.getCanonicalHostName(host); - } - catch (UnknownHostException e) { - Msg.warn(ClientUtil.class, "Failed to resolve hostname for " + host); - } - if (port <= 0) { port = GhidraServerHandle.DEFAULT_PORT; } @@ -145,22 +136,14 @@ public class ClientUtil { * Eliminate the specified repository server from the connection cache * @param host host name or IP address * @param port port (0: use default port) - * @throws IOException */ - public static void clearRepositoryAdapter(String host, int port) throws IOException { - host = host.trim().toLowerCase(); - String hostAddr = host; - try { - hostAddr = InetNameLookup.getCanonicalHostName(host); - } - catch (UnknownHostException e) { - throw new IOException("Repository server lookup failed: " + host); - } + public static void clearRepositoryAdapter(String host, int port) { if (port == 0) { port = GhidraServerHandle.DEFAULT_PORT; } - ServerInfo server = new ServerInfo(hostAddr, port); + + ServerInfo server = new ServerInfo(host, port); RepositoryServerAdapter serverAdapter = serverHandles.remove(server); if (serverAdapter != null) { serverAdapter.disconnect(); @@ -170,6 +153,7 @@ public class ClientUtil { /** * Returns default user login name. Actual user name used by repository * should be obtained from RepositoryServerAdapter.getUser + * @return default user name */ public static String getUserName() { String name = SystemUtilities.getUserName(); @@ -372,7 +356,7 @@ public class ClientUtil { * @param parent dialog parent * @param handle server handle * @param serverInfo server information - * @throws IOException + * @throws IOException if error occurs while updating password */ public static void changePassword(Component parent, RepositoryServerHandle handle, String serverInfo) throws IOException { @@ -451,7 +435,7 @@ public class ClientUtil { sigCb.getRecognizedAuthorities(), sigCb.getToken()); sigCb.sign(signedToken.certChain, signedToken.signature); Msg.info(ClientUtil.class, "PKI Authenticating to " + serverName + " as user '" + - signedToken.certChain[0].getSubjectDN() + "'"); + signedToken.certChain[0].getSubjectX500Principal() + "'"); } catch (Exception e) { String msg = e.getMessage(); diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ServerConnectTask.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ServerConnectTask.java index de4ae466ae..aa4d817023 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ServerConnectTask.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/client/ServerConnectTask.java @@ -18,10 +18,12 @@ package ghidra.framework.client; import java.io.Closeable; import java.io.IOException; import java.net.Socket; +import java.net.SocketAddress; import java.net.UnknownHostException; import java.rmi.*; import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; +import java.security.cert.Certificate; import java.util.HashSet; import javax.net.ssl.SSLHandshakeException; @@ -46,6 +48,8 @@ import ghidra.util.task.*; */ class ServerConnectTask extends Task { + private static final int LIVENESS_CHECK_TIMEOUT_MS = 3000; + private ServerInfo server; //private String defaultUserID; private boolean allowLoginRetry; @@ -98,6 +102,7 @@ class ServerConnectTask extends Task { * if handle is null after running task. If both the exception * and handle are null, it implies the connection attempt was cancelled * by the user. + * @return exception which occured during a failed connection attempt, or null */ Exception getException() { return exc; @@ -123,16 +128,6 @@ class ServerConnectTask extends Task { return subj; } - private static String getPreferredHostname(String name) { - try { - return InetNameLookup.getCanonicalHostName(name); - } - catch (UnknownHostException e) { - Msg.warn(ServerConnectTask.class, "Failed to resolve hostname for " + name); - } - return name; - } - private static boolean isSSLHandshakeCancelled(SSLHandshakeException e) throws IOException { if (e.getMessage().indexOf("bad_certificate") > 0) { if (ApplicationKeyManagerFactory.getPreferredKeyStore() == null) { @@ -154,8 +149,8 @@ class ServerConnectTask extends Task { * @param server server information * @param monitor cancellable monitor * @return Ghidra Server Handle object - * @throws IOException - * @throws CancelledException + * @throws IOException if a connection error occurs + * @throws CancelledException if connection attempt was cancelled */ public static GhidraServerHandle getGhidraServerHandle(ServerInfo server, TaskMonitor monitor) throws IOException, CancelledException { @@ -163,6 +158,7 @@ class ServerConnectTask extends Task { GhidraServerHandle gsh = null; boolean canCancel = monitor.isCancelEnabled(); // original state try { + // Test SSL Handshake to ensure that user is able to decrypt keystore. // This is intended to work around an RMI issue where a continuous // retry condition can occur when a user cancels the password entry @@ -172,17 +168,10 @@ class ServerConnectTask extends Task { monitor.setCancelEnabled(false); monitor.setMessage("Connecting..."); - Registry reg; - try { - // attempt to connect with older Ghidra Server registry without using SSL/TLS - reg = LocateRegistry.getRegistry(server.getServerName(), server.getPortNumber()); - checkServerBindNames(reg); - } - catch (IOException e) { - reg = LocateRegistry.getRegistry(server.getServerName(), server.getPortNumber(), + Registry reg = + LocateRegistry.getRegistry(server.getServerName(), server.getPortNumber(), new SslRMIClientSocketFactory()); - checkServerBindNames(reg); - } + checkServerBindNames(reg); gsh = (GhidraServerHandle) reg.lookup(GhidraServerHandle.BIND_NAME); gsh.checkCompatibility(GhidraServerHandle.INTERFACE_VERSION); @@ -241,20 +230,17 @@ class ServerConnectTask extends Task { /** * Attempts server connection and completes any necessary authentication. - * @param defaultUserID + * @param defaultUserID default user ID (actual ID used established during authentication) * @param monitor task monitor for connection cancellation * @return server handle or null if authentication or connection attempt was cancelled by user - * @throws IOException - * @throws LoginException + * @throws IOException if server connection fails + * @throws LoginException login failure */ private RemoteRepositoryServerHandle getRepositoryServerHandle(String defaultUserID, TaskMonitor monitor) throws IOException, LoginException, CancelledException { GhidraServerHandle gsh = getGhidraServerHandle(server, monitor); - if (gsh == null) { - return null; - } Callback[] callbacks = null; try { @@ -275,7 +261,6 @@ class ServerConnectTask extends Task { } } - String serverName = getPreferredHostname(server.getServerName()); AnonymousCallback onlyAnonymousCb = null; while (true) { try { @@ -298,8 +283,8 @@ class ServerConnectTask extends Task { // SSH option only available in conjunction with password // based authentication which will be used if SSH attempt fails hasSSHSignatureCallback = false; // only try SSH once - ClientUtil.processSSHSignatureCallback(callbacks, serverName, - defaultUserID); + ClientUtil.processSSHSignatureCallback(callbacks, + server.getServerName(), defaultUserID); } else if (pkiSignatureCb != null) { // when using PKI - no other authentication callback will be used @@ -317,14 +302,15 @@ class ServerConnectTask extends Task { } loopOK = false; // only try once - ClientUtil.processSignatureCallback(serverName, pkiSignatureCb); + ClientUtil.processSignatureCallback(server.getServerName(), + pkiSignatureCb); } else { // assume all other callback scenarios are password based // anonymous option must be explicitly chosen over username/password // when processing password callback - if (!ClientUtil.processPasswordCallbacks(callbacks, serverName, - defaultUserID, loginError)) { + if (!ClientUtil.processPasswordCallbacks(callbacks, + server.getServerName(), defaultUserID, loginError)) { return null; // Cancelled by user } } @@ -336,7 +322,7 @@ class ServerConnectTask extends Task { gsh.getRepositoryServer(getLocalUserSubject(), callbacks); if (rsh.isReadOnly()) { Msg.showInfo(this, null, "Anonymous Server Login", - "You have been logged-in anonymously to " + serverName + + "You have been logged-in anonymously to " + server.getServerName() + "\nRead-only permission is granted to repositories which allow anonymous access"); } return rsh; @@ -374,7 +360,30 @@ class ServerConnectTask extends Task { } } - private static void testServerSSLConnection(ServerInfo server, TaskMonitor monitor) + /** + * Socket implementation with very short connect timeout + */ + private static class FastConnectionFailSocket extends Socket { + FastConnectionFailSocket(String host, int port) throws UnknownHostException, IOException { + super(host, port); + } + + public void connect(SocketAddress endpoint) throws IOException { + connect(endpoint, LIVENESS_CHECK_TIMEOUT_MS); + } + } + + /** + * Initiate an SSLSocket connection in order to ensure that any neccesary client/server + * certificate validation is performed. + * @param server server to which connection should be verified. For the Ghidra Server + * this should correspond to the RMI Registry port {@link GhidraServerHandle#DEFAULT_PORT}. + * @param monitor connection task monitor + * @return certificate chain of server + * @throws IOException if connection failure occurs + * @throws CancelledException if connection attempt is cancelled + */ + private static Certificate[] testServerSSLConnection(ServerInfo server, TaskMonitor monitor) throws IOException, CancelledException { RMIServerPortFactory portFactory = new RMIServerPortFactory(server.getPortNumber()); @@ -384,7 +393,18 @@ class ServerConnectTask extends Task { monitor.setCancelEnabled(true); monitor.setMessage("Checking Server Liveness..."); + + // Perform simple socket test connection with short timeout to verify connectivity. + try (Socket socket = new FastConnectionFailSocket(serverName, sslRmiPort); + ConnectCancelledListener cancelListener = + new ConnectCancelledListener(monitor, () -> forceClose(socket))) { + // do nothing - connect occurs during instantiation + } + finally { + monitor.checkCanceled(); // circumvent any IOException which may have occured + } + // Perform secure socket test connection to prime keystore use without RMI involvement try (SSLSocket socket = (SSLSocket) factory.createSocket(serverName, sslRmiPort); ConnectCancelledListener cancelListener = new ConnectCancelledListener(monitor, () -> forceClose(socket))) { @@ -392,6 +412,7 @@ class ServerConnectTask extends Task { // which will give user ability to cancel without involving RMI which // will avoid RMI reconnect attempts socket.startHandshake(); + return socket.getSession().getPeerCertificates(); } finally { monitor.checkCanceled(); // circumvent any IOException which may have occured diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/model/ServerInfo.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/model/ServerInfo.java index a912e21e90..047144bd6e 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/model/ServerInfo.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/model/ServerInfo.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,7 +37,8 @@ public class ServerInfo implements Serializable { } /** - * Get the server name. + * Get the server hostname or IP address as originally specified. + * @return hostname or IP address as originally specified */ public String getServerName() { return host; @@ -46,6 +46,7 @@ public class ServerInfo implements Serializable { /** * Get the port number. + * @return port number */ public int getPortNumber() { return portNumber; diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java index 8857ecf726..825dd19544 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerFactory.java @@ -21,7 +21,7 @@ import java.net.Socket; import java.security.*; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.Arrays; +import java.util.*; import javax.net.ssl.*; import javax.security.auth.x500.X500Principal; @@ -62,6 +62,7 @@ public class ApplicationKeyManagerFactory { private static KeyStorePasswordProvider customPasswordProvider; private static X500Principal defaultIdentity; + private static List subjectAlternativeNames; private static ApplicationKeyManagerFactory instance; @@ -182,16 +183,48 @@ public class ApplicationKeyManagerFactory { /** * Set the default self-signed principal identity to be used during initialization * if no keystore defined. Current application key manager will be invalidated. - * @param identity if not null and a KeyStore path has not be set, this - * identity will be used to generate a self-signed certificate and private key * (NOTE: this is intended for server use only when client will not be performing * CA validation). + * @param identity if not null and a KeyStore path has not be set, this + * identity will be used to generate a self-signed certificate and private key */ public synchronized static void setDefaultIdentity(X500Principal identity) { defaultIdentity = identity; getKeyManagerWrapper().invalidateKey(); } + /** + * Add the optional self-signed subject alternative name to be used during initialization + * if no keystore defined. Current application key manager will be invalidated. + * (NOTE: this is intended for server use only when client will not be performing + * CA validation). + * @param subjectAltName name to be added to the current list of alternative subject names. + * A null value will clear all names currently set. + * name will be used to generate a self-signed certificate and private key + */ + public synchronized static void addSubjectAlternativeName(String subjectAltName) { + if (subjectAltName == null) { + subjectAlternativeNames = null; + } + else { + if (subjectAlternativeNames == null) { + subjectAlternativeNames = new ArrayList<>(); + } + subjectAlternativeNames.add(subjectAltName); + } + getKeyManagerWrapper().invalidateKey(); + } + + /** + * Get the current list of subject alternative names to be used for a self-signed certificate + * if no keystore defined. + * @return list of subject alternative names to be used for a self-signed certificate + * if no keystore defined. + */ + public synchronized static List getSubjectAlternativeName() { + return Collections.unmodifiableList(subjectAlternativeNames); + } + /** * Initialize key manager if needed. Doing this explicitly independent of an SSL connection * allows application to bail before initiating connection. This will get handshake failure @@ -548,7 +581,7 @@ public class ApplicationKeyManagerFactory { KeyStore selfSignedKeyStore = ApplicationKeyManagerUtils.createKeyStore("defaultSigKey", defaultIdentity.getName(), SELF_SIGNED_DURATION_DAYS, null, null, "JKS", - pwd); + subjectAlternativeNames, pwd); keystoreData = new ProtectedKeyStoreData(selfSignedKeyStore, pwd); isSelfSigned = true; } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java index 55fd3a1e9f..082ba095a6 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/ApplicationKeyManagerUtils.java @@ -37,6 +37,7 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.operator.ContentSigner; import org.bouncycastle.operator.OperatorException; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.util.IPAddress; import generic.random.SecureRandomFactory; import ghidra.util.Msg; @@ -301,15 +302,19 @@ public class ApplicationKeyManagerUtils { * @param alias entry alias with keystore * @param dn distinguished name (e.g., "CN=Ghidra Test, O=Ghidra, OU=Test, C=US" ) * @param durationDays number of days which generated certificate should remain valid - * @param caEntry optional CA private key entry. If null, a self-signed CA certificate will be generated. + * @param caEntry optional CA private key entry. If null, a self-signed CA certificate will be + * generated. * @param keyFile optional file to load/store resulting {@link KeyStore} (may be null) * @param keystoreType support keystore type (e.g., "JKS", "PKCS12") + * @param subjectAlternativeNames an optional list of subject alternative names to be included + * in certificate (may be null) * @param protectedPassphrase key and keystore protection password * @return keystore containing newly generated certification with key pair * @throws KeyStoreException if error occurs while updating keystore */ public static final KeyStore createKeyStore(String alias, String dn, int durationDays, - PrivateKeyEntry caEntry, File keyFile, String keystoreType, char[] protectedPassphrase) + PrivateKeyEntry caEntry, File keyFile, String keystoreType, + Collection subjectAlternativeNames, char[] protectedPassphrase) throws KeyStoreException { PasswordProtection pp = new PasswordProtection(protectedPassphrase); @@ -352,9 +357,8 @@ public class ApplicationKeyManagerUtils { } X509Certificate caX509Cert = (X509Certificate) caCert; caX500Name = - new X500Name(caX509Cert.getSubjectDN().getName()); - keyUsage = new KeyUsage( - KeyUsage.digitalSignature | KeyUsage.keyEncipherment); + new X500Name(caX509Cert.getSubjectX500Principal().getName()); + keyUsage = new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment); issuerKey = caEntry.getPrivateKey(); } Date notBefore = new Date(); @@ -362,18 +366,23 @@ public class ApplicationKeyManagerUtils { Date notAfter = new Date(notBefore.getTime() + durationMs); BigInteger serialNumber = new BigInteger(128, random); -// JcaX509ExtensionUtils x509Utils = new JcaX509ExtensionUtils(); - X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder(caX500Name, serialNumber, notBefore, notAfter, x500Name, bcPk); - certificateBuilder -// .addExtension(Extension.subjectKeyIdentifier, true, x509Utils.createSubjectKeyIdentifier(bcPk)) - .addExtension(Extension.keyUsage, true, keyUsage); - + certificateBuilder.addExtension(Extension.keyUsage, true, keyUsage); + if (subjectAlternativeNames != null && !subjectAlternativeNames.isEmpty()) { + List nameList = new ArrayList(); + for (String altName : subjectAlternativeNames) { + int nameType = + IPAddress.isValid(altName) ? GeneralName.iPAddress : GeneralName.dNSName; + nameList.add(new GeneralName(nameType, altName)); + } + GeneralName[] altNames = nameList.toArray(GeneralName[]::new); + certificateBuilder.addExtension(Extension.subjectAlternativeName, false, + new GeneralNames(altNames)); + } if (caEntry == null) { - certificateBuilder - .addExtension(Extension.basicConstraints, true, new BasicConstraints(1)); -// .addExtension(Extension.authorityKeyIdentifier, true, x509Utils.createAuthorityKeyIdentifier(bcPk)); + certificateBuilder.addExtension(Extension.basicConstraints, true, + new BasicConstraints(1)); } ContentSigner contentSigner = @@ -438,18 +447,21 @@ public class ApplicationKeyManagerUtils { * @param caEntry optional CA private key entry. If null, a self-signed CA certificate will be generated. * @param keyFile optional file to load/store resulting {@link KeyStore} (may be null) * @param keystoreType support keystore type (e.g., "JKS", "PKCS12") + * @param subjectAlternativeNames an optional list of subject alternative names to be included + * in certificate (may be null) * @param protectedPassphrase key and keystore protection password * @return newly generated keystore entry with key pair * @throws KeyStoreException if error occurs while updating keystore */ public static final PrivateKeyEntry createKeyEntry(String alias, String dn, int durationDays, - PrivateKeyEntry caEntry, File keyFile, String keystoreType, char[] protectedPassphrase) + PrivateKeyEntry caEntry, File keyFile, String keystoreType, + Collection subjectAlternativeNames, char[] protectedPassphrase) throws KeyStoreException { PasswordProtection pp = new PasswordProtection(protectedPassphrase); try { KeyStore keyStore = createKeyStore(alias, dn, durationDays, caEntry, keyFile, - keystoreType, protectedPassphrase); + keystoreType, subjectAlternativeNames, protectedPassphrase); return (PrivateKeyEntry) keyStore.getEntry(alias, pp); } catch (NoSuchAlgorithmException | UnrecoverableEntryException e) { diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/net/ApplicationKeyManagerFactoryTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/net/ApplicationKeyManagerFactoryTest.java index 7670ac47f3..064cb8d7a7 100644 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/net/ApplicationKeyManagerFactoryTest.java +++ b/Ghidra/Framework/Generic/src/test/java/ghidra/net/ApplicationKeyManagerFactoryTest.java @@ -74,7 +74,7 @@ public class ApplicationKeyManagerFactoryTest extends AbstractGenericTest { keystoreFile.delete(); ApplicationKeyManagerUtils.createKeyStore(ALIAS, TEST_IDENTITY, 2, null, keystoreFile, - "PKCS12", TEST_PWD.toCharArray()); + "PKCS12", null, TEST_PWD.toCharArray()); ApplicationKeyManagerFactory.setKeyStorePasswordProvider(passwordProvider); } diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java index d006558cbc..0100841dc3 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java @@ -943,21 +943,21 @@ public class ServerTestUtil { Msg.info(ServerTestUtil.class, "Generating self-signed CA cert: " + caPath); PrivateKeyEntry caEntry = ApplicationKeyManagerUtils.createKeyEntry("test-CA", TEST_PKI_CA_DN, 2, null, null, - "PKCS12", ApplicationKeyManagerFactory.DEFAULT_PASSWORD.toCharArray()); + "PKCS12", null, ApplicationKeyManagerFactory.DEFAULT_PASSWORD.toCharArray()); ApplicationKeyManagerUtils.exportX509Certificates(caEntry.getCertificateChain(), caFile); // Generate User/Client certificate and keystore Msg.info(ServerTestUtil.class, "Generating test user key/cert (signed by test-CA, pwd: " + TEST_PKI_USER_PASSPHRASE + "): " + userKeystorePath); ApplicationKeyManagerUtils.createKeyEntry("test-sig", TEST_PKI_USER_DN, 2, caEntry, - userKeystoreFile, "PKCS12", TEST_PKI_USER_PASSPHRASE.toCharArray()); + userKeystoreFile, "PKCS12", null, TEST_PKI_USER_PASSPHRASE.toCharArray()); // Generate Server certificate and keystore Msg.info(ServerTestUtil.class, "Generating test server key/cert (signed by test-CA, pwd: " + TEST_PKI_SERVER_PASSPHRASE + "): " + serverKeystorePath); ApplicationKeyManagerUtils.createKeyEntry("test-sig", TEST_PKI_SERVER_DN, 2, caEntry, - serverKeystoreFile, "PKCS12", TEST_PKI_SERVER_PASSPHRASE.toCharArray()); + serverKeystoreFile, "PKCS12", null, TEST_PKI_SERVER_PASSPHRASE.toCharArray()); } /**