mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 02:39:44 +02:00
Merge branch 'patch'
Conflicts: gradleScripts/distribution.gradle
This commit is contained in:
commit
1cae5552f6
23 changed files with 604 additions and 520 deletions
|
@ -15,7 +15,29 @@
|
||||||
apply plugin: 'cpp'
|
apply plugin: 'cpp'
|
||||||
apply plugin: 'c'
|
apply plugin: 'c'
|
||||||
|
|
||||||
|
// Unclear if we can rely on the VisualCpp plugin to identify the correct Visual Studio paths
|
||||||
|
|
||||||
project.ext.VISUAL_STUDIO_BASE_DIR = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017"
|
project.ext.VISUAL_STUDIO_BASE_DIR = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017"
|
||||||
|
project.ext.WINDOWS_KITS_DIR = "C:/Program Files (x86)/Windows Kits/10"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Method for extracting value from <name>=<value> pairs
|
||||||
|
****************************************************************************/
|
||||||
|
ext.getEnvironmentValue = { envLines, name ->
|
||||||
|
String assignment = name + "="
|
||||||
|
for (String line : envLines) {
|
||||||
|
if (line.startsWith(assignment)) {
|
||||||
|
String[] parts = line.split("=")
|
||||||
|
String value = parts[1].trim()
|
||||||
|
// remove trailing \ if present
|
||||||
|
if (value.endsWith("\\")) {
|
||||||
|
value = value.substring(0, value.length()-1)
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
// Ok, this is stupid, but mac and linux can't handle files paths that start with c:
|
// Ok, this is stupid, but mac and linux can't handle files paths that start with c:
|
||||||
// These paths are actually only used when running on windows, but the paths gets evaulated
|
// These paths are actually only used when running on windows, but the paths gets evaulated
|
||||||
|
@ -27,26 +49,31 @@ if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
|
||||||
if (!file(project.ext.VISUAL_STUDIO_INSTALL_DIR).exists()) {
|
if (!file(project.ext.VISUAL_STUDIO_INSTALL_DIR).exists()) {
|
||||||
project.ext.VISUAL_STUDIO_INSTALL_DIR = project.ext.VISUAL_STUDIO_BASE_DIR + "\\Community"
|
project.ext.VISUAL_STUDIO_INSTALL_DIR = project.ext.VISUAL_STUDIO_BASE_DIR + "\\Community"
|
||||||
}
|
}
|
||||||
|
println "Visual Studio Path: ${VISUAL_STUDIO_INSTALL_DIR}"
|
||||||
// TODO: Use of this will require coping with VC version in path
|
|
||||||
project.ext.WINDOWS_KITS_DIR = "C:/Program Files (x86)/Windows Kits/10.0"
|
|
||||||
|
|
||||||
project.ext.VISUAL_STUDIO_VCVARS_CMD = "\"${VISUAL_STUDIO_INSTALL_DIR}\\VC\\Auxiliary\\Build\\vcvarsall.bat\" x86_amd64"
|
project.ext.VISUAL_STUDIO_VCVARS_CMD = "\"${VISUAL_STUDIO_INSTALL_DIR}\\VC\\Auxiliary\\Build\\vcvarsall.bat\" x86_amd64"
|
||||||
|
|
||||||
// TODO: force VisualCpp installDir and windowsSdkDir
|
|
||||||
|
|
||||||
// NOTE: Windows 7 targeting requires the use of the Windows 8.1 SDK and setting the
|
// NOTE: Windows 7 targeting requires the use of the Windows 8.1 SDK and setting the
|
||||||
// WINVER property a value of "0x0601" which may be specified to the compiler/linker.
|
// WINVER property a value of "0x0601" which may be specified to the compiler/linker.
|
||||||
// If using a VS Solution this must be specified within the project file(s).
|
// If using a VS Solution this must be specified within the project file(s).
|
||||||
project.ext.WINVER = "0x0601"
|
project.ext.WINVER = "0x0601"
|
||||||
|
|
||||||
|
// Rely on vcvars script to supply SDK versions
|
||||||
|
def c = VISUAL_STUDIO_VCVARS_CMD + " && env"
|
||||||
|
String envText = c.execute().text
|
||||||
|
String[] envLines = c.execute().text.split("\n")
|
||||||
|
project.ext.MSVC_SDK_VERSION = getEnvironmentValue(envLines, "WINDOWSSDKVERSION")
|
||||||
|
println "Visual Studio SDK Version: ${MSVC_SDK_VERSION}"
|
||||||
|
project.ext.MSVC_TOOLS_VERSION = getEnvironmentValue(envLines, "VCTOOLSVERSION")
|
||||||
|
println "Visual Studio VCTools Version: ${MSVC_TOOLS_VERSION}"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
project.ext.VISUAL_STUDIO_INSTALL_DIR = "/"
|
project.ext.VISUAL_STUDIO_INSTALL_DIR = "/"
|
||||||
project.ext.WINDOWS_KITS_DIR = "/"
|
|
||||||
project.ext.VISUAL_STUDIO_VCVARS_CMD = "NA"
|
project.ext.VISUAL_STUDIO_VCVARS_CMD = "NA"
|
||||||
|
project.ext.MSVC_SDK_VERSION = "?"
|
||||||
|
project.ext.MSVC_TOOLS_VERSION = "?"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Defines the platforms we have to support in Ghidra. This model is used
|
* Defines the platforms we have to support in Ghidra. This model is used
|
||||||
* for all native builds and should be extended by each module as-needed.
|
* for all native builds and should be extended by each module as-needed.
|
||||||
|
|
|
@ -7,6 +7,49 @@
|
||||||
|
|
||||||
<BODY>
|
<BODY>
|
||||||
|
|
||||||
|
<H1 align="center">Ghidra 9.0.3 Change History (April 2019)</H1>
|
||||||
|
|
||||||
|
<blockquote><p><u>New Feature</u></p></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li><I>GUI.</I> Function tags are now viewable by function.</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<blockquote><p><u>Improvements</u></p></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li><I>Decompiler.</I> Improved modeling of CFG on Windows 10 (Thanks, Markus Pieton). (Issue #340)</li>
|
||||||
|
<li><I>Patcher.</I> Renamed patch directory to /Ghidra/patch and added README.txt that explains how the patch directory is used.</li>
|
||||||
|
<li><I>Search.</I> Fixed NullPointerException in Decompiler Data Type Reference Finder. (Issue #407)</li>
|
||||||
|
<li><I>Search.</I> Updated the Decompiler Data Type Finder to find references to inside of nested array access in a line of Decompiler C output. (Issue #416)</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<blockquote><p><u>Bugs</u></p></blockquote>
|
||||||
|
<blockquote>
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
<li><I>Analysis.</I> Code that checks for thunks no longer throws an exception if the PC is not set for the processor.</li>
|
||||||
|
<li><I>Analysis.</I> Made a fix to enable Apply button when changing tool options. (Issue #40)</li>
|
||||||
|
<li><I>Data Types.</I> Fixed concurrent modification exception when replacing one datatype for another that results in some other datatype being renamed. </li>
|
||||||
|
<li><I>Decompiler.</I> Fixed dynamic variables and equates in 16-bit x86 programs. (Issue #336)</li>
|
||||||
|
<li><I>Decompiler:Java.</I> Fixed DEX decompilation regression issue. (Issue #350)</li>
|
||||||
|
<li><I>Eclipse Integration.</I> Fixed exception in Eclipse GhidraDev plugin that occurred when performing certain actions on a Ghidra project that was imported from a previously exported Archive File. (Issues #283, #383)</li>
|
||||||
|
<li><I>Importer.</I> Fixed an exception that occurred when batch importing APK files. (Issue #426)</li>
|
||||||
|
<li><I>Languages.</I> The 6502 Zero page indexed addressing has been corrected to only access the Zero page. (Issue #201)</li>
|
||||||
|
<li><I>Languages.</I> The 68000 BCD arithmetic instructions now have pcode semantics that allow disassembly to continue. (Issue #227)</li>
|
||||||
|
<li><I>Multi-User:Ghidra Server.</I> Restored ability to execute svrAdmin script in development mode. </li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</blockquote>
|
||||||
|
`
|
||||||
|
<li><I>
|
||||||
|
|
||||||
<H1 align="center">Ghidra 9.0.2 Change History (April 2019)</H1>
|
<H1 align="center">Ghidra 9.0.2 Change History (April 2019)</H1>
|
||||||
|
|
||||||
<blockquote><p><u>Bugs</u></p></blockquote>
|
<blockquote><p><u>Bugs</u></p></blockquote>
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
||||||
import docking.options.editor.GenericOptionsComponent;
|
import docking.options.editor.GenericOptionsComponent;
|
||||||
import docking.widgets.OptionDialog;
|
import docking.widgets.OptionDialog;
|
||||||
import docking.widgets.table.*;
|
import docking.widgets.table.*;
|
||||||
|
import ghidra.GhidraOptions;
|
||||||
import ghidra.app.services.Analyzer;
|
import ghidra.app.services.Analyzer;
|
||||||
import ghidra.framework.options.*;
|
import ghidra.framework.options.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
|
@ -465,20 +466,27 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void propertyChange(PropertyChangeEvent evt) {
|
public void propertyChange(PropertyChangeEvent evt) {
|
||||||
checkForDifferences();
|
if (checkForDifferences()) {
|
||||||
|
propertyChangeListener.propertyChange(
|
||||||
|
new PropertyChangeEvent(this, GhidraOptions.APPLY_ENABLED, null, Boolean.TRUE));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkForDifferences() {
|
private boolean checkForDifferences() {
|
||||||
|
boolean changes = false;
|
||||||
for (int i = 0; i < analyzerNames.size(); ++i) {
|
for (int i = 0; i < analyzerNames.size(); ++i) {
|
||||||
String analyzerName = analyzerNames.get(i);
|
String analyzerName = analyzerNames.get(i);
|
||||||
boolean currEnabled = analyzerEnablement.get(i);
|
boolean currEnabled = analyzerEnablement.get(i);
|
||||||
boolean origEnabled = analysisOptions.getBoolean(analyzerName, false);
|
boolean origEnabled = analysisOptions.getBoolean(analyzerName, false);
|
||||||
if (currEnabled != origEnabled) {
|
if (currEnabled != origEnabled) {
|
||||||
|
changes = true;
|
||||||
propertyChangeListener.propertyChange(
|
propertyChangeListener.propertyChange(
|
||||||
new PropertyChangeEvent(this, analyzerName, origEnabled, currEnabled));
|
new PropertyChangeEvent(this, analyzerName, origEnabled, currEnabled));
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (changes) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for (EditorState info : editorList) {
|
for (EditorState info : editorList) {
|
||||||
if (info.isValueChanged()) {
|
if (info.isValueChanged()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -603,20 +611,17 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||||
public void updateOptionForAllPrograms(String analyzerName, boolean enabled) {
|
public void updateOptionForAllPrograms(String analyzerName, boolean enabled) {
|
||||||
for (Program program : programs) {
|
for (Program program : programs) {
|
||||||
|
|
||||||
|
// Check to make sure we're only handling events that relate to analyzers. If we
|
||||||
|
// receive something else (eg: "analyze.apply") ignore it.
|
||||||
|
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
||||||
|
if (!options.getOptionNames().contains(analyzerName)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
boolean commit = false;
|
boolean commit = false;
|
||||||
int id = program.startTransaction("Setting analysis property");
|
int id = program.startTransaction("Setting analysis property " + analyzerName);
|
||||||
try {
|
try {
|
||||||
Options options = program.getOptions(Program.ANALYSIS_PROPERTIES);
|
|
||||||
|
|
||||||
// Sanity check to make sure that the analyzer is appropriate for
|
|
||||||
// this program. This should always be the case but it doesn't
|
|
||||||
// hurt to check.
|
|
||||||
if (!options.getOptionNames().contains(analyzerName)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
options.setBoolean(analyzerName, enabled);
|
options.setBoolean(analyzerName, enabled);
|
||||||
|
|
||||||
commit = true;
|
commit = true;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
|
@ -624,5 +629,4 @@ class AnalysisPanel extends JPanel implements PropertyChangeListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
MODULE FILE LICENSE: lib/dex-ir-2.0.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/dex-ir-2.0.jar Apache License 2.0
|
||||||
|
MODULE FILE LICENSE: lib/dexlib-1.4.0.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/dex-reader-2.0.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/dex-reader-2.0.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/dex-reader-api-2.0.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/dex-reader-api-2.0.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/dex-translator-2.0.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/dex-translator-2.0.jar Apache License 2.0
|
||||||
|
@ -7,3 +8,4 @@ MODULE FILE LICENSE: lib/baksmali-1.4.0.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/sevenzipjbinding-9.20-2.00beta.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/sevenzipjbinding-9.20-2.00beta.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/sevenzipjbinding-all-platforms-9.20-2.00beta.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/sevenzipjbinding-all-platforms-9.20-2.00beta.jar Apache License 2.0
|
||||||
MODULE FILE LICENSE: lib/AXMLPrinter2.jar Apache License 2.0
|
MODULE FILE LICENSE: lib/AXMLPrinter2.jar Apache License 2.0
|
||||||
|
MODULE FILE LICENSE: lib/util-1.4.0.jar BSD
|
||||||
|
|
|
@ -20,7 +20,11 @@ dependencies {
|
||||||
compile ':dex-translator:2.0'
|
compile ':dex-translator:2.0'
|
||||||
|
|
||||||
compile 'org.ow2.asm:asm-debug-all:4.1'
|
compile 'org.ow2.asm:asm-debug-all:4.1'
|
||||||
compile 'org.smali:baksmali:1.4.0' // TODO: Would like 1.4.2
|
|
||||||
|
compile 'org.smali:baksmali:1.4.0' // TODO: upgrade to 2.2.6
|
||||||
|
compile 'org.smali:dexlib:1.4.0'
|
||||||
|
compile 'org.smali:util:1.4.0'
|
||||||
|
|
||||||
compile 'net.sf.sevenzipjbinding:sevenzipjbinding:9.20-2.00beta'
|
compile 'net.sf.sevenzipjbinding:sevenzipjbinding:9.20-2.00beta'
|
||||||
compile ':AXMLPrinter2'
|
compile ':AXMLPrinter2'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,403 @@
|
||||||
|
/* ###
|
||||||
|
* 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.server;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.security.auth.x500.X500Principal;
|
||||||
|
|
||||||
|
import generic.jar.ResourceFile;
|
||||||
|
import ghidra.GhidraApplicationLayout;
|
||||||
|
import ghidra.GhidraLaunchable;
|
||||||
|
import ghidra.framework.Application;
|
||||||
|
import ghidra.framework.ApplicationConfiguration;
|
||||||
|
import ghidra.util.Msg;
|
||||||
|
import ghidra.util.NamingUtilities;
|
||||||
|
|
||||||
|
public class ServerAdmin implements GhidraLaunchable {
|
||||||
|
|
||||||
|
private static final String CONFIG_FILE_PROPERTY = "UserAdmin.config";
|
||||||
|
|
||||||
|
// property name defined within the sever.conf file which specifies
|
||||||
|
// server repositories directory
|
||||||
|
private static final String SERVER_DIR_CONFIG_PROPERTY = "ghidra.repositories.dir";
|
||||||
|
|
||||||
|
private static final String INVOCATION_NAME_PROPERTY = "UserAdmin.invocation";
|
||||||
|
|
||||||
|
// Immediate commands
|
||||||
|
private static final String LIST_COMMAND = "-list";
|
||||||
|
private static final String USERS_COMMAND = "-users";
|
||||||
|
|
||||||
|
// Delayed commands
|
||||||
|
private static final String MIGRATE_COMMAND = "-migrate";
|
||||||
|
private static final String MIGRATE_ALL_COMMAND = "-migrate-all";
|
||||||
|
|
||||||
|
private boolean propertyUsed = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main method for launching the ServerAdmin Application via GhidraLauncher.
|
||||||
|
* The following properties may be set:
|
||||||
|
* <pre>
|
||||||
|
* UserAdmin.invocation - identifies the name of the application used when displaying usage text.
|
||||||
|
* UserAdmin.serverDir - identifies the server directory instead of passing on command line.
|
||||||
|
* </pre>
|
||||||
|
* @param args command line arguments
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void launch(GhidraApplicationLayout layout, String[] args) {
|
||||||
|
|
||||||
|
// Perform static initializations if not already initialized
|
||||||
|
// Some tests invoke main method directly which have already initialized Application
|
||||||
|
if (!Application.isInitialized()) {
|
||||||
|
ApplicationConfiguration configuration = new ApplicationConfiguration();
|
||||||
|
configuration.setInitializeLogging(false);
|
||||||
|
Application.initializeApplication(layout, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main method for processing ServerAdmin command line arguments.
|
||||||
|
* The following properties may be set:
|
||||||
|
* <pre>
|
||||||
|
* UserAdmin.invocation - identifies the name of the application used when displaying usage text.
|
||||||
|
* UserAdmin.serverDir - identifies the server directory instead of passing on command line.
|
||||||
|
* </pre>
|
||||||
|
* @param args command line arguments
|
||||||
|
*/
|
||||||
|
public void execute(String[] args) {
|
||||||
|
|
||||||
|
File serverDir = null;
|
||||||
|
|
||||||
|
int ix = 0;
|
||||||
|
if (args.length != 0 && !args[0].startsWith("-")) {
|
||||||
|
serverDir = new File(args[ix++]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serverDir = getServerDirFromConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serverDir == null || (args.length - ix) == 0) {
|
||||||
|
displayUsage("");
|
||||||
|
System.exit(-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
serverDir = serverDir.getCanonicalFile();
|
||||||
|
}
|
||||||
|
catch (IOException e1) {
|
||||||
|
System.err.println("Failed to resolve server directory: " + serverDir);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyUsed) {
|
||||||
|
System.out.println("Using server directory: " + serverDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
File userFile = new File(serverDir, UserManager.USER_PASSWORD_FILE);
|
||||||
|
if (!serverDir.isDirectory() || !userFile.isFile()) {
|
||||||
|
System.err.println("Invalid Ghidra server directory!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
File cmdDir = new File(serverDir, UserAdmin.ADMIN_CMD_DIR);
|
||||||
|
if (!cmdDir.isDirectory() || !cmdDir.canWrite()) {
|
||||||
|
System.err.println("Insufficient privilege or server not started!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process command line
|
||||||
|
boolean listRepositories = false;
|
||||||
|
boolean listUsers = false;
|
||||||
|
boolean migrationConfirmed = false;
|
||||||
|
boolean migrationAbort = false;
|
||||||
|
ArrayList<String> cmdList = new ArrayList<>();
|
||||||
|
int cmdLen = 1;
|
||||||
|
for (; ix < args.length; ix += cmdLen) {
|
||||||
|
boolean queueCmd = true;
|
||||||
|
if (UserAdmin.ADD_USER_COMMAND.equals(args[ix])) { // add user
|
||||||
|
cmdLen = 2;
|
||||||
|
validateSID(args, ix + 1);
|
||||||
|
}
|
||||||
|
else if (UserAdmin.REMOVE_USER_COMMAND.equals(args[ix])) { // remove user
|
||||||
|
cmdLen = 2;
|
||||||
|
validateSID(args, ix + 1);
|
||||||
|
}
|
||||||
|
else if (UserAdmin.RESET_USER_COMMAND.equals(args[ix])) { // reset user
|
||||||
|
cmdLen = 2;
|
||||||
|
validateSID(args, ix + 1);
|
||||||
|
}
|
||||||
|
else if (UserAdmin.SET_USER_DN_COMMAND.equals(args[ix])) { // set/add user with DN for PKI
|
||||||
|
cmdLen = 3;
|
||||||
|
validateSID(args, ix + 1);
|
||||||
|
validateDN(args, ix + 2);
|
||||||
|
}
|
||||||
|
else if (UserAdmin.SET_ADMIN_COMMAND.equals(args[ix])) { // set/add repository admin
|
||||||
|
cmdLen = 3;
|
||||||
|
validateSID(args, ix + 1);
|
||||||
|
validateRepName(args, ix + 2, serverDir);
|
||||||
|
}
|
||||||
|
else if (LIST_COMMAND.equals(args[ix])) { // list repositories
|
||||||
|
cmdLen = 1;
|
||||||
|
queueCmd = false;
|
||||||
|
listRepositories = true;
|
||||||
|
}
|
||||||
|
else if (USERS_COMMAND.equals(args[ix])) { // list users (also affects listRepositories)
|
||||||
|
cmdLen = 1;
|
||||||
|
queueCmd = false;
|
||||||
|
listUsers = true;
|
||||||
|
}
|
||||||
|
else if (MIGRATE_ALL_COMMAND.equals(args[ix])) { // list repositories
|
||||||
|
cmdLen = 1;
|
||||||
|
queueCmd = false;
|
||||||
|
if (!migrationConfirmed && !confirmMigration()) {
|
||||||
|
migrationAbort = true;
|
||||||
|
}
|
||||||
|
migrationConfirmed = true;
|
||||||
|
if (!migrationAbort) {
|
||||||
|
RepositoryManager.markAllRepositoriesForIndexMigration(serverDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (MIGRATE_COMMAND.equals(args[ix])) { // list repositories
|
||||||
|
cmdLen = 2;
|
||||||
|
queueCmd = false;
|
||||||
|
if (ix == (args.length - 1)) {
|
||||||
|
System.err.println("Missing " + MIGRATE_COMMAND + " repository name argument");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String repositoryName = args[ix + 1];
|
||||||
|
if (!migrationConfirmed && !confirmMigration()) {
|
||||||
|
migrationAbort = true;
|
||||||
|
}
|
||||||
|
migrationConfirmed = true;
|
||||||
|
if (!migrationAbort) {
|
||||||
|
Repository.markRepositoryForIndexMigration(serverDir, repositoryName,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
displayUsage("Invalid usage!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
if (queueCmd) {
|
||||||
|
addCommand(cmdList, args, ix, cmdLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
UserAdmin.writeCommands(cmdList, cmdDir);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
System.err.println("Failed to queue commands: " + e.toString());
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
System.out.println(cmdList.size() + " command(s) queued.");
|
||||||
|
|
||||||
|
if (listUsers) {
|
||||||
|
UserManager.listUsers(serverDir);
|
||||||
|
}
|
||||||
|
if (listRepositories) {
|
||||||
|
RepositoryManager.listRepositories(serverDir, listUsers);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param serverDir
|
||||||
|
* @param args
|
||||||
|
* @param i
|
||||||
|
*/
|
||||||
|
private static void addCommand(ArrayList<String> cmdList, String[] args, int argOffset,
|
||||||
|
int argCnt) {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
for (int i = 0; i < argCnt; i++) {
|
||||||
|
if (i > 0) {
|
||||||
|
buf.append(' ');
|
||||||
|
}
|
||||||
|
buf.append(args[argOffset + i]);
|
||||||
|
}
|
||||||
|
cmdList.add(buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean confirmMigration() {
|
||||||
|
System.out.print("\nWARNING! Please confirm the requested migration of one or more\n" +
|
||||||
|
"Ghidra Server repositories. Once migrated to indexed storage,\n" +
|
||||||
|
"any attempt to use these server repositories with a Ghidra Server\n" +
|
||||||
|
"older than version 5.5 will corrupt the data storage.\n" +
|
||||||
|
"\nWould you like to continue? [y/n]: ");
|
||||||
|
try {
|
||||||
|
if ('y' == System.in.read()) {
|
||||||
|
System.out.println();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.out.println("\nAll repository data migration(s) has been aborted.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate properly formatted Distinguished Name
|
||||||
|
* Example: 'CN=Doe John, OU=X, OU=Y, OU=DoD, O=U.S. Government, C=US'
|
||||||
|
* @param args
|
||||||
|
* @param i argument index
|
||||||
|
*/
|
||||||
|
private void validateDN(String[] args, int i) {
|
||||||
|
if (args.length < (i + 1)) {
|
||||||
|
displayUsage("Invalid usage!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
String dn = args[i];
|
||||||
|
try {
|
||||||
|
X500Principal x500User = new X500Principal(dn);
|
||||||
|
args[i] = "\"" + x500User.getName() + "\"";
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Msg.error(UserAdmin.class, "Invalid DN: " + dn);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate username/sid
|
||||||
|
* @param args
|
||||||
|
* @param i argument index
|
||||||
|
*/
|
||||||
|
private void validateSID(String[] args, int i) {
|
||||||
|
if (args.length < (i + 1)) {
|
||||||
|
displayUsage("Invalid usage!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
String sid = args[i];
|
||||||
|
if (!NamingUtilities.isValidName(sid) || sid.indexOf(' ') >= 0) {
|
||||||
|
Msg.error(UserAdmin.class, "Invalid username/sid: " + sid);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate username/sid
|
||||||
|
* @param args
|
||||||
|
* @param i argument index
|
||||||
|
*/
|
||||||
|
private void validateRepName(String[] args, int i, File rootDirFile) {
|
||||||
|
if (args.length < (i + 1)) {
|
||||||
|
displayUsage("Invalid usage!");
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
String repName = args[i];
|
||||||
|
File f = new File(rootDirFile, NamingUtilities.mangle(repName));
|
||||||
|
if (!f.isDirectory()) {
|
||||||
|
Msg.error(UserAdmin.class, "Repository not found: " + repName);
|
||||||
|
System.exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getServerDirFromConfig() {
|
||||||
|
String p = System.getProperty(CONFIG_FILE_PROPERTY);
|
||||||
|
if (p == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
propertyUsed = true;
|
||||||
|
File configFile = new File(p);
|
||||||
|
|
||||||
|
if (!configFile.exists()) {
|
||||||
|
System.out.println("Config file not found: " + configFile.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties config = new Properties();
|
||||||
|
InputStream in = null;
|
||||||
|
try {
|
||||||
|
in = new FileInputStream(configFile);
|
||||||
|
config.load(in);
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
System.out.println("Failed to read " + configFile.getName() + ": " + e.getMessage());
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY);
|
||||||
|
if (p == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
File dir = new File(p);
|
||||||
|
if (!dir.isAbsolute()) {
|
||||||
|
// Make relative repositories dir relative to installation root
|
||||||
|
ResourceFile installRoot = Application.getInstallationDirectory();
|
||||||
|
if (installRoot == null || installRoot.getFile(false) == null) {
|
||||||
|
System.out.println("Failed to resolve installation root directory!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
dir = new File(installRoot.getFile(false), p);
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display an optional message followed by usage syntax.
|
||||||
|
* @param msg
|
||||||
|
*/
|
||||||
|
private void displayUsage(String msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
System.err.println(msg);
|
||||||
|
}
|
||||||
|
String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY);
|
||||||
|
System.err.println("Usage: " +
|
||||||
|
(invocationName != null ? invocationName : "java " + UserAdmin.class.getName()) +
|
||||||
|
(propertyUsed ? "" : " <serverPath>") + " [<command>] [<command>] ...");
|
||||||
|
System.err.println("\nSupported commands:");
|
||||||
|
System.err.println(" -add <sid>");
|
||||||
|
System.err.println(" Add a new user to the server identified by their sid identifier");
|
||||||
|
System.err.println(" -remove <sid>");
|
||||||
|
System.err.println(" Remove the specified user from the server's user list");
|
||||||
|
System.err.println(" -reset <sid>");
|
||||||
|
System.err.println(" Reset the specified user's server login password");
|
||||||
|
System.err.println(" -dn <sid> \"<dname>\"");
|
||||||
|
System.err.println(
|
||||||
|
" When PKI authentication is used, add the specified X500 Distinguished Name for a user");
|
||||||
|
System.err.println(" -admin <sid> \"<repository-name>\"");
|
||||||
|
System.err.println(
|
||||||
|
" Grant ADMIN privilege to the specified user with the specified repository");
|
||||||
|
System.err.println(" -list [-users]");
|
||||||
|
System.err.println(
|
||||||
|
" Output list of repositories to the console (user access list will be included with -users)");
|
||||||
|
System.err.println(" -users");
|
||||||
|
System.err.println(" Output list of users to console which have server access");
|
||||||
|
System.err.println(" -migrate \"<repository-name>\"");
|
||||||
|
System.err.println(
|
||||||
|
" Migrate the specified repository to the latest file system storage schema (see svrREADME.html)");
|
||||||
|
System.err.println(" -migrate-all");
|
||||||
|
System.err.println(
|
||||||
|
" Migrate the all repositories to the latest file system storage schema (see svrREADME.html)");
|
||||||
|
System.err.println();
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,15 +23,8 @@ import javax.security.auth.x500.X500Principal;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import generic.jar.ResourceFile;
|
|
||||||
import ghidra.framework.Application;
|
|
||||||
import ghidra.framework.ApplicationConfiguration;
|
|
||||||
import ghidra.framework.store.local.LocalFileSystem;
|
import ghidra.framework.store.local.LocalFileSystem;
|
||||||
import ghidra.server.remote.GhidraServerApplicationLayout;
|
|
||||||
import ghidra.util.Msg;
|
|
||||||
import ghidra.util.NamingUtilities;
|
|
||||||
import ghidra.util.exception.DuplicateNameException;
|
import ghidra.util.exception.DuplicateNameException;
|
||||||
import utility.application.ApplicationLayout;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>UserAdmin</code> is an Application for generating administrative
|
* <code>UserAdmin</code> is an Application for generating administrative
|
||||||
|
@ -41,32 +34,15 @@ import utility.application.ApplicationLayout;
|
||||||
public class UserAdmin {
|
public class UserAdmin {
|
||||||
static final Logger log = LogManager.getLogger(UserAdmin.class);
|
static final Logger log = LogManager.getLogger(UserAdmin.class);
|
||||||
|
|
||||||
private static final String INVOCATION_NAME_PROPERTY = "UserAdmin.invocation";
|
|
||||||
private static final String CONFIG_FILE_PROPERTY = "UserAdmin.config";
|
|
||||||
|
|
||||||
// property name defined within the sever.conf file which specifies
|
|
||||||
// server repositories directory
|
|
||||||
private static final String SERVER_DIR_CONFIG_PROPERTY = "ghidra.repositories.dir";
|
|
||||||
|
|
||||||
private static boolean propertyUsed = false;
|
|
||||||
|
|
||||||
// Queued commands
|
// Queued commands
|
||||||
private static final String ADD_USER_COMMAND = "-add";
|
static final String ADD_USER_COMMAND = "-add";
|
||||||
private static final String REMOVE_USER_COMMAND = "-remove";
|
static final String REMOVE_USER_COMMAND = "-remove";
|
||||||
private static final String RESET_USER_COMMAND = "-reset";
|
static final String RESET_USER_COMMAND = "-reset";
|
||||||
private static final String SET_USER_DN_COMMAND = "-dn";
|
static final String SET_USER_DN_COMMAND = "-dn";
|
||||||
private static final String SET_ADMIN_COMMAND = "-admin";
|
static final String SET_ADMIN_COMMAND = "-admin";
|
||||||
|
|
||||||
// Immediate commands
|
static final String ADMIN_CMD_DIR = LocalFileSystem.HIDDEN_DIR_PREFIX + "admin";
|
||||||
private static final String LIST_COMMAND = "-list";
|
static final String COMMAND_FILE_EXT = ".cmd";
|
||||||
private static final String USERS_COMMAND = "-users";
|
|
||||||
|
|
||||||
// Delayed commands
|
|
||||||
private static final String MIGRATE_COMMAND = "-migrate";
|
|
||||||
private static final String MIGRATE_ALL_COMMAND = "-migrate-all";
|
|
||||||
|
|
||||||
private static final String ADMIN_CMD_DIR = LocalFileSystem.HIDDEN_DIR_PREFIX + "admin";
|
|
||||||
private static final String COMMAND_FILE_EXT = ".cmd";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Command file filter
|
* Command file filter
|
||||||
|
@ -264,7 +240,7 @@ public class UserAdmin {
|
||||||
* @param cmdDir command file directory
|
* @param cmdDir command file directory
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
private static void writeCommands(ArrayList<String> cmdList, File cmdDir) throws IOException {
|
static void writeCommands(ArrayList<String> cmdList, File cmdDir) throws IOException {
|
||||||
File cmdFile = File.createTempFile("adm", ".tmp", cmdDir);
|
File cmdFile = File.createTempFile("adm", ".tmp", cmdDir);
|
||||||
String cmdFilename = cmdFile.getName();
|
String cmdFilename = cmdFile.getName();
|
||||||
cmdFilename = cmdFilename.substring(0, cmdFilename.length() - 4) + COMMAND_FILE_EXT;
|
cmdFilename = cmdFilename.substring(0, cmdFilename.length() - 4) + COMMAND_FILE_EXT;
|
||||||
|
@ -289,346 +265,4 @@ public class UserAdmin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate properly formatted Distinguished Name
|
|
||||||
* Example: 'CN=Doe John, OU=X, OU=Y, OU=DoD, O=U.S. Government, C=US'
|
|
||||||
* @param args
|
|
||||||
* @param i argument index
|
|
||||||
*/
|
|
||||||
private static void validateDN(String[] args, int i) {
|
|
||||||
if (args.length < (i + 1)) {
|
|
||||||
displayUsage("Invalid usage!");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
String dn = args[i];
|
|
||||||
try {
|
|
||||||
X500Principal x500User = new X500Principal(dn);
|
|
||||||
args[i] = "\"" + x500User.getName() + "\"";
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
Msg.error(UserAdmin.class, "Invalid DN: " + dn);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate username/sid
|
|
||||||
* @param args
|
|
||||||
* @param i argument index
|
|
||||||
*/
|
|
||||||
private static void validateSID(String[] args, int i) {
|
|
||||||
if (args.length < (i + 1)) {
|
|
||||||
displayUsage("Invalid usage!");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
String sid = args[i];
|
|
||||||
if (!NamingUtilities.isValidName(sid) || sid.indexOf(' ') >= 0) {
|
|
||||||
Msg.error(UserAdmin.class, "Invalid username/sid: " + sid);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate username/sid
|
|
||||||
* @param args
|
|
||||||
* @param i argument index
|
|
||||||
*/
|
|
||||||
private static void validateRepName(String[] args, int i, File rootDirFile) {
|
|
||||||
if (args.length < (i + 1)) {
|
|
||||||
displayUsage("Invalid usage!");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
String repName = args[i];
|
|
||||||
File f = new File(rootDirFile, NamingUtilities.mangle(repName));
|
|
||||||
if (!f.isDirectory()) {
|
|
||||||
Msg.error(UserAdmin.class, "Repository not found: " + repName);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param serverDir
|
|
||||||
* @param args
|
|
||||||
* @param i
|
|
||||||
*/
|
|
||||||
private static void addCommand(ArrayList<String> cmdList, String[] args, int argOffset,
|
|
||||||
int argCnt) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
for (int i = 0; i < argCnt; i++) {
|
|
||||||
if (i > 0) {
|
|
||||||
buf.append(' ');
|
|
||||||
}
|
|
||||||
buf.append(args[argOffset + i]);
|
|
||||||
}
|
|
||||||
cmdList.add(buf.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display an optional message followed by usage syntax.
|
|
||||||
* @param msg
|
|
||||||
*/
|
|
||||||
private static void displayUsage(String msg) {
|
|
||||||
if (msg != null) {
|
|
||||||
System.err.println(msg);
|
|
||||||
}
|
|
||||||
String invocationName = System.getProperty(INVOCATION_NAME_PROPERTY);
|
|
||||||
System.err.println("Usage: " +
|
|
||||||
(invocationName != null ? invocationName : "java " + UserAdmin.class.getName()) +
|
|
||||||
(propertyUsed ? "" : " <serverPath>") + " [<command>] [<command>] ...");
|
|
||||||
System.err.println("\nSupported commands:");
|
|
||||||
System.err.println(" -add <sid>");
|
|
||||||
System.err.println(" Add a new user to the server identified by their sid identifier");
|
|
||||||
System.err.println(" -remove <sid>");
|
|
||||||
System.err.println(" Remove the specified user from the server's user list");
|
|
||||||
System.err.println(" -reset <sid>");
|
|
||||||
System.err.println(" Reset the specified user's server login password");
|
|
||||||
System.err.println(" -dn <sid> \"<dname>\"");
|
|
||||||
System.err.println(
|
|
||||||
" When PKI authentication is used, add the specified X500 Distinguished Name for a user");
|
|
||||||
System.err.println(" -admin <sid> \"<repository-name>\"");
|
|
||||||
System.err.println(
|
|
||||||
" Grant ADMIN privilege to the specified user with the specified repository");
|
|
||||||
System.err.println(" -list [-users]");
|
|
||||||
System.err.println(
|
|
||||||
" Output list of repositories to the console (user access list will be included with -users)");
|
|
||||||
System.err.println(" -users");
|
|
||||||
System.err.println(" Output list of users to console which have server access");
|
|
||||||
System.err.println(" -migrate \"<repository-name>\"");
|
|
||||||
System.err.println(
|
|
||||||
" Migrate the specified repository to the latest file system storage schema (see svrREADME.html)");
|
|
||||||
System.err.println(" -migrate-all");
|
|
||||||
System.err.println(
|
|
||||||
" Migrate the all repositories to the latest file system storage schema (see svrREADME.html)");
|
|
||||||
System.err.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File getServerDirFromConfig() {
|
|
||||||
String p = System.getProperty(CONFIG_FILE_PROPERTY);
|
|
||||||
if (p == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
propertyUsed = true;
|
|
||||||
File configFile = new File(p);
|
|
||||||
|
|
||||||
if (!configFile.exists()) {
|
|
||||||
System.out.println("Config file not found: " + configFile.getAbsolutePath());
|
|
||||||
}
|
|
||||||
|
|
||||||
Properties config = new Properties();
|
|
||||||
InputStream in = null;
|
|
||||||
try {
|
|
||||||
in = new FileInputStream(configFile);
|
|
||||||
config.load(in);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
System.out.println("Failed to read " + configFile.getName() + ": " + e.getMessage());
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
if (in != null) {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p = config.getProperty(SERVER_DIR_CONFIG_PROPERTY);
|
|
||||||
if (p == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
File dir = new File(p);
|
|
||||||
if (!dir.isAbsolute()) {
|
|
||||||
// Make relative repositories dir relative to installation root
|
|
||||||
ResourceFile installRoot = Application.getInstallationDirectory();
|
|
||||||
if (installRoot == null || installRoot.getFile(false) == null) {
|
|
||||||
System.out.println("Failed to resolve installation root directory!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
dir = new File(installRoot.getFile(false), p);
|
|
||||||
}
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main method for running the UserAdmin Application.
|
|
||||||
* The following properties may be set:
|
|
||||||
* <pre>
|
|
||||||
* UserAdmin.invocation - identifies the name of the application used when displaying usage text.
|
|
||||||
* UserAdmin.serverDir - identifies the server directory instead of passing on command line.
|
|
||||||
* </pre>
|
|
||||||
* @param args command line arguments
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
// Perform static initializations if not already initialized
|
|
||||||
// Some tests invoke main method directly which have already initialized Application
|
|
||||||
if (!Application.isInitialized()) {
|
|
||||||
ApplicationLayout layout = new GhidraServerApplicationLayout();
|
|
||||||
ApplicationConfiguration configuration = new ApplicationConfiguration();
|
|
||||||
configuration.setInitializeLogging(false);
|
|
||||||
Application.initializeApplication(layout, configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
File serverDir = null;
|
|
||||||
|
|
||||||
int ix = 0;
|
|
||||||
if (args.length != 0 && !args[0].startsWith("-")) {
|
|
||||||
serverDir = new File(args[ix++]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
serverDir = getServerDirFromConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serverDir == null || (args.length - ix) == 0) {
|
|
||||||
displayUsage("");
|
|
||||||
System.exit(-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
serverDir = serverDir.getCanonicalFile();
|
|
||||||
}
|
|
||||||
catch (IOException e1) {
|
|
||||||
System.err.println("Failed to resolve server directory: " + serverDir);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (propertyUsed) {
|
|
||||||
System.out.println("Using server directory: " + serverDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
File userFile = new File(serverDir, UserManager.USER_PASSWORD_FILE);
|
|
||||||
if (!serverDir.isDirectory() || !userFile.isFile()) {
|
|
||||||
System.err.println("Invalid Ghidra server directory specified: " + serverDir);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
File cmdDir = new File(serverDir, ADMIN_CMD_DIR);
|
|
||||||
if (!cmdDir.exists()) {
|
|
||||||
System.err.println("Insufficient privilege or server not started.");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
if (!cmdDir.isDirectory()) {
|
|
||||||
System.err.println("Bad server directory: " + serverDir);
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process command line
|
|
||||||
boolean listRepositories = false;
|
|
||||||
boolean listUsers = false;
|
|
||||||
boolean migrationConfirmed = false;
|
|
||||||
boolean migrationAbort = false;
|
|
||||||
ArrayList<String> cmdList = new ArrayList<>();
|
|
||||||
int cmdLen = 1;
|
|
||||||
for (; ix < args.length; ix += cmdLen) {
|
|
||||||
boolean queueCmd = true;
|
|
||||||
if (ADD_USER_COMMAND.equals(args[ix])) { // add user
|
|
||||||
cmdLen = 2;
|
|
||||||
validateSID(args, ix + 1);
|
|
||||||
}
|
|
||||||
else if (REMOVE_USER_COMMAND.equals(args[ix])) { // remove user
|
|
||||||
cmdLen = 2;
|
|
||||||
validateSID(args, ix + 1);
|
|
||||||
}
|
|
||||||
else if (RESET_USER_COMMAND.equals(args[ix])) { // reset user
|
|
||||||
cmdLen = 2;
|
|
||||||
validateSID(args, ix + 1);
|
|
||||||
}
|
|
||||||
else if (SET_USER_DN_COMMAND.equals(args[ix])) { // set/add user with DN for PKI
|
|
||||||
cmdLen = 3;
|
|
||||||
validateSID(args, ix + 1);
|
|
||||||
validateDN(args, ix + 2);
|
|
||||||
}
|
|
||||||
else if (SET_ADMIN_COMMAND.equals(args[ix])) { // set/add repository admin
|
|
||||||
cmdLen = 3;
|
|
||||||
validateSID(args, ix + 1);
|
|
||||||
validateRepName(args, ix + 2, serverDir);
|
|
||||||
}
|
|
||||||
else if (LIST_COMMAND.equals(args[ix])) { // list repositories
|
|
||||||
cmdLen = 1;
|
|
||||||
queueCmd = false;
|
|
||||||
listRepositories = true;
|
|
||||||
}
|
|
||||||
else if (USERS_COMMAND.equals(args[ix])) { // list users (also affects listRepositories)
|
|
||||||
cmdLen = 1;
|
|
||||||
queueCmd = false;
|
|
||||||
listUsers = true;
|
|
||||||
}
|
|
||||||
else if (MIGRATE_ALL_COMMAND.equals(args[ix])) { // list repositories
|
|
||||||
cmdLen = 1;
|
|
||||||
queueCmd = false;
|
|
||||||
if (!migrationConfirmed && !confirmMigration()) {
|
|
||||||
migrationAbort = true;
|
|
||||||
}
|
|
||||||
migrationConfirmed = true;
|
|
||||||
if (!migrationAbort) {
|
|
||||||
RepositoryManager.markAllRepositoriesForIndexMigration(serverDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (MIGRATE_COMMAND.equals(args[ix])) { // list repositories
|
|
||||||
cmdLen = 2;
|
|
||||||
queueCmd = false;
|
|
||||||
if (ix == (args.length - 1)) {
|
|
||||||
System.err.println("Missing " + MIGRATE_COMMAND + " repository name argument");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String repositoryName = args[ix + 1];
|
|
||||||
if (!migrationConfirmed && !confirmMigration()) {
|
|
||||||
migrationAbort = true;
|
|
||||||
}
|
|
||||||
migrationConfirmed = true;
|
|
||||||
if (!migrationAbort) {
|
|
||||||
Repository.markRepositoryForIndexMigration(serverDir, repositoryName,
|
|
||||||
false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
displayUsage("Invalid usage!");
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
if (queueCmd) {
|
|
||||||
addCommand(cmdList, args, ix, cmdLen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
writeCommands(cmdList, cmdDir);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
System.err.println("Failed to queue commands: " + e.toString());
|
|
||||||
System.exit(-1);
|
|
||||||
}
|
|
||||||
System.out.println(cmdList.size() + " command(s) queued.");
|
|
||||||
|
|
||||||
if (listUsers) {
|
|
||||||
UserManager.listUsers(serverDir);
|
|
||||||
}
|
|
||||||
if (listRepositories) {
|
|
||||||
RepositoryManager.listRepositories(serverDir, listUsers);
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean confirmMigration() {
|
|
||||||
System.out.print("\nWARNING! Please confirm the requested migration of one or more\n" +
|
|
||||||
"Ghidra Server repositories. Once migrated to indexed storage,\n" +
|
|
||||||
"any attempt to use these server repositories with a Ghidra Server\n" +
|
|
||||||
"older than version 5.5 will corrupt the data storage.\n" +
|
|
||||||
"\nWould you like to continue? [y/n]: ");
|
|
||||||
try {
|
|
||||||
if ('y' == System.in.read()) {
|
|
||||||
System.out.println();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
System.out.println("\nAll repository data migration(s) has been aborted.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -532,12 +532,17 @@ public class UserManager {
|
||||||
readUserList(userFile, list, lookupMap);
|
readUserList(userFile, list, lookupMap);
|
||||||
|
|
||||||
System.out.println("\nRepository Server Users:");
|
System.out.println("\nRepository Server Users:");
|
||||||
for (String name : list.keySet()) {
|
if (list.isEmpty()) {
|
||||||
System.out.println(" " + name);
|
System.out.println(" <No users have been added>");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (String name : list.keySet()) {
|
||||||
|
System.out.println(" " + name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
System.out.println("Failed to read user file: " + e.getMessage());
|
System.out.println("\nFailed to read user file: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,13 @@ import DisplayParser, SemanticParser;
|
||||||
gDisplayParser.setLexer(lexer);
|
gDisplayParser.setLexer(lexer);
|
||||||
gSemanticParser.setLexer(lexer);
|
gSemanticParser.setLexer(lexer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnv(ParsingEnvironment env) {
|
||||||
|
super.setEnv(env);
|
||||||
|
gDisplayParser.setEnv(env);
|
||||||
|
gSemanticParser.setEnv(env);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,30 +1,29 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ***********************************************************
|
# ***********************************************************
|
||||||
# ** Arguments (each -argument option may be repeated):
|
# ** Arguments (each -argument option may be repeated):
|
||||||
# ** [-add <sid>] [-remove <sid>] [-reset <sid>] [-dn <sid> "<x500_distinguished_name>"]
|
# ** [-add <sid>] [-dn <sid> "<x500_distinguished_name>"]
|
||||||
# ** [-admin <sid> "<repository-name>"] [-list] [-migrate "<repository-name>"] [-migrate-all]
|
# ** [-remove <sid>]
|
||||||
|
# ** [-reset <sid>]
|
||||||
|
# ** [-admin <sid> "<repository-name>"]
|
||||||
|
# ** [-list] [-users]
|
||||||
|
# ** [-migrate "<repository-name>"] [-migrate-all]
|
||||||
# **
|
# **
|
||||||
# ** add - add a new user to the server with the default password 'changeme'
|
# ** add - add a new user to the server with the default password 'changeme'
|
||||||
|
# ** dn - set a user's distinguished name for PKI authentication
|
||||||
# ** remove - remove an existing user from the server
|
# ** remove - remove an existing user from the server
|
||||||
# ** reset - reset an existing user's password to 'changeme'
|
# ** reset - reset an existing user's password to 'changeme'
|
||||||
# ** dn - set a user's distinguished name for PKI authentication
|
|
||||||
# ** admin - set the specified existing user as an admin of the specified repository
|
# ** admin - set the specified existing user as an admin of the specified repository
|
||||||
# ** list - list all existing named repositories
|
# ** list - list all existing named repositories
|
||||||
|
# ** users - list all users or those associated with each listed repository
|
||||||
# ** migrate - migrate the specified named repository to an indexed data storage
|
# ** migrate - migrate the specified named repository to an indexed data storage
|
||||||
# ** migrate-all - migrate all named repositories to index data storage
|
# ** migrate-all - migrate all named repositories to index data storage
|
||||||
# ***********************************************************
|
# ***********************************************************
|
||||||
|
|
||||||
UMASK=027
|
SUDO=sudo
|
||||||
|
|
||||||
# Preserve quoted arguments
|
# Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
|
||||||
ARGS=()
|
# the physical memory available to the OS. Uncomment MAXMEM setting if non-default value is needed.
|
||||||
WHITESPACE="[[:space:]]"
|
MAXMEM=128M
|
||||||
for AA in "$@"; do
|
|
||||||
if [[ $AA =~ $WHITESPACE ]]; then
|
|
||||||
AA="\"$AA\""
|
|
||||||
fi
|
|
||||||
ARGS[${#ARGS[@]}]=$AA
|
|
||||||
done
|
|
||||||
|
|
||||||
# Resolve symbolic link if present and get the directory this script lives in.
|
# Resolve symbolic link if present and get the directory this script lives in.
|
||||||
# NOTE: "readlink -f" is best but works on Linux only, "readlink" will only work if your PWD
|
# NOTE: "readlink -f" is best but works on Linux only, "readlink" will only work if your PWD
|
||||||
|
@ -34,49 +33,20 @@ SCRIPT_FILE="$(readlink -f "$0" 2>/dev/null || readlink "$0" 2>/dev/null || echo
|
||||||
SCRIPT_DIR="${SCRIPT_FILE%/*}"
|
SCRIPT_DIR="${SCRIPT_FILE%/*}"
|
||||||
|
|
||||||
if [ -d "${SCRIPT_DIR}/../Ghidra" ]; then
|
if [ -d "${SCRIPT_DIR}/../Ghidra" ]; then
|
||||||
|
|
||||||
# Production Environment
|
# Production Environment
|
||||||
CONFIG="${SCRIPT_DIR}/server.conf"
|
CONFIG="${SCRIPT_DIR}/server.conf"
|
||||||
GHIDRA_DIR="${SCRIPT_DIR}/../Ghidra"
|
|
||||||
CPATH="${GHIDRA_DIR}/Features/GhidraServer/lib/GhidraServer.jar:${GHIDRA_DIR}/Framework/FileSystem/lib/FileSystem.jar:${GHIDRA_DIR}/Framework/DB/lib/DB.jar:${GHIDRA_DIR}/Framework/Generic/lib/Generic.jar:${GHIDRA_DIR}/Framework/Utility/lib/Utility.jar:${GHIDRA_DIR}/Framework/Generic/lib/log4j-core-2.8.1.jar:${GHIDRA_DIR}/Framework/Generic/lib/log4j-api-2.8.1.jar"
|
|
||||||
LS_CPATH="${GHIDRA_DIR}/../support/LaunchSupport.jar"
|
|
||||||
else
|
else
|
||||||
|
|
||||||
# Development Environment
|
# Development Environment
|
||||||
CONFIG="${SCRIPT_DIR}/../../Common/server/server.conf"
|
CONFIG="${SCRIPT_DIR}/../../Common/server/server.conf"
|
||||||
GHIDRA_DIR="${SCRIPT_DIR}/../../.."
|
|
||||||
GHIDRA_BIN_REPO="${GHIDRA_DIR}/../../ghidra.bin"
|
|
||||||
CPATH="${GHIDRA_DIR}/Features/GhidraServer/bin/main:${GHIDRA_DIR}/Framework/FileSystem/bin/main:${GHIDRA_DIR}/Framework/DB/bin/main:${GHIDRA_DIR}/Framework/Generic/bin/main:${GHIDRA_DIR}/Framework/Utility/bin/main:${GHIDRA_BIN_REPO}/ExternalLibraries/libsForRuntime/log4j-core-2.8.1.jar:${GHIDRA_BIN_REPO}/ExternalLibraries/libsForRuntime/log4j-api-2.8.1.jar"
|
|
||||||
LS_CPATH="${GHIDRA_DIR}/../GhidraBuild/LaunchSupport/bin/main"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Make sure some kind of java is on the path. It's required to run the LaunchSupport program.
|
|
||||||
if ! [ -x "$(command -v java)" ] ; then
|
|
||||||
echo "Java runtime not found. Please refer to the Ghidra Installation Guide's Troubleshooting section."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the java that will be used to launch GhidraServer
|
|
||||||
JAVA_HOME=$(java -cp "${LS_CPATH}" LaunchSupport "${GHIDRA_DIR}/.." -java_home)
|
|
||||||
if [ ! $? -eq 0 ]; then
|
|
||||||
echo "Failed to find a supported Java runtime. Please refer to the Ghidra Installation Guide's Troubleshooting section."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
JAVA_CMD="${JAVA_HOME}/bin/java"
|
|
||||||
|
|
||||||
VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") -DUserAdmin.config=\"${CONFIG}\""
|
|
||||||
|
|
||||||
OLD_UMASK=$(umask)
|
|
||||||
umask $UMASK
|
|
||||||
|
|
||||||
# Identify server process owner if set within server.conf
|
# Identify server process owner if set within server.conf
|
||||||
OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')"
|
OWNER="$(grep '^wrapper.app.account=' "${CONFIG}" | sed -e 's/^.*=\(.*\)\s*.*$/\1/')"
|
||||||
|
|
||||||
if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then
|
if [ -z "${OWNER}" -o "${OWNER}" = "$(whoami)" ]; then
|
||||||
eval "\"${JAVA_CMD}\" ${VMARGS} -cp \"${CPATH}\" ghidra.server.UserAdmin ${ARGS[@]}"
|
VMARGS="-DUserAdmin.invocation=$(basename "${SCRIPT_FILE}") -DUserAdmin.config=\"${CONFIG}\""
|
||||||
|
"${SCRIPT_DIR}"/../support/launch.sh fg svrAdmin "${MAXMEM}" "$VMARGS" ghidra.server.ServerAdmin "$@"
|
||||||
else
|
else
|
||||||
echo "Running svrAdmin with sudo as ${OWNER} ..."
|
echo "Running svrAdmin with $SUDO as ${OWNER} ..."
|
||||||
eval "sudo -u "${OWNER}" \"${JAVA_CMD}\" ${VMARGS} -cp \"${CPATH}\" ghidra.server.UserAdmin ${ARGS[@]}"
|
$SUDO -u $OWNER "$0" "${ARGS[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
umask $OLD_UMASK
|
|
||||||
|
|
|
@ -1,22 +1,30 @@
|
||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
:: ***********************************************************
|
:: ***********************************************************
|
||||||
:: ** Arguments (each argument set may be repeated):
|
:: ** Arguments (each -argument option may be repeated):
|
||||||
:: ** [-add <sid>] [-remove <sid>] [-reset <sid>] [-dn <sid> "<x500_distinguished_name>"]
|
:: ** [-add <sid>] [-dn <sid> "<x500_distinguished_name>"]
|
||||||
:: ** [-admin <sid> "<repository-name>"] [-list] [-migrate "<repository-name>"] [-migrate-all]
|
:: ** [-remove <sid>]
|
||||||
|
:: ** [-reset <sid>]
|
||||||
|
:: ** [-admin <sid> "<repository-name>"]
|
||||||
|
:: ** [-list] [-users]
|
||||||
|
:: ** [-migrate "<repository-name>"] [-migrate-all]
|
||||||
:: **
|
:: **
|
||||||
:: ** add - add a new user to the server with the default password 'changeme'
|
:: ** add - add a new user to the server with the default password 'changeme'
|
||||||
|
:: ** dn - set a user's distinguished name for PKI authentication
|
||||||
:: ** remove - remove an existing user from the server
|
:: ** remove - remove an existing user from the server
|
||||||
:: ** reset - reset an existing user's password to 'changeme'
|
:: ** reset - reset an existing user's password to 'changeme'
|
||||||
:: ** dn - set a user's distinguished name for PKI authentication
|
|
||||||
:: ** admin - set the specified existing user as an admin of the specified repository
|
:: ** admin - set the specified existing user as an admin of the specified repository
|
||||||
:: ** list - list all existing named repositories
|
:: ** list - list all existing named repositories
|
||||||
|
:: ** users - list all users or those associated with each listed repository
|
||||||
:: ** migrate - migrate the specified named repository to an indexed data storage
|
:: ** migrate - migrate the specified named repository to an indexed data storage
|
||||||
:: ** migrate-all - migrate all named repositories to index data storage
|
:: ** migrate-all - migrate all named repositories to index data storage
|
||||||
:: ***********************************************************
|
:: ***********************************************************
|
||||||
|
|
||||||
setlocal
|
setlocal
|
||||||
|
|
||||||
|
:: maximum heap memory may be change if inadequate
|
||||||
|
set MAXMEM=128M
|
||||||
|
|
||||||
:: Sets SCRIPT_DIR to the directory that contains this file
|
:: Sets SCRIPT_DIR to the directory that contains this file
|
||||||
::
|
::
|
||||||
:: '% ~' dereferences the value in param 0
|
:: '% ~' dereferences the value in param 0
|
||||||
|
@ -24,51 +32,16 @@ setlocal
|
||||||
:: 'p' - path (without filename)
|
:: 'p' - path (without filename)
|
||||||
set SCRIPT_DIR=%~dp0
|
set SCRIPT_DIR=%~dp0
|
||||||
|
|
||||||
:: Uncomment and set the value below as necessary
|
|
||||||
:: set SCRIPT_DIR=<full Ghidra installation server directory path>
|
|
||||||
|
|
||||||
if not exist "%SCRIPT_DIR%" (
|
|
||||||
echo Unable to set the Ghidra server script directory.
|
|
||||||
echo.
|
|
||||||
echo To run Ghidra in this mode you must set the
|
|
||||||
echo value of SCRIPT_DIR in this file to be
|
|
||||||
echo the full path containing this batch file
|
|
||||||
goto :eof
|
|
||||||
)
|
|
||||||
|
|
||||||
:: Production Environment
|
:: Production Environment
|
||||||
set CONFIG=%SCRIPT_DIR%.\server.conf
|
set CONFIG=%SCRIPT_DIR%.\server.conf
|
||||||
set GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra
|
|
||||||
set CPATH=%GHIDRA_DIR%\Features\GhidraServer\lib\GhidraServer.jar;%GHIDRA_DIR%\Framework\FileSystem\lib\FileSystem.jar;%GHIDRA_DIR%\Framework\DB\lib\DB.jar;%GHIDRA_DIR%\Framework\Generic\lib\Generic.jar;%GHIDRA_DIR%\Framework\Utility\lib\Utility.jar;%GHIDRA_DIR%\Framework\Generic\lib\log4j-core-2.8.1.jar;%GHIDRA_DIR%\Framework\Generic\lib\log4j-api-2.8.1.jar
|
|
||||||
set LS_CPATH=%GHIDRA_DIR%\..\support\LaunchSupport.jar
|
|
||||||
|
|
||||||
if exist "%GHIDRA_DIR%" goto continue
|
if exist "%GHIDRA_DIR%" goto continue
|
||||||
|
|
||||||
:: Development Environment - assumes suitable java in command path
|
:: Development Environment
|
||||||
set CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf
|
set CONFIG=%SCRIPT_DIR%..\..\Common\server\server.conf
|
||||||
set GHIDRA_DIR=%SCRIPT_DIR%..\..\..
|
|
||||||
set GHIDRA_BIN_HOME=%GHIDRA_DIR%\..\..\ghidra.bin
|
|
||||||
set CPATH=%GHIDRA_DIR%\Features\GhidraServer\bin\main;%GHIDRA_DIR%\Framework\FileSystem\bin\main;%GHIDRA_DIR%\Framework\DB\bin\main;%GHIDRA_DIR%\Framework\Generic\bin\main;%GHIDRA_DIR%\Framework\Utility\bin\main;%GHIDRA_BIN_HOME%\ExternalLibraries\libsForRuntime\log4j-core-2.8.1.jar;%GHIDRA_BIN_HOME%\ExternalLibraries\libsForRuntime\log4j-api-2.8.1.jar
|
|
||||||
set LS_CPATH=%GHIDRA_DIR%\..\GhidraBuild\LaunchSupport\bin\main
|
|
||||||
|
|
||||||
:continue
|
:continue
|
||||||
|
|
||||||
:: Make sure some kind of java is on the path. It's required to run the LaunchSupport program.
|
set VMARGS=-DUserAdmin.invocation="%0" -DUserAdmin.config="%CONFIG%"
|
||||||
java -version >nul 2>nul
|
|
||||||
if not %ERRORLEVEL% == 0 (
|
|
||||||
echo Java runtime not found. Please refer to the Ghidra Installation Guide's Troubleshooting section.
|
|
||||||
exit /B 1
|
|
||||||
)
|
|
||||||
|
|
||||||
:: Get the java that will be used to launch GhidraServer
|
call "%~dp0\..\support\launch.bat" fg svrAdmin "%MAXMEM%" "%VMARGS%" ghidra.server.ServerAdmin %*
|
||||||
set JAVA_HOME=
|
|
||||||
for /f "delims=*" %%i in ('java -cp "%LS_CPATH%" LaunchSupport "%GHIDRA_DIR%\.." -java_home') do set JAVA_HOME=%%i
|
|
||||||
if "%JAVA_HOME%" == "" (
|
|
||||||
echo Failed to find a supported Java runtime. Please refer to the Ghidra Installation Guide's Troubleshooting section.
|
|
||||||
exit /B 1
|
|
||||||
)
|
|
||||||
set JAVA=%JAVA_HOME%\bin\java.exe
|
|
||||||
|
|
||||||
set VMARGS=-DUserAdmin.invocation="%0" -DUserAdmin.config="%CONFIG%" -Djava.net.preferIPv4Stack=true
|
|
||||||
|
|
||||||
"%JAVA%" %VMARGS% -cp "%CPATH%" ghidra.server.UserAdmin %*
|
|
||||||
|
|
|
@ -10,31 +10,45 @@
|
||||||
@echo off
|
@echo off
|
||||||
setlocal
|
setlocal
|
||||||
|
|
||||||
if "%~1" == "" (
|
|
||||||
echo "Usage: createPdbXmlFiles.bat <path to .pdb file|path to directory of .pdb files>"
|
|
||||||
Exit /B 0
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Get parent of current folder
|
REM Get parent of current folder
|
||||||
for %%A in (%~dp0\.) do set ghidraPath=%%~dpA
|
set SCRIPT_DIR=%~dp0
|
||||||
|
|
||||||
|
set GHIDRA_DIR=%SCRIPT_DIR%..\Ghidra
|
||||||
|
set OS_DIR=os
|
||||||
|
|
||||||
REM Production Environment
|
REM Production Environment
|
||||||
if exist "%ghidraPath%Ghidra" goto continue
|
if exist "%GHIDRA_DIR%" goto continue
|
||||||
|
|
||||||
REM Development Environment
|
REM Development Environment
|
||||||
set ghidraPath="%ghidraPath%..\..\..\..\ghidra.bin\"
|
set GHIDRA_DIR=%SCRIPT_DIR%..\..\..
|
||||||
|
set OS_DIR=build\os
|
||||||
|
|
||||||
:continue
|
:continue
|
||||||
|
|
||||||
set arg1="%~1"
|
REM create absolute path
|
||||||
|
for /f %%i in ("%GHIDRA_DIR%") do set GHIDRA_DIR=%%~fi
|
||||||
|
|
||||||
REM Determine if 64-bit or 32-bit
|
REM Determine if 64-bit or 32-bit
|
||||||
if exist "%PROGRAMFILES(X86)%" (
|
if exist "%PROGRAMFILES(X86)%" (
|
||||||
set osType=win64
|
set OS_TYPE=win64
|
||||||
) else (
|
) else (
|
||||||
set osType=win32
|
set OS_TYPE=win32
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set PDB_EXE=%GHIDRA_DIR%\Features\PDB\%OS_DIR%\%OS_TYPE%\pdb.exe
|
||||||
|
|
||||||
|
if not exist "%PDB_EXE%" (
|
||||||
|
echo "%PDB_EXE% not found"
|
||||||
|
Exit /B 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%~1" == "" (
|
||||||
|
echo "Usage: createPdbXmlFiles.bat <path to .pdb file|path to directory of .pdb files>"
|
||||||
|
Exit /B 1
|
||||||
|
)
|
||||||
|
|
||||||
|
set arg1="%~1"
|
||||||
|
|
||||||
set /a count=0
|
set /a count=0
|
||||||
|
|
||||||
REM Recursively traverse through the given directory
|
REM Recursively traverse through the given directory
|
||||||
|
@ -50,7 +64,7 @@ for /f "tokens=* delims=" %%a in ('dir %arg1% /s /b') do (
|
||||||
setlocal enableDelayedExpansion
|
setlocal enableDelayedExpansion
|
||||||
(
|
(
|
||||||
echo "Processing file: %%a"
|
echo "Processing file: %%a"
|
||||||
START /B /WAIT "" "%ghidraPath%Ghidra\Features\PDB\os\%ostype%\pdb.exe" %%a > "%%a.xml"
|
START /B /WAIT "" "%PDB_EXE%" %%a > "%%a.xml"
|
||||||
|
|
||||||
REM Exit if executable returned non-zero error code (signifies that there is a problem).
|
REM Exit if executable returned non-zero error code (signifies that there is a problem).
|
||||||
if !errorlevel! neq 0 (
|
if !errorlevel! neq 0 (
|
||||||
|
@ -63,7 +77,7 @@ for /f "tokens=* delims=" %%a in ('dir %arg1% /s /b') do (
|
||||||
echo Error detected. Exiting...
|
echo Error detected. Exiting...
|
||||||
)
|
)
|
||||||
|
|
||||||
Exit /B 0
|
Exit /B 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ import ghidra.framework.store.local.LocalFileSystem;
|
||||||
import ghidra.framework.store.local.LocalFolderItem;
|
import ghidra.framework.store.local.LocalFolderItem;
|
||||||
import ghidra.net.*;
|
import ghidra.net.*;
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.server.UserAdmin;
|
import ghidra.server.ServerAdmin;
|
||||||
import ghidra.server.UserManager;
|
import ghidra.server.UserManager;
|
||||||
import ghidra.test.ToyProgramBuilder;
|
import ghidra.test.ToyProgramBuilder;
|
||||||
import ghidra.util.*;
|
import ghidra.util.*;
|
||||||
|
@ -942,11 +942,12 @@ public class ServerTestUtil {
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static void addPKIUser(File serverRoot, String userName, String dn) throws Exception {
|
public static void addPKIUser(File serverRoot, String userName, String dn) throws Exception {
|
||||||
|
ServerAdmin serverAdmin = new ServerAdmin();
|
||||||
if (dn != null) {
|
if (dn != null) {
|
||||||
UserAdmin.main(new String[] { serverRoot.getAbsolutePath(), "-dn", userName, dn });
|
serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-dn", userName, dn });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
UserAdmin.main(new String[] { serverRoot.getAbsolutePath(), "-add", userName });
|
serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-add", userName });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Drop jar files in this directory to apply patches to an installation of Ghidra. Any jar files
|
|
||||||
found in this directory will be placed at the front of the classpath, allowing them to override
|
|
||||||
any existing classes in any module.
|
|
|
@ -1,2 +0,0 @@
|
||||||
##VERSION: 2.0
|
|
||||||
README.txt||GHIDRA||||END|
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<site>
|
<site>
|
||||||
<feature url="features/ghidra.ghidradev_2.0.0.qualifier.jar" id="ghidra.ghidradev" version="2.0.0.qualifier">
|
<feature url="features/ghidra.ghidradev_2.0.1.qualifier.jar" id="ghidra.ghidradev" version="2.0.1.qualifier">
|
||||||
<category name="ghidra.ghidradev"/>
|
<category name="ghidra.ghidradev"/>
|
||||||
</feature>
|
</feature>
|
||||||
<category-def name="ghidra.ghidradev" label="Ghidra"/>
|
<category-def name="ghidra.ghidradev" label="Ghidra"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<feature
|
<feature
|
||||||
id="ghidra.ghidradev"
|
id="ghidra.ghidradev"
|
||||||
label="GhidraDev"
|
label="GhidraDev"
|
||||||
version="2.0.0.qualifier"
|
version="2.0.1.qualifier"
|
||||||
provider-name="Ghidra">
|
provider-name="Ghidra">
|
||||||
|
|
||||||
<description>
|
<description>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<h1>GhidraDev README</h1>
|
<h1>GhidraDev README</h1>
|
||||||
<p>GhidraDev provides support for developing and debugging Ghidra scripts and modules in Eclipse.
|
<p>GhidraDev provides support for developing and debugging Ghidra scripts and modules in Eclipse.
|
||||||
</p>
|
</p>
|
||||||
<p>The information provided in this document is effective as of GhidraDev 2.0.0 and is subject to
|
<p>The information provided in this document is effective as of GhidraDev 2.0.1 and is subject to
|
||||||
change with future releases.</p>
|
change with future releases.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -53,7 +53,9 @@ change with future releases.</p>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2><a name="ChangeHistory"></a>Change History</h2>
|
<h2><a name="ChangeHistory"></a>Change History</h2>
|
||||||
<p><u><b>2.0.0</b>:</u></p>
|
<p><u><b>2.0.1</b>:</u> Fixed exception that occurred when performing certain actions on a Ghidra
|
||||||
|
project that was imported from a previously exported Archive File.</p>
|
||||||
|
<p><u><b>2.0.0</b>:</u>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
Improved Ghidra module project starting templates for Analyzer and Plugin and added new
|
Improved Ghidra module project starting templates for Analyzer and Plugin and added new
|
||||||
|
|
|
@ -3,7 +3,7 @@ Manifest-Version: 1.0
|
||||||
Bundle-ManifestVersion: 2
|
Bundle-ManifestVersion: 2
|
||||||
Bundle-Name: GhidraDev
|
Bundle-Name: GhidraDev
|
||||||
Bundle-SymbolicName: ghidra.ghidradev;singleton:=true
|
Bundle-SymbolicName: ghidra.ghidradev;singleton:=true
|
||||||
Bundle-Version: 2.0.0.qualifier
|
Bundle-Version: 2.0.1.qualifier
|
||||||
Bundle-Activator: ghidradev.Activator
|
Bundle-Activator: ghidradev.Activator
|
||||||
Require-Bundle: org.eclipse.ant.core;bundle-version="3.5.200",
|
Require-Bundle: org.eclipse.ant.core;bundle-version="3.5.200",
|
||||||
org.eclipse.buildship.core;bundle-version="3.0.0",
|
org.eclipse.buildship.core;bundle-version="3.0.0",
|
||||||
|
|
|
@ -222,7 +222,7 @@ public class GhidraModuleUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
File ghidraInstallDir = ghidraLayout.getApplicationInstallationDir().getFile(false);
|
File ghidraInstallDir = ghidraLayout.getApplicationInstallationDir().getFile(false);
|
||||||
File antFile = new File(project.getRawLocation().toFile(), ".antProperties.xml"); // hidden
|
File antFile = new File(project.getLocation().toFile(), ".antProperties.xml"); // hidden
|
||||||
|
|
||||||
try (PrintWriter writer = new PrintWriter(new FileWriter(antFile))) {
|
try (PrintWriter writer = new PrintWriter(new FileWriter(antFile))) {
|
||||||
writer.println(
|
writer.println(
|
||||||
|
|
|
@ -352,7 +352,7 @@ public class GhidraProjectUtils {
|
||||||
IFolder ghidraFolder =
|
IFolder ghidraFolder =
|
||||||
javaProject.getProject().getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME);
|
javaProject.getProject().getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME);
|
||||||
IPath oldGhidraInstallPath = ghidraFolder.exists()
|
IPath oldGhidraInstallPath = ghidraFolder.exists()
|
||||||
? new Path(ghidraFolder.getRawLocation().toFile().getAbsolutePath())
|
? new Path(ghidraFolder.getLocation().toFile().getAbsolutePath())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
// Loop through the project's existing classpath to decide what to keep (things that aren't
|
// Loop through the project's existing classpath to decide what to keep (things that aren't
|
||||||
|
|
|
@ -111,7 +111,7 @@ public class ExportGhidraModuleWizard extends Wizard implements INewWizard {
|
||||||
|
|
||||||
// Get path to Ghidra installation directory
|
// Get path to Ghidra installation directory
|
||||||
String ghidraInstallDirPath = project.getFolder(
|
String ghidraInstallDirPath = project.getFolder(
|
||||||
GhidraProjectUtils.GHIDRA_FOLDER_NAME).getRawLocation().toOSString();
|
GhidraProjectUtils.GHIDRA_FOLDER_NAME).getLocation().toOSString();
|
||||||
|
|
||||||
// Get project's java. Gradle should use the same version.
|
// Get project's java. Gradle should use the same version.
|
||||||
// TODO: It's more correct to get this from the project's classpath, since Ghidra's
|
// TODO: It's more correct to get this from the project's classpath, since Ghidra's
|
||||||
|
@ -126,7 +126,7 @@ public class ExportGhidraModuleWizard extends Wizard implements INewWizard {
|
||||||
|
|
||||||
// Setup the Gradle build attributes
|
// Setup the Gradle build attributes
|
||||||
List<String> tasks = new ArrayList<>();
|
List<String> tasks = new ArrayList<>();
|
||||||
String workingDir = project.getRawLocation().toOSString();
|
String workingDir = project.getLocation().toOSString();
|
||||||
String gradleDist = gradleDistribution.toString();
|
String gradleDist = gradleDistribution.toString();
|
||||||
String gradleUserHome = "";
|
String gradleUserHome = "";
|
||||||
String javaHome = javaHomeDir.getAbsolutePath();
|
String javaHome = javaHomeDir.getAbsolutePath();
|
||||||
|
|
|
@ -144,7 +144,7 @@ public class ConfigureGradleWizardPage extends WizardPage {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
IProject project = projectPage.getGhidraModuleProject().getProject();
|
IProject project = projectPage.getGhidraModuleProject().getProject();
|
||||||
IFolder ghidraFolder = project.getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME);
|
IFolder ghidraFolder = project.getFolder(GhidraProjectUtils.GHIDRA_FOLDER_NAME);
|
||||||
File ghidraDir = ghidraFolder.getRawLocation().toFile();
|
File ghidraDir = ghidraFolder.getLocation().toFile();
|
||||||
try {
|
try {
|
||||||
GhidraApplicationLayout ghidraLayout = new GhidraApplicationLayout(ghidraDir);
|
GhidraApplicationLayout ghidraLayout = new GhidraApplicationLayout(ghidraDir);
|
||||||
ApplicationProperties props = ghidraLayout.getApplicationProperties();
|
ApplicationProperties props = ghidraLayout.getApplicationProperties();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue