mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-10-06 04:59:23 +08:00
Merge remote-tracking branch 'origin/GP-7328_ghidra1_DataBuffer' into Ghidra_12.2
This commit is contained in:
@@ -15,32 +15,18 @@
|
||||
*/
|
||||
package ghidra.server.remote;
|
||||
|
||||
import static ghidra.server.remote.GhidraServer.AuthMode.JAAS_LOGIN;
|
||||
import static ghidra.server.remote.GhidraServer.AuthMode.NO_AUTH_LOGIN;
|
||||
import static ghidra.server.remote.GhidraServer.AuthMode.PASSWORD_FILE_LOGIN;
|
||||
import static ghidra.server.remote.GhidraServer.AuthMode.PKI_LOGIN;
|
||||
import static ghidra.server.remote.GhidraServer.AuthMode.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.rmi.NoSuchObjectException;
|
||||
import java.rmi.RemoteException;
|
||||
import java.rmi.registry.LocateRegistry;
|
||||
import java.rmi.registry.Registry;
|
||||
import java.rmi.server.RMIClientSocketFactory;
|
||||
import java.rmi.server.RMIServerSocketFactory;
|
||||
import java.rmi.server.UnicastRemoteObject;
|
||||
import java.rmi.server.*;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
import javax.rmi.ssl.SslRMIClientSocketFactory;
|
||||
@@ -57,29 +43,17 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.bouncycastle.asn1.x509.GeneralName;
|
||||
|
||||
import db.buffers.DataBuffer;
|
||||
import generic.jar.ResourceFile;
|
||||
import generic.random.SecureRandomFactory;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.ApplicationConfiguration;
|
||||
import ghidra.framework.remote.GhidraObjectInputFilter;
|
||||
import ghidra.framework.remote.GhidraPrincipal;
|
||||
import ghidra.framework.remote.GhidraServerHandle;
|
||||
import ghidra.framework.remote.RemoteRepositoryServerHandle;
|
||||
import ghidra.net.DefaultKeyManagerFactory;
|
||||
import ghidra.net.DefaultSSLContextInitializer;
|
||||
import ghidra.net.DefaultTrustManagerFactory;
|
||||
import ghidra.net.PKIUtils;
|
||||
import ghidra.framework.remote.*;
|
||||
import ghidra.net.*;
|
||||
import ghidra.server.RepositoryManager;
|
||||
import ghidra.server.UserManager;
|
||||
import ghidra.server.security.AnonymousAuthenticationModule;
|
||||
import ghidra.server.security.AuthenticationModule;
|
||||
import ghidra.server.security.JAASAuthenticationModule;
|
||||
import ghidra.server.security.Krb5ActiveDirectoryAuthenticationModule;
|
||||
import ghidra.server.security.PKIAuthenticationModule;
|
||||
import ghidra.server.security.PasswordFileAuthenticationModule;
|
||||
import ghidra.server.security.SSHAuthenticationModule;
|
||||
import ghidra.server.security.*;
|
||||
import ghidra.server.stream.BlockStreamServer;
|
||||
import ghidra.server.stream.RemoteBlockStreamHandle;
|
||||
import ghidra.util.SystemUtilities;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
@@ -867,8 +841,7 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan
|
||||
log.info(" RMI SSL port: " + ServerPortFactory.getRMISSLPort());
|
||||
log.info(" Block Stream port: " + ServerPortFactory.getStreamPort());
|
||||
log.info(" Block Stream compression: " +
|
||||
(RemoteBlockStreamHandle.enableCompressedSerializationOutput ? "enabled"
|
||||
: "disabled"));
|
||||
(DataBuffer.isCompressedSerializationOutputEnabled() ? "enabled" : "disabled"));
|
||||
log.info(" Root: " + serverRoot.getAbsolutePath());
|
||||
log.info(" Auth: " + authMode.getDescription());
|
||||
if (authMode == PASSWORD_FILE_LOGIN && defaultPasswordExpiration >= 0) {
|
||||
|
||||
+1
-4
@@ -51,9 +51,6 @@ public abstract class RemoteBlockStreamHandle<T extends BlockStream> implements
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
|
||||
public static boolean enableCompressedSerializationOutput = Boolean.parseBoolean(
|
||||
System.getProperty(DataBuffer.COMPRESSED_SERIAL_OUTPUT_PROPERTY, "false"));
|
||||
|
||||
public static final String HEADER_PREFIX = "@stream:";
|
||||
public static final String HEADER_SUFFIX = "@";
|
||||
public static final int HEADER_LENGTH =
|
||||
@@ -70,7 +67,7 @@ public abstract class RemoteBlockStreamHandle<T extends BlockStream> implements
|
||||
private final int blockCount;
|
||||
private final int blockSize;
|
||||
|
||||
protected final boolean compressed = enableCompressedSerializationOutput;
|
||||
protected final boolean compressed = DataBuffer.isCompressedSerializationOutputEnabled();
|
||||
|
||||
private boolean connectionPending = true;
|
||||
|
||||
|
||||
@@ -40,12 +40,18 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
enableCompressedSerializationOutput = enable;
|
||||
}
|
||||
|
||||
public static boolean usingCompressedSerializationOutput() {
|
||||
public static boolean isCompressedSerializationOutputEnabled() {
|
||||
return enableCompressedSerializationOutput;
|
||||
}
|
||||
|
||||
private static int FORMAT_VERSION = 0xEA; // 0xEA is first version (avoided simple value like 0 or 1)
|
||||
|
||||
// Maximum support buffer size supported
|
||||
public static final int MAX_BUFFER_SIZE = 65536;
|
||||
|
||||
// Establish safe limit for compressed buffer size
|
||||
private static final int MAX_COMPRESSED_BUFFER_SIZE = MAX_BUFFER_SIZE + 1024;
|
||||
|
||||
/**
|
||||
* NOTE: See custom serialization methods at bottom which implement compression.
|
||||
*/
|
||||
@@ -145,7 +151,7 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return data.length;
|
||||
return data != null ? data.length : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -333,8 +339,7 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
// Deflater must be consistent with inflateData nowrap option and should
|
||||
// not be changed since client/server must match.
|
||||
// NOTE: compression mode may be adjusted to optimize performance
|
||||
Deflater deflate = new Deflater(Deflater.BEST_SPEED, true);
|
||||
try {
|
||||
try (Deflater deflate = new Deflater(Deflater.BEST_SPEED, true)) {
|
||||
deflate.setInput(data, 0, data.length);
|
||||
deflate.finish();
|
||||
|
||||
@@ -350,8 +355,6 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
}
|
||||
|
||||
return compressedDataOffset;
|
||||
} finally {
|
||||
deflate.end(); // get rid of any native memory rather than waiting for GC
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,13 +372,18 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
dirty = in.readBoolean();
|
||||
empty = in.readBoolean();
|
||||
int len = in.readInt();
|
||||
|
||||
data = null;
|
||||
|
||||
if (len >= 0) {
|
||||
if (len > MAX_BUFFER_SIZE) {
|
||||
throw new IOException("Unsupported buffer size: " + len);
|
||||
}
|
||||
data = new byte[len];
|
||||
if (compressed) {
|
||||
int compressedLen = in.readInt();
|
||||
if (compressedLen > MAX_COMPRESSED_BUFFER_SIZE) {
|
||||
throw new IOException("Unsupported compressed buffer size: " + compressedLen);
|
||||
}
|
||||
byte[] compressedData = new byte[compressedLen];
|
||||
in.readFully(compressedData);
|
||||
inflateData(compressedData, data);
|
||||
@@ -414,14 +422,13 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
* Inflate compressedData into a properly sized data array.
|
||||
* @param compressedData array containing compressed data
|
||||
* @param data target data array size to receive fully inflated data.
|
||||
* @throws IOException
|
||||
* @throws IOException if an IO error occurs
|
||||
*/
|
||||
private static void inflateData(byte[] compressedData, byte[] data) throws IOException {
|
||||
|
||||
// Inflater must be consistent with deflateData nowrap option and should
|
||||
// not be changed since client/server must match.
|
||||
Inflater inflater = new Inflater(true);
|
||||
try {
|
||||
try (Inflater inflater = new Inflater(true)) {
|
||||
inflater.setInput(compressedData);
|
||||
int off = 0;
|
||||
while (!inflater.finished() && off < data.length) {
|
||||
@@ -437,9 +444,6 @@ public class DataBuffer implements Buffer, Externalizable {
|
||||
catch (DataFormatException e) {
|
||||
throw new IOException("DataBuffer inflation failed", e);
|
||||
}
|
||||
finally {
|
||||
inflater.end(); // get rid of any native memory rather than waiting for GC
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ public class LocalBufferFile implements BufferFile {
|
||||
|
||||
private static final String STRING_ENCODING = "UTF-8";
|
||||
|
||||
// ?? Should be changed !!
|
||||
private static final int MINIMUM_BLOCK_SIZE = 128;
|
||||
private static final int MINIMUM_BLOCK_SIZE = 512;
|
||||
private static final int MAXIMUM_BLOCK_SIZE = DataBuffer.MAX_BUFFER_SIZE;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
@@ -196,6 +196,9 @@ public class LocalBufferFile implements BufferFile {
|
||||
LocalBufferFile(int bufferSize, String tmpPrefix, String tmpExtension) throws IOException {
|
||||
this.bufferSize = bufferSize;
|
||||
this.blockSize = bufferSize + BUFFER_PREFIX_SIZE;
|
||||
if (blockSize < MINIMUM_BLOCK_SIZE || blockSize > MAXIMUM_BLOCK_SIZE) {
|
||||
throw new IllegalArgumentException("Unsupported buffer size: " + bufferSize);
|
||||
}
|
||||
this.readOnly = false;
|
||||
this.temporary = true;
|
||||
file = Application.createTempFile(tmpPrefix, tmpExtension);
|
||||
@@ -219,6 +222,12 @@ public class LocalBufferFile implements BufferFile {
|
||||
this.file = file;
|
||||
this.bufferSize = bufferSize;
|
||||
this.blockSize = bufferSize + BUFFER_PREFIX_SIZE;
|
||||
|
||||
if (blockSize < MINIMUM_BLOCK_SIZE || blockSize > MAXIMUM_BLOCK_SIZE) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported buffer size: " + bufferSize);
|
||||
}
|
||||
|
||||
this.readOnly = false;
|
||||
raf = new RandomAccessFile(file, "rw");
|
||||
|
||||
@@ -452,8 +461,12 @@ public class LocalBufferFile implements BufferFile {
|
||||
throw new IOException("Unrecognized file format");
|
||||
}
|
||||
|
||||
// Read buffer size, free buffer count, and first free buffer index
|
||||
// Read block size, free buffer count, and first free buffer index
|
||||
blockSize = raf.readInt();
|
||||
if (blockSize < MINIMUM_BLOCK_SIZE || blockSize > MAXIMUM_BLOCK_SIZE) {
|
||||
throw new IOException("Unsupported block size: " + blockSize);
|
||||
}
|
||||
|
||||
bufferSize = blockSize - BUFFER_PREFIX_SIZE;
|
||||
int firstFreeBufferIndex = raf.readInt();
|
||||
long len = raf.length();
|
||||
@@ -686,7 +699,8 @@ public class LocalBufferFile implements BufferFile {
|
||||
|
||||
byte[] data = buf.data;
|
||||
boolean empty = buf.isEmpty();
|
||||
if (!empty && data.length != bufferSize) {
|
||||
|
||||
if (data != null && data.length != bufferSize) {
|
||||
throw new IllegalArgumentException("Bad buffer size");
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,10 @@ public class DataBufferTest extends AbstractGenericTest {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// restore default compression: enabled
|
||||
DataBuffer.enableCompressedSerializationOutput(true);
|
||||
DataBuffer.enableCompressedSerializationOutput(
|
||||
Boolean.parseBoolean(
|
||||
System.getProperty(DataBuffer.COMPRESSED_SERIAL_OUTPUT_PROPERTY,
|
||||
"true")));
|
||||
}
|
||||
|
||||
private void transferData(boolean useRandomFill) throws Exception {
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.jdom2.JDOMException;
|
||||
import org.jdom2.input.SAXBuilder;
|
||||
import org.jdom2.output.XMLOutputter;
|
||||
|
||||
import db.buffers.DataBuffer;
|
||||
import docking.*;
|
||||
import docking.action.DockingAction;
|
||||
import docking.action.MenuData;
|
||||
@@ -93,14 +92,10 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
|
||||
public static final String AUTOMATICALLY_SAVE_TOOLS = "Automatically Save Tools";
|
||||
public static final String DEFAULT_TOOL_LAUNCH_MODE = "Default Tool Launch Mode";
|
||||
private static final String SHOW_TOOLTIPS_OPTION_NAME = "Show Tooltips";
|
||||
private static final String USE_COMPRESSED_DATABUFFER_OUTPUT =
|
||||
"Use DataBuffer Output Compression";
|
||||
private static final String USE_NATURAL_SORT = "Use Natural File Sort";
|
||||
private static final String USE_COMBINED_ALT_GRAPH_OPTION_NAME = "Use Combined Alt Keys";
|
||||
private static final String USE_ALERT_ANIMATION_OPTION_NAME = "Use Notification Animation";
|
||||
|
||||
private static final Boolean ENABLE_COMPRESSED_DATABUFFER_OUTPUT_DEFAULT = true;
|
||||
|
||||
private static final String RESTORE_PREVIOUS_PROJECT_NAME = "Restore Previous Project";
|
||||
private boolean shouldRestorePreviousProject;
|
||||
|
||||
@@ -358,10 +353,6 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
|
||||
|
||||
options.registerOption(SHOW_TOOLTIPS_OPTION_NAME, true, help,
|
||||
"Controls the display of tooltip popup windows.");
|
||||
options.registerOption(USE_COMPRESSED_DATABUFFER_OUTPUT,
|
||||
ENABLE_COMPRESSED_DATABUFFER_OUTPUT_DEFAULT, help,
|
||||
"When enabled data buffers sent to Ghidra Server are compressed (see server " +
|
||||
"configuration for other direction)");
|
||||
|
||||
options.registerOption(BLINKING_CURSORS_OPTION_NAME, true, help,
|
||||
"This controls whether" + " text cursors blink when focused");
|
||||
@@ -386,11 +377,6 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
|
||||
boolean showToolTips = options.getBoolean(SHOW_TOOLTIPS_OPTION_NAME, true);
|
||||
DockingUtils.setGlobalTooltipEnabledOption(showToolTips);
|
||||
|
||||
boolean compressDataBuffers =
|
||||
options.getBoolean(USE_COMPRESSED_DATABUFFER_OUTPUT,
|
||||
ENABLE_COMPRESSED_DATABUFFER_OUTPUT_DEFAULT);
|
||||
DataBuffer.enableCompressedSerializationOutput(compressDataBuffers);
|
||||
|
||||
shouldRestorePreviousProject = options.getBoolean(RESTORE_PREVIOUS_PROJECT_NAME, true);
|
||||
|
||||
boolean blink = options.getBoolean(BLINKING_CURSORS_OPTION_NAME, true);
|
||||
@@ -420,9 +406,6 @@ public class FrontEndTool extends PluginTool implements OptionsChangeListener {
|
||||
else if (SHOW_TOOLTIPS_OPTION_NAME.equals(optionName)) {
|
||||
DockingUtils.setGlobalTooltipEnabledOption((Boolean) newValue);
|
||||
}
|
||||
else if (USE_COMPRESSED_DATABUFFER_OUTPUT.equals(optionName)) {
|
||||
DataBuffer.enableCompressedSerializationOutput((Boolean) newValue);
|
||||
}
|
||||
else if (RESTORE_PREVIOUS_PROJECT_NAME.equals(optionName)) {
|
||||
shouldRestorePreviousProject = (Boolean) newValue;
|
||||
}
|
||||
|
||||
@@ -83,18 +83,15 @@ wrapper.java.additional.7=-Djdk.tls.server.cipherSuites="TLS_DHE_RSA_WITH_AES_25
|
||||
#wrapper.java.additional.9=-Dghidra.keystore=
|
||||
#wrapper.java.additional.10=-Dghidra.password=
|
||||
|
||||
# Enable/Disable use of compression for DataBuffer serialization and Block Streams
|
||||
wrapper.java.additional.11=-Ddb.buffers.DataBuffer.compressedOutput=true
|
||||
|
||||
# Uncomment to enable remote debug support
|
||||
# The debug address will listen on all network interfaces, if desired the '*' may be
|
||||
# set to a specific interface IP address (e.g., 127.0.0.1) if you wish to restrict.
|
||||
# During debug it will be necessary to increase timeout values to prevent the wrapper
|
||||
# from restarting the server due to unresponsiveness.
|
||||
#wrapper.java.additional.12=-Xdebug
|
||||
#wrapper.java.additional.13=-Xnoagent
|
||||
#wrapper.java.additional.14=-Djava.compiler=NONE
|
||||
#wrapper.java.additional.15=-Xrunjdwp:transport=dt_socket\,server=y\,suspend=n\,address=*:18200
|
||||
#wrapper.java.additional.11=-Xdebug
|
||||
#wrapper.java.additional.12=-Xnoagent
|
||||
#wrapper.java.additional.13=-Djava.compiler=NONE
|
||||
#wrapper.java.additional.14=-Xrunjdwp:transport=dt_socket\,server=y\,suspend=n\,address=*:18200
|
||||
#wrapper.startup.timeout=0
|
||||
#wrapper.ping.timeout=0
|
||||
|
||||
|
||||
+6
@@ -631,6 +631,12 @@ public class ServerTestUtil {
|
||||
|
||||
TransientProjectManager.getTransientProjectManager().dispose();
|
||||
|
||||
// restore default compression: enabled
|
||||
DataBuffer.enableCompressedSerializationOutput(
|
||||
Boolean.parseBoolean(
|
||||
System.getProperty(DataBuffer.COMPRESSED_SERIAL_OUTPUT_PROPERTY,
|
||||
"true")));
|
||||
|
||||
if (serverProcess != null) {
|
||||
|
||||
cmdOut.dispose();
|
||||
|
||||
Reference in New Issue
Block a user