1818import java .util .HashMap ;
1919import java .util .Map ;
2020import java .util .Set ;
21+ import java .util .UUID ;
2122import java .util .concurrent .ConcurrentHashMap ;
2223
2324import ghidra .framework .options .Options ;
@@ -39,14 +40,20 @@ public class ConfigManager implements OptionsChangeListener {
3940
4041 // Option names
4142 public static final String SERVER_PORT = "Server Port" ;
43+ public static final String SERVER_HOST = "Server Host" ;
4244 public static final String SERVER_ENABLED = "Server Enabled" ;
45+ public static final String API_KEY_ENABLED = "API Key Authentication Enabled" ;
46+ public static final String API_KEY = "API Key" ;
4347 public static final String DEBUG_MODE = "Debug Mode" ;
4448 public static final String MAX_DECOMPILER_SEARCH_FUNCTIONS = "Max Decompiler Search Functions" ;
4549 public static final String DECOMPILER_TIMEOUT_SECONDS = "Decompiler Timeout Seconds" ;
4650
4751 // Default values
4852 private static final int DEFAULT_PORT = 8080 ;
53+ private static final String DEFAULT_HOST = "127.0.0.1" ;
4954 private static final boolean DEFAULT_SERVER_ENABLED = true ;
55+ private static final boolean DEFAULT_API_KEY_ENABLED = false ;
56+ private static final String DEFAULT_API_KEY = "" ;
5057 private static final boolean DEFAULT_DEBUG_MODE = false ;
5158 private static final int DEFAULT_MAX_DECOMPILER_SEARCH_FUNCTIONS = 1000 ;
5259 private static final int DEFAULT_DECOMPILER_TIMEOUT_SECONDS = 10 ;
@@ -79,11 +86,27 @@ public ConfigManager(PluginTool tool) {
7986 */
8087 private void registerOptionsWithGhidra () {
8188 HelpLocation help = new HelpLocation ("ReVa" , "Configuration" );
82-
89+
8390 toolOptions .registerOption (SERVER_PORT , DEFAULT_PORT , help ,
8491 "Port number for the ReVa MCP server" );
92+ toolOptions .registerOption (SERVER_HOST , DEFAULT_HOST , help ,
93+ "Host interface for the ReVa MCP server (127.0.0.1 for localhost only, 0.0.0.0 for all interfaces)" );
8594 toolOptions .registerOption (SERVER_ENABLED , DEFAULT_SERVER_ENABLED , help ,
8695 "Whether the ReVa MCP server is enabled" );
96+ toolOptions .registerOption (API_KEY_ENABLED , DEFAULT_API_KEY_ENABLED , help ,
97+ "Whether API key authentication is required for MCP server access" );
98+
99+ // Only generate a new API key if one does not already exist
100+ String existingApiKey = toolOptions .getString (API_KEY , null );
101+ boolean isApiKeyMissing = (existingApiKey == null || existingApiKey .isEmpty ());
102+ String apiKeyToRegister = isApiKeyMissing ? generateDefaultApiKey () : existingApiKey ;
103+ toolOptions .registerOption (API_KEY , apiKeyToRegister , help ,
104+ "API key required for MCP server access when authentication is enabled" );
105+
106+ // Ensure the generated key is actually set in the options
107+ if (isApiKeyMissing ) {
108+ toolOptions .setString (API_KEY , apiKeyToRegister );
109+ }
87110 toolOptions .registerOption (DEBUG_MODE , DEFAULT_DEBUG_MODE , help ,
88111 "Whether debug mode is enabled" );
89112 toolOptions .registerOption (MAX_DECOMPILER_SEARCH_FUNCTIONS , DEFAULT_MAX_DECOMPILER_SEARCH_FUNCTIONS , help ,
@@ -98,7 +121,14 @@ private void registerOptionsWithGhidra() {
98121 protected void loadOptions () {
99122 // Cache the options
100123 cachedOptions .put (SERVER_PORT , toolOptions .getInt (SERVER_PORT , DEFAULT_PORT ));
124+ cachedOptions .put (SERVER_HOST , toolOptions .getString (SERVER_HOST , DEFAULT_HOST ));
101125 cachedOptions .put (SERVER_ENABLED , toolOptions .getBoolean (SERVER_ENABLED , DEFAULT_SERVER_ENABLED ));
126+ cachedOptions .put (API_KEY_ENABLED , toolOptions .getBoolean (API_KEY_ENABLED , DEFAULT_API_KEY_ENABLED ));
127+
128+ // Get the actual API key that was registered (could be generated or existing)
129+ String apiKey = toolOptions .getString (API_KEY , DEFAULT_API_KEY );
130+ cachedOptions .put (API_KEY , apiKey );
131+
102132 cachedOptions .put (DEBUG_MODE , toolOptions .getBoolean (DEBUG_MODE , DEFAULT_DEBUG_MODE ));
103133 cachedOptions .put (MAX_DECOMPILER_SEARCH_FUNCTIONS ,
104134 toolOptions .getInt (MAX_DECOMPILER_SEARCH_FUNCTIONS , DEFAULT_MAX_DECOMPILER_SEARCH_FUNCTIONS ));
@@ -179,6 +209,23 @@ public void setServerPort(int port) {
179209 // optionsChanged() will be called automatically
180210 }
181211
212+ /**
213+ * Get the server host
214+ * @return The configured server host
215+ */
216+ public String getServerHost () {
217+ return (String ) cachedOptions .getOrDefault (SERVER_HOST , DEFAULT_HOST );
218+ }
219+
220+ /**
221+ * Set the server host
222+ * @param host The host interface to bind to
223+ */
224+ public void setServerHost (String host ) {
225+ toolOptions .setString (SERVER_HOST , host );
226+ // optionsChanged() will be called automatically
227+ }
228+
182229 /**
183230 * Check if the server is enabled
184231 * @return True if the server is enabled
@@ -196,6 +243,40 @@ public void setServerEnabled(boolean enabled) {
196243 // optionsChanged() will be called automatically
197244 }
198245
246+ /**
247+ * Check if API key authentication is enabled
248+ * @return True if API key authentication is enabled
249+ */
250+ public boolean isApiKeyEnabled () {
251+ return (Boolean ) cachedOptions .getOrDefault (API_KEY_ENABLED , DEFAULT_API_KEY_ENABLED );
252+ }
253+
254+ /**
255+ * Set whether API key authentication is enabled
256+ * @param enabled True to enable API key authentication
257+ */
258+ public void setApiKeyEnabled (boolean enabled ) {
259+ toolOptions .setBoolean (API_KEY_ENABLED , enabled );
260+ // optionsChanged() will be called automatically
261+ }
262+
263+ /**
264+ * Get the API key
265+ * @return The configured API key
266+ */
267+ public String getApiKey () {
268+ return (String ) cachedOptions .getOrDefault (API_KEY , DEFAULT_API_KEY );
269+ }
270+
271+ /**
272+ * Set the API key
273+ * @param apiKey The API key to use
274+ */
275+ public void setApiKey (String apiKey ) {
276+ toolOptions .setString (API_KEY , apiKey );
277+ // optionsChanged() will be called automatically
278+ }
279+
199280 /**
200281 * Check if debug mode is enabled
201282 * @return True if debug mode is enabled
@@ -247,6 +328,14 @@ public void setDecompilerTimeoutSeconds(int timeoutSeconds) {
247328 // optionsChanged() will be called automatically
248329 }
249330
331+ /**
332+ * Generate a default API key with ReVa-UUID format
333+ * @return A new API key in the format "ReVa-{uuid}"
334+ */
335+ private String generateDefaultApiKey () {
336+ return "ReVa-" + UUID .randomUUID ().toString ();
337+ }
338+
250339 /**
251340 * Clean up when the plugin is disposed
252341 */
0 commit comments