mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
GP-42 Initial implementation of Pdb symbol store / symbol servers
This commit is contained in:
parent
df72f24b58
commit
425667e640
93 changed files with 7715 additions and 3874 deletions
|
@ -0,0 +1,88 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.net;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpClient.Redirect;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
public class HttpClients {
|
||||
/**
|
||||
* Note: java.net.http.HttpClient instances can allocate system resources (file handles),
|
||||
* and frequently creating a new HttpClient could exhaust system resources.
|
||||
* <p>
|
||||
* There is no "close()" on a HttpClient to release resources. The system resources
|
||||
* allocated by HttpClient instances will be released when the instance is gc'd.
|
||||
* However, since the resources in question (filehandles) are not tied to memory pressure,
|
||||
* its possible a gc() won't happen before running out of file handles if a few hundred
|
||||
* HttpClient instances have been created / discarded.
|
||||
* <p>
|
||||
* Also note, there is no per-connection ability to disable hostname verification in a
|
||||
* SSL/TLS connection. There is a global flag:
|
||||
* -Djdk.internal.httpclient.disableHostnameVerification
|
||||
*
|
||||
*/
|
||||
private static HttpClient client;
|
||||
|
||||
/**
|
||||
* Creates a HttpClient Builder using Ghidra SSL/TLS context info.
|
||||
*
|
||||
* @return a new HttpClient Builder
|
||||
* @throws IOException if error in PKI settings or crypto configuration
|
||||
*/
|
||||
public static HttpClient.Builder newHttpClientBuilder() throws IOException {
|
||||
if (!ApplicationKeyManagerFactory.initialize()) {
|
||||
if (ApplicationKeyManagerFactory.getKeyStore() != null) {
|
||||
throw new IOException("Failed to initialize PKI certificate keystore");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return HttpClient.newBuilder()
|
||||
.sslContext(SSLContext.getDefault())
|
||||
.followRedirects(Redirect.NORMAL);
|
||||
}
|
||||
catch (NoSuchAlgorithmException nsae) {
|
||||
throw new IOException("Missing algorithm", nsae);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shared, plain (no special options) {@link HttpClient}.
|
||||
*
|
||||
* @return a {@link HttpClient}
|
||||
* @throws IOException if error in PKI settings or crypto configuration
|
||||
*/
|
||||
public static synchronized HttpClient getHttpClient() throws IOException {
|
||||
if (client == null) {
|
||||
client = newHttpClientBuilder().build();
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the currently cached {@link HttpClient}, forcing it to be
|
||||
* rebuilt during the next call to {@link #getHttpClient()}.
|
||||
*/
|
||||
public static synchronized void clearHttpClient() {
|
||||
client = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -110,6 +110,10 @@ public class SSLContextInitializer implements ModuleInitializer {
|
|||
// Establish default HTTPS socket factory
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
|
||||
|
||||
// Force the HttpClient to be re-created by the next request to
|
||||
// HttpClients.getHttpClient() so that the new SSLContext is used
|
||||
HttpClients.clearHttpClient();
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
|
@ -15,39 +15,15 @@
|
|||
*/
|
||||
package ghidra.net.http;
|
||||
|
||||
import ghidra.net.ApplicationKeyManagerFactory;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.Properties;
|
||||
|
||||
import ghidra.net.ApplicationKeyManagerFactory;
|
||||
import ghidra.util.Msg;
|
||||
|
||||
public class HttpUtil {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("User-Agent", "Microsoft-Symbol-Server/6.3.9600.17298");
|
||||
|
||||
String urlStr =
|
||||
"http://msdl.microsoft.com/download/symbols/write.pdb/4FD8CA6696F445A7B969AB9BBD76E4591/write.pd_";
|
||||
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File f = new File(homeDir + "/Downloads", "write.pdb.deleteme");
|
||||
|
||||
try {
|
||||
getFile(urlStr, properties, true, f);
|
||||
System.out.println("getFile completed: " + f);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute an HTTP/HTTPS GET request and return the resulting HttpURLConnection.
|
||||
|
@ -155,4 +131,5 @@ public class HttpUtil {
|
|||
|
||||
return connection.getContentType();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,25 +15,23 @@
|
|||
*/
|
||||
package ghidra.util.filechooser;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* A convenience implementation of FileFilter that filters out
|
||||
* all files except for those type extensions that it knows about.
|
||||
*
|
||||
* Extensions are of the type ".foo", which is typically found on
|
||||
* Windows and Unix boxes, but not on Mac. Case is ignored.
|
||||
*
|
||||
* <p>
|
||||
* Extensions are of the type "foo" (no leading dot). Case is ignored.
|
||||
* <p>
|
||||
* Example - create a new filter that filters out all files
|
||||
* but gif and jpg image files:
|
||||
* <pre>
|
||||
* GhidraFileChooser chooser = new GhidraFileChooser();
|
||||
* ExtensionFileFilter filter = new ExtensionFileFilter(
|
||||
* new String{"gif", "jpg"}, "JPEG and GIF Images")
|
||||
* chooser.addFileFilter(filter);
|
||||
* chooser.addFileFilter(ExtensionFilFilter.forExtensions("JPEG and GIF Images", "gif", "jpg"));
|
||||
*</pre>
|
||||
*/
|
||||
public class ExtensionFileFilter implements GhidraFileFilter {
|
||||
|
@ -50,19 +48,16 @@ public class ExtensionFileFilter implements GhidraFileFilter {
|
|||
return eff;
|
||||
}
|
||||
|
||||
private Hashtable<String, ExtensionFileFilter> filters = null;
|
||||
private String description = null;
|
||||
private String fullDescription = null;
|
||||
private boolean useExtensionsInDescription = true;
|
||||
private List<String> extensions;
|
||||
private String description;
|
||||
private String fullDescription;
|
||||
|
||||
/**
|
||||
* Creates a file filter that accepts the given file type.
|
||||
* Example: new ExtensionFileFilter("jpg", "JPEG Image Images");
|
||||
* Example: new ExtensionFileFilter("jpg", "JPEG Images");
|
||||
*
|
||||
* Note that the "." before the extension is not needed. If
|
||||
* provided, it will be ignored.
|
||||
*
|
||||
* @see #addExtension
|
||||
* @param extension file extension to match, without leading dot
|
||||
* @param description descriptive string of the filter
|
||||
*/
|
||||
public ExtensionFileFilter(String extension, String description) {
|
||||
this(new String[] { extension }, description);
|
||||
|
@ -72,16 +67,15 @@ public class ExtensionFileFilter implements GhidraFileFilter {
|
|||
* Creates a file filter from the given string array and description.
|
||||
* Example: new ExtensionFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
|
||||
*
|
||||
* Note that the "." before the extension is not needed and will be ignored.
|
||||
*
|
||||
* @see #addExtension
|
||||
* @param filters array of file name extensions, each without a leading dot
|
||||
* @param description descriptive string of the filter
|
||||
*/
|
||||
public ExtensionFileFilter(String[] filters, String description) {
|
||||
this.filters = new Hashtable<String, ExtensionFileFilter>(filters.length);
|
||||
for (String filter : filters) {
|
||||
addExtension(filter);//add filters one by one
|
||||
}
|
||||
setDescription(description);
|
||||
this.extensions = Arrays.asList(filters)
|
||||
.stream()
|
||||
.map(String::toLowerCase)
|
||||
.collect(Collectors.toList());
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +84,6 @@ public class ExtensionFileFilter implements GhidraFileFilter {
|
|||
*
|
||||
* Files that begin with "." are ignored.
|
||||
*
|
||||
* @see #getExtension
|
||||
* @see FileFilter#accept
|
||||
*/
|
||||
@Override
|
||||
|
@ -101,133 +94,37 @@ public class ExtensionFileFilter implements GhidraFileFilter {
|
|||
if (model.isDirectory(f)) {
|
||||
return true;
|
||||
}
|
||||
if (filters.size() == 0) {
|
||||
if (extensions.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
String extension = getExtension(f);
|
||||
return extension != null && filters.get(extension) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extension portion of the file's name .
|
||||
*
|
||||
* @see #getExtension
|
||||
* @see FileFilter#accept
|
||||
*/
|
||||
public String getExtension(File f) {
|
||||
if (f != null) {
|
||||
String filename = f.getName();
|
||||
int i = filename.lastIndexOf('.');
|
||||
if (i > 0 && i < filename.length() - 1) {
|
||||
return filename.substring(i + 1).toLowerCase();
|
||||
String filename = f.getName().toLowerCase();
|
||||
if (filename.startsWith(".")) {
|
||||
return false;
|
||||
}
|
||||
int fnLen = filename.length();
|
||||
for (String ext : extensions) {
|
||||
int extLen = ext.length();
|
||||
int extStart = fnLen - extLen;
|
||||
if (extStart > 0 && filename.substring(extStart).equals(ext) &&
|
||||
filename.charAt(extStart - 1) == '.') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filetype "dot" extension to filter against.
|
||||
*
|
||||
* For example: the following code will create a filter that filters
|
||||
* out all files except those that end in ".jpg" and ".tif":
|
||||
*
|
||||
* ExtensionFileFilter filter = new ExtensionFileFilter();
|
||||
* filter.addExtension("jpg");
|
||||
* filter.addExtension("tif");
|
||||
*
|
||||
* Note that the "." before the extension is not needed and will be ignored.
|
||||
*/
|
||||
public void addExtension(String extension) {
|
||||
if (filters == null) {
|
||||
filters = new Hashtable<String, ExtensionFileFilter>(5);
|
||||
}
|
||||
filters.put(extension.toLowerCase(), this);
|
||||
fullDescription = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human readable description of this filter. For
|
||||
* example: "JPEG and GIF Image Files (*.jpg, *.gif)"
|
||||
*/
|
||||
@Override
|
||||
public String getDescription() {
|
||||
if (fullDescription == null) {
|
||||
fullDescription = "";
|
||||
if (description == null || isExtensionListInDescription()) {
|
||||
if (description != null) {
|
||||
fullDescription = description;
|
||||
}
|
||||
fullDescription += " (";
|
||||
// build the description from the extension list
|
||||
fullDescription = Objects.requireNonNullElse(description, "");
|
||||
|
||||
if (filters.size() == 0) {
|
||||
fullDescription += "*.*";
|
||||
}
|
||||
else {
|
||||
boolean firstExt = true;
|
||||
Enumeration<String> extensions = filters.keys();
|
||||
if (extensions != null) {
|
||||
while (extensions.hasMoreElements()) {
|
||||
if (!firstExt) {
|
||||
fullDescription += ",";
|
||||
}
|
||||
else {
|
||||
firstExt = false;
|
||||
}
|
||||
fullDescription += "*." + extensions.nextElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
fullDescription += ")";
|
||||
}
|
||||
else {
|
||||
fullDescription = description;
|
||||
}
|
||||
// add prettified extensions to the description string
|
||||
fullDescription += " (";
|
||||
fullDescription += extensions.isEmpty()
|
||||
? "*.*"
|
||||
: extensions.stream().map(s -> "*." + s).collect(Collectors.joining(","));
|
||||
fullDescription += ")";
|
||||
}
|
||||
return fullDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the human readable description of this filter. For
|
||||
* example: filter.setDescription("Gif and JPG Images");
|
||||
*
|
||||
* @see #setDescription
|
||||
* @see #setExtensionListInDescription
|
||||
* @see #isExtensionListInDescription
|
||||
*/
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
fullDescription = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the extension list (.jpg, .gif, etc) should
|
||||
* show up in the human readable description.
|
||||
*
|
||||
* Only relevant if a description was provided in the constructor
|
||||
* or using setDescription();
|
||||
*
|
||||
* @see #getDescription
|
||||
* @see #setDescription
|
||||
* @see #isExtensionListInDescription
|
||||
*/
|
||||
public void setExtensionListInDescription(boolean b) {
|
||||
useExtensionsInDescription = b;
|
||||
fullDescription = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the extension list (.jpg, .gif, etc) should
|
||||
* show up in the human readable description.
|
||||
*
|
||||
* Only relevant if a description was provided in the constructor
|
||||
* or using setDescription();
|
||||
*
|
||||
* @see #getDescription
|
||||
* @see #setDescription
|
||||
* @see #setExtensionListInDescription
|
||||
*/
|
||||
public final boolean isExtensionListInDescription() {
|
||||
return useExtensionsInDescription;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -16,12 +15,16 @@
|
|||
*/
|
||||
package ghidra.util.task;
|
||||
|
||||
/**
|
||||
* Similar to a {@link Runnable} except the {@link #monitoredRun(TaskMonitor) run}
|
||||
* method is given a monitor to report progress and check for cancellation.
|
||||
*/
|
||||
public interface MonitoredRunnable {
|
||||
|
||||
/**
|
||||
* Similar to a runnable except that is given a monitor to report progress and check for
|
||||
* cancellation.
|
||||
* @param monitor the TaskMonitor to use.
|
||||
*/
|
||||
public void monitoredRun(TaskMonitor monitor);
|
||||
* Similar to a runnable except the run method is given a monitor
|
||||
* to report progress and check for cancellation.
|
||||
* @param monitor the TaskMonitor to use.
|
||||
*/
|
||||
void monitoredRun(TaskMonitor monitor);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.net.http;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
public class HttpUtilTest {
|
||||
public static void main(String[] args) {
|
||||
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("User-Agent", "Microsoft-Symbol-Server/6.3.9600.17298");
|
||||
|
||||
String urlStr =
|
||||
"http://msdl.microsoft.com/download/symbols/write.pdb/4FD8CA6696F445A7B969AB9BBD76E4591/write.pd_";
|
||||
|
||||
String homeDir = System.getProperty("user.home");
|
||||
File f = new File(homeDir + "/Downloads", "write.pdb.deleteme");
|
||||
|
||||
try {
|
||||
HttpUtil.getFile(urlStr, properties, true, f);
|
||||
System.out.println("getFile completed: " + f);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue