diff --git a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java index 1e8da88e4c..550e72f99f 100755 --- a/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java +++ b/Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/BSimClientFactory.java @@ -51,7 +51,7 @@ public class BSimClientFactory { String protocol = url.getProtocol(); if (!protocol.equals("postgresql") && !protocol.equals("https") && !protocol.equals("elastic") && !protocol.equals("file")) { - throw new MalformedURLException("Protocol not permissable for BSim URL"); + throw new MalformedURLException("Protocol not permitted for BSim URL"); } String path = url.getPath(); if (path == null || path.length() == 0 || path.equals("/")) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java index 72fdec3d22..3af390e98a 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/osgi/BundleHost.java @@ -417,6 +417,10 @@ public class BundleHost { // setup the cache path config.setProperty(Constants.FRAMEWORK_STORAGE, makeCacheDir()); + // prevent the use of Felix URL handlers which can interfere with URL.openConnection + // exception handling + config.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false"); + config.put(FelixConstants.LOG_LEVEL_PROP, "1"); if (STDERR_DEBUGGING) { config.put(FelixConstants.LOG_LEVEL_PROP, "999"); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramLocator.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramLocator.java index dc45224df1..e9b5a3b962 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramLocator.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/progmgr/ProgramLocator.java @@ -36,7 +36,14 @@ import ghidra.util.Msg; */ public class ProgramLocator { private final DomainFile domainFile; + + // Connections and any saved state should be based upon a non-normalized URL + // as it was originally specified. This is necessary to ensure that server + // certificate validation is based upon the original server hostname as + // specified by the user. private final URL ghidraURL; + private final URL normalizedGhidraURL; + private final int version; private final boolean invalidContent; @@ -49,7 +56,8 @@ public class ProgramLocator { if (!GhidraURL.isGhidraURL(url)) { throw new IllegalArgumentException("unsupported protocol: " + url.getProtocol()); } - this.ghidraURL = GhidraURL.getNormalizedURL(url); + this.ghidraURL = url; + this.normalizedGhidraURL = GhidraURL.getNormalizedURL(url); this.domainFile = null; this.version = DomainFile.DEFAULT_VERSION; this.invalidContent = false; // unable to validate @@ -98,6 +106,7 @@ public class ProgramLocator { } this.domainFile = file; this.ghidraURL = url; + this.normalizedGhidraURL = url != null ? GhidraURL.getNormalizedURL(url) : null; } /** @@ -109,13 +118,22 @@ public class ProgramLocator { } /** - * Returns the URL for this locator or null if this is a DomainFile based locator - * @return the URL for this locator or null if this is a DomainFile based locator + * Returns the Ghidra URL for this locator or null if this is a DomainFile based locator. + * This URL represents the original URL form when locator was first instantiated. + * @return the Ghidra URL for this locator or null if this is a DomainFile based locator. */ public URL getURL() { return ghidraURL; } + /** + * Returns the normalized Ghidra URL for this locator or null if this is a DomainFile based locator. + * @return the Ghidra URL for this locator or null if this is a DomainFile based locator. + */ + public URL getNormalizedURL() { + return normalizedGhidraURL; + } + /** * Returns the version of the program that this locator represents * @return the version of the program that this locator represents @@ -166,7 +184,7 @@ public class ProgramLocator { @Override public int hashCode() { - return Objects.hash(domainFile, ghidraURL, version); + return Objects.hash(domainFile, normalizedGhidraURL, version); } @Override @@ -182,7 +200,8 @@ public class ProgramLocator { } ProgramLocator other = (ProgramLocator) obj; return Objects.equals(domainFile, other.domainFile) && - Objects.equals(ghidraURL, other.ghidraURL) && version == other.version; + Objects.equals(normalizedGhidraURL, other.normalizedGhidraURL) && + version == other.version; } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/DefaultLocalGhidraProtocolConnector.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/DefaultLocalGhidraProtocolConnector.java index 0657a5ef57..26c7c1461b 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/DefaultLocalGhidraProtocolConnector.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/DefaultLocalGhidraProtocolConnector.java @@ -61,7 +61,7 @@ public class DefaultLocalGhidraProtocolConnector extends GhidraProtocolConnector protected void checkHostInfo() throws MalformedURLException { String host = url.getHost(); if (host.length() != 0) { - throw new MalformedURLException("unsupported host specification"); + throw new MalformedURLException("Invalid local Ghidra URL"); } } diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraProtocolConnector.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraProtocolConnector.java index cfacf0029b..6db7dc5b6c 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraProtocolConnector.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraProtocolConnector.java @@ -80,7 +80,7 @@ public abstract class GhidraProtocolConnector { */ protected void checkProtocol() throws MalformedURLException { if (!GhidraURL.PROTOCOL.equals(url.getProtocol())) { - throw new MalformedURLException("expected ghidra URL protocol"); + throw new MalformedURLException("Expected ghidra URL protocol"); } } @@ -102,7 +102,7 @@ public abstract class GhidraProtocolConnector { protected void checkHostInfo() throws MalformedURLException { String host = url.getHost(); if (host.length() == 0) { - throw new MalformedURLException("missing server host specification"); + throw new MalformedURLException("URL is missing server specification"); } } @@ -129,7 +129,7 @@ public abstract class GhidraProtocolConnector { } if (path.length() == 0) { - throw new MalformedURLException("invalid path specification"); + throw new MalformedURLException("URL is missing repository name"); } return path; @@ -149,7 +149,7 @@ public abstract class GhidraProtocolConnector { } if (!contentPath.startsWith(FileSystem.SEPARATOR)) { - throw new MalformedURLException("invalid content path specification"); + throw new MalformedURLException("URL has invalid content path specification"); } boolean isFolder = contentPath.endsWith(FileSystem.SEPARATOR); @@ -165,7 +165,7 @@ public abstract class GhidraProtocolConnector { for (int i = 1; i < pieces.length; i++) { String p = pieces[i]; if (p.length() == 0) { - throw new MalformedURLException("invalid content path specification"); + throw new MalformedURLException("URL has invalid content path specification"); } if (!isFolder && i == (pieces.length - 1)) { folderItemName = p; diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraURL.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraURL.java index 57996f9afe..6ae1e7d591 100644 --- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraURL.java +++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/protocol/ghidra/GhidraURL.java @@ -681,7 +681,14 @@ public class GhidraURL { /** * Get a normalized URL which eliminates use of host names and optional URL ref - * which may prevent direct comparison. + * which may prevent direct comparison. + *

+ * NOTE: This method is primarily intended to be used when caching based upon + * a Ghidra URL. This method should not be used to transform a URL for + * connection use since the original hostname FQDN is used during server + * certificate validation. Although, it is a good practice for a server + * certificate to include both FQDN and IP Address as subject alternative + * names. * * @param url Ghidra URL * @return normalized url