From b971dcae195289660edc88246305fc7c6251f406 Mon Sep 17 00:00:00 2001 From: Valentin Obst Date: Tue, 10 Dec 2024 12:55:53 +0100 Subject: [PATCH] lib/utils: fall back to env for configs and Ghidra plugins If config files or Ghidra plugins are not found in the respective project directories, fall back to env vars that contain an alternative search directory. --- src/cwe_checker_lib/src/utils/ghidra.rs | 2 +- src/cwe_checker_lib/src/utils/mod.rs | 76 +++++++++++++++++++++---- 2 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/cwe_checker_lib/src/utils/ghidra.rs b/src/cwe_checker_lib/src/utils/ghidra.rs index da7441f16..166fd9902 100644 --- a/src/cwe_checker_lib/src/utils/ghidra.rs +++ b/src/cwe_checker_lib/src/utils/ghidra.rs @@ -183,7 +183,7 @@ fn generate_ghidra_call_command( .ok_or_else(|| anyhow!("Invalid file name"))? .to_string_lossy() .to_string(); - let ghidra_plugin_path = get_ghidra_plugin_path("p_code_extractor"); + let ghidra_plugin_path = get_ghidra_plugin_path("p_code_extractor")?; let mut ghidra_command = Command::new(headless_path); ghidra_command diff --git a/src/cwe_checker_lib/src/utils/mod.rs b/src/cwe_checker_lib/src/utils/mod.rs index 93beae261..f142781be 100644 --- a/src/cwe_checker_lib/src/utils/mod.rs +++ b/src/cwe_checker_lib/src/utils/mod.rs @@ -10,21 +10,77 @@ pub mod symbol_utils; use crate::prelude::*; +use std::{env, fs, path}; + +use anyhow::bail; + +const ENV_CWE_CHECKER_CONFIGS_PATH: &str = "CWE_CHECKER_CONFIGS_PATH"; +const ENV_CWE_CHECKER_GHIDRA_PLUGINS_PATH: &str = "CWE_CHECKER_GHIDRA_PLUGINS_PATH"; + /// Get the contents of a configuration file. +/// +/// We first search the file in our config directory. Then, we fall back to +/// the CWE_CHECKER_CONFIG environment variable. pub fn read_config_file(filename: &str) -> Result { - let project_dirs = directories::ProjectDirs::from("", "", "cwe_checker") - .context("Could not discern location of configuration files.")?; + let config_path = if let Some(config_path) = get_config_path_from_project_dir(filename) { + config_path + } else if let Some(config_path) = get_path_from_env(ENV_CWE_CHECKER_CONFIGS_PATH, filename) { + config_path + } else { + bail!("Unable to find configuration file: {}.", filename) + }; + let config_file = fs::read_to_string(config_path) + .context(format!("Could not read configuration file: {}", filename))?; + Ok(serde_json::from_str(&config_file)?) +} + +fn get_config_path_from_project_dir(filename: &str) -> Option { + let project_dirs = directories::ProjectDirs::from("", "", "cwe_checker")?; let config_dir = project_dirs.config_dir(); let config_path = config_dir.join(filename); - let config_file = - std::fs::read_to_string(config_path).context("Could not read configuration file")?; - Ok(serde_json::from_str(&config_file)?) + + if config_path.exists() { + Some(config_path) + } else { + None + } +} + +/// Get the path to a Ghidra plugin that is bundled with the cwe_checker. +/// +/// We first search the plugin in our data directory, then we fall back to +/// the CWE_CHECKER_GHIDRA_PLUGIN_PATH environment variable. +pub fn get_ghidra_plugin_path(plugin_name: &str) -> Result { + if let Some(ghidra_plugin_path) = get_ghidra_plugin_path_from_project_dirs(plugin_name) { + Ok(ghidra_plugin_path) + } else if let Some(ghidra_plugin_path) = + get_path_from_env(ENV_CWE_CHECKER_GHIDRA_PLUGINS_PATH, plugin_name) + { + Ok(ghidra_plugin_path) + } else { + bail!("Unable to find Ghidra plugin: {}", plugin_name) + } } -/// Get the folder path to a Ghidra plugin bundled with the cwe_checker. -pub fn get_ghidra_plugin_path(plugin_name: &str) -> std::path::PathBuf { - let project_dirs = directories::ProjectDirs::from("", "", "cwe_checker") - .expect("Could not discern location of data directory."); +fn get_ghidra_plugin_path_from_project_dirs(plugin_name: &str) -> Option { + let project_dirs = directories::ProjectDirs::from("", "", "cwe_checker")?; let data_dir = project_dirs.data_dir(); - data_dir.join("ghidra").join(plugin_name) + let plugin_path = data_dir.join("ghidra").join(plugin_name); + + if plugin_path.exists() { + Some(plugin_path) + } else { + None + } +} + +fn get_path_from_env(var: &str, filename: &str) -> Option { + let val = env::var(var).ok()?; + let path = path::PathBuf::from(val).join(filename); + + if path.exists() { + Some(path) + } else { + None + } }