From f3d634968ad75930ac0bfde5e26fbf989dce1061 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 09:50:14 -0400 Subject: [PATCH 1/2] GP-0 Corrected server test utility to comply with Ghidra Server ACL restrictions from GP-7049 --- .../ghidra/server/remote/ServerTestUtil.java | 84 ++++++++++--------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java index 0f4bb42519..3e331d7e04 100644 --- a/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java +++ b/Ghidra/Test/IntegrationTest/src/test.slow/java/ghidra/server/remote/ServerTestUtil.java @@ -823,13 +823,45 @@ public class ServerTestUtil { } /** - * Create and populate server test repositories "Test" and "Test1" with the specified - * users added. The ADMIN_USER "test" is added by default. - * @param dirPath server root - * @param users optional inclusion of USER_A and/or USER_B to be added with no authentication required + * Add a new user to an existing local Ghidra Test Server using the ServerAdmin class. + * @param serverRoot server's repositories root directory + * @param name user name + * @param dn DN or null (applies to PKI authentication only) * @throws Exception */ - public static void createPopulatedTestServer(String dirPath, String... users) throws Exception { + public static void addUser(File serverRoot, String name, String dn) throws Exception { + ServerAdmin serverAdmin = new ServerAdmin(); + if (dn != null) { + serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-dn", name, dn }); + } + else { + serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-add", name }); + } + } + + /** + * Grant an existing user access to a repository for an existing local Ghidra Test Server + * using the ServerAdmin class. + * @param serverRoot server's repositories root directory + * @param name user name + * @param repoName existing repository name + * @param access an access string: "+r", "+w", "+a" + * @throws Exception + */ + public static void setUserAccess(File serverRoot, String name, String repoName, String access) + throws Exception { + ServerAdmin serverAdmin = new ServerAdmin(); + serverAdmin.execute( + new String[] { serverRoot.getAbsolutePath(), "-grant", name, access, repoName }); + } + + /** + * Create and populate server test repositories "Test" and "Test1". The ADMIN_USER "test" + * is added by default to both repositories. + * @param dirPath server root + * @throws Exception + */ + public static void createPopulatedTestServer(String dirPath) throws Exception { Msg.info(ServerTestUtil.class, "Constructing Ghidra Server for testing: " + dirPath); @@ -837,16 +869,12 @@ public class ServerTestUtil { FileUtilities.deleteDir(rootDir); FileUtilities.mkdirs(rootDir); - String[] userArray = new String[users.length + 1]; - userArray[0] = ADMIN_USER; - System.arraycopy(users, 0, userArray, 1, users.length); - createUsers(dirPath, userArray); + createUsers(dirPath, new String[] { ADMIN_USER }); String keys[] = SSHKeyUtil.generateSSHRSAKeys(); addSSHKeys(dirPath, keys[0], "test.key", keys[1], "test.pub"); - LocalFileSystem repoFilesystem = createRepository(dirPath, "Test", ADMIN_USER + "=ADMIN", - USER_A + "=READ_ONLY", USER_B + "=WRITE"); + LocalFileSystem repoFilesystem = createRepository(dirPath, "Test", ADMIN_USER + "=ADMIN"); try { createRepositoryItem(repoFilesystem, "foo", "/", 0); createRepositoryItem(repoFilesystem, "notepad", "/", 0); @@ -857,7 +885,7 @@ public class ServerTestUtil { } repoFilesystem = createRepository(dirPath, "Test1", "=ANONYMOUS_ALLOWED", - ADMIN_USER + "=ADMIN", USER_A + "=WRITE"); + ADMIN_USER + "=ADMIN"); try { createRepositoryItem(repoFilesystem, "foo1", "/", 0); createRepositoryItem(repoFilesystem, "notepad1", "/", 0); @@ -870,17 +898,16 @@ public class ServerTestUtil { } /** - * Create and populate server test repositories "Test" and "Test1" with the specified - * users added. The ADMIN_USER "test" is added by default. + * Create and populate server test repositories "Test" and "Test1". The ADMIN_USER "test" + * is added by default to both repositories. * @param dirPath server root * @param repoName repository name * @param contentProvider repository content provider callback * (use {@link #createRepositoryItem(LocalFileSystem, String, String, Program)} to add content. - * @param users optional inclusion of USER_A and/or USER_B to be added with no authentication required * @throws Exception */ public static void createPopulatedTestServer(String dirPath, String repoName, - Consumer contentProvider, String... users) throws Exception { + Consumer contentProvider) throws Exception { Msg.info(ServerTestUtil.class, "Constructing Ghidra Server for testing: " + dirPath); @@ -888,16 +915,12 @@ public class ServerTestUtil { FileUtilities.deleteDir(rootDir); FileUtilities.mkdirs(rootDir); - String[] userArray = new String[users.length + 1]; - userArray[0] = ADMIN_USER; - System.arraycopy(users, 0, userArray, 1, users.length); - createUsers(dirPath, userArray); + createUsers(dirPath, new String[] { ADMIN_USER }); String keys[] = SSHKeyUtil.generateSSHRSAKeys(); addSSHKeys(dirPath, keys[0], "test.key", keys[1], "test.pub"); - LocalFileSystem repoFilesystem = createRepository(dirPath, repoName, ADMIN_USER + "=ADMIN", - USER_A + "=READ_ONLY", USER_B + "=WRITE"); + LocalFileSystem repoFilesystem = createRepository(dirPath, repoName, ADMIN_USER + "=ADMIN"); try { contentProvider.accept(repoFilesystem); } @@ -987,21 +1010,4 @@ public class ServerTestUtil { return altNames; } - /** - * Add PKI user to server - * @param serverRoot - * @param userName - * @param dn - * @throws Exception - */ - public static void addPKIUser(File serverRoot, String userName, String dn) throws Exception { - ServerAdmin serverAdmin = new ServerAdmin(); - if (dn != null) { - serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-dn", userName, dn }); - } - else { - serverAdmin.execute(new String[] { serverRoot.getAbsolutePath(), "-add", userName }); - } - } - } From 08a1765da8616b4d90ad5b7d0a0233acc15d64e6 Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Jul 2026 10:38:54 -0400 Subject: [PATCH 2/2] GP-1 Revised server command processing to address testing issue --- .../main/java/ghidra/server/CommandProcessor.java | 14 +++++++------- .../main/java/ghidra/server/CommandWatcher.java | 6 +++--- .../src/main/java/ghidra/server/ServerAdmin.java | 6 +----- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java index 93c9f41428..edff61a2f8 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandProcessor.java @@ -224,12 +224,12 @@ public class CommandProcessor { return -1; } - static File getCommandDir(File serverRootDir) { - return new File(serverRootDir, ADMIN_CMD_DIR); - } - - static File getOrCreateCommandDir(RepositoryManager repositoryMgr) { - File cmdDir = getCommandDir(repositoryMgr.getRootDir()); + static File getOrCreateCommandDir(File serverRootDir) { + if (!serverRootDir.isDirectory() || !serverRootDir.canWrite()) { + System.err.println("Insufficient privilege or server not started!"); + System.exit(-1); + } + File cmdDir = new File(serverRootDir, ADMIN_CMD_DIR); if (!cmdDir.exists()) { // ensure process owner creates queued command directory cmdDir.mkdir(); @@ -243,7 +243,7 @@ public class CommandProcessor { * @throws IOException */ static void processCommands(RepositoryManager repositoryMgr) throws IOException { - File cmdDir = getOrCreateCommandDir(repositoryMgr); + File cmdDir = getOrCreateCommandDir(repositoryMgr.getRootDir()); File[] files = cmdDir.listFiles(CMD_FILE_FILTER); if (files == null) { log.error("Failed to access command queue " + cmdDir.getAbsolutePath() + diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java index e3b4ffbe1c..fd235b23ba 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/CommandWatcher.java @@ -4,9 +4,9 @@ * 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. @@ -37,7 +37,7 @@ public class CommandWatcher implements Runnable { this.repositoryMgr = repositoryMgr; watcher = FileSystems.getDefault().newWatchService(); - cmdDirPath = CommandProcessor.getOrCreateCommandDir(repositoryMgr).toPath(); + cmdDirPath = CommandProcessor.getOrCreateCommandDir(repositoryMgr.getRootDir()).toPath(); cmdDirPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); } diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java index 2edbc46cf0..fe0a217f84 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/ServerAdmin.java @@ -111,11 +111,7 @@ public class ServerAdmin implements GhidraLaunchable { System.exit(-1); } - File cmdDir = CommandProcessor.getCommandDir(serverRootDir); - if (!cmdDir.isDirectory() || !cmdDir.canWrite()) { - System.err.println("Insufficient privilege or server not started!"); - System.exit(-1); - } + File cmdDir = CommandProcessor.getOrCreateCommandDir(serverRootDir); // Process command line boolean listRepositories = false;