Skip to content

Commit

Permalink
Change: make async the methods for preference handling. (#1572)
Browse files Browse the repository at this point in the history
Also, improve the creating the RedisHelper, since at this point the nvti cache and a main kb for the scan should have been created.

Usage example. (Needs a running redis instance with an up-to-date nvticache)

```

```use std::sync::{Arc, Mutex};

use models::{AliveTestMethods, Credential, PortRange, Port, Scan, Parameter};
use openvas::{pref_handler::PreferenceHandler, openvas_redis::RedisHelper};
use redis_storage::{NameSpaceSelector, RedisCtx};

async fn main() -> Result<(), std::fmt::Error> {

    // Create an scan config
    let mut scan = Scan::default();
    scan.scan_id = Some("123-456".to_string());
    scan.target.alive_test_methods = vec![AliveTestMethods::Icmp, AliveTestMethods::TcpSyn];
    scan.target.credentials = vec![Credential {
        service: models::Service::SSH,
        port: Some(22),
        credential_type: models::CredentialType::UP {
            username: "user".to_string(),
            password: "pass".to_string(),
            privilege_credential: None,
        },
    }];
    scan.vts.push(models::VT {
        oid: "1.3.6.1.4.1.25623.1.0.112771".to_string(),
        parameters: vec![Parameter {
            id: 1,
            value: "llala".to_string()

        }]
    });
    scan.target.excluded_hosts = vec!["127.0.0.1".to_string()];
    scan.target.hosts = vec!["127.0.0.2".to_string()];
    scan.target.ports = vec![Port {
        protocol: Some(models::Protocol::TCP),
        range: vec![
            PortRange {
                start: 22,
                end: Some(25),
            },
            PortRange {
                start: 80,
                end: None,
            },
        ],
    }];

    let redis_url = "unix:///run/redis-openvas/redis.sock";
    // In this example, a fix db is taken,but the next free can be taken, using the name space selector NameSpaceSelector::Free
    let mut rctx = RedisCtx::open(redis_url, &[NameSpaceSelector::Fix(6)]).unwrap();
    rctx.delete_namespace().unwrap();
    // Create a redis connection to the nvticache, and a connection to the mainkb().
    let cache = RedisCtx::open(redis_url, &[NameSpaceSelector::Key("nvticache")]).unwrap();

    // New redis helper with access to the main kb for storing the preferences, and access to the nvticache
    // for getting info to build preferences.
    let rc = RedisHelper::<RedisCtx>::init(Arc::new(Mutex::new(cache)),Arc::new(Mutex::new(rctx))).unwrap();

    let mut p = PreferenceHandler::new(scan, rc);
    Ok(p.prepare_preferences_for_openvas().await.expect("aaa"))

}
  • Loading branch information
jjnicola authored Feb 21, 2024
1 parent d37e426 commit c741857
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 57 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/openvasctl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ models = { path = "../models" }
redis = "0.22.0"
redis-storage = { version = "0.1.0", path = "../redis-storage" }
storage = { version = "0.1.0", path = "../storage" }
tokio = { version = "1.36.0", features = ["full"] }
tracing = "0.1.40"
22 changes: 9 additions & 13 deletions rust/openvasctl/src/openvas_redis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use redis_storage::{
dberror::{DbError, RedisStorageResult},
NameSpaceSelector, RedisCtx, RedisGetNvt, RedisWrapper,
RedisCtx, RedisGetNvt, RedisWrapper,
};
use std::{
collections::HashMap,
Expand All @@ -27,18 +27,14 @@ where
{
/// Initialize a RedisHelper struct with the connection to access the NVT cache
/// and a empty task knowledge base to store the scan configuration to be sent to openvas.
pub fn init(
redis_url: &str,
selector: &[NameSpaceSelector],
) -> RedisStorageResult<RedisHelper<RedisCtx>> {
let mut rctx = RedisCtx::open(redis_url, selector)?;
rctx.delete_namespace()?;
let cache = RedisCtx::open(redis_url, selector)?;

Ok(RedisHelper::<RedisCtx> {
cache: Arc::new(Mutex::new(cache)),
task_kb: Arc::new(Mutex::new(rctx)),
})
pub fn new(
nvti_cache: Arc<Mutex<RedisCtx>>,
kb_cache: Arc<Mutex<RedisCtx>>,
) -> RedisHelper<RedisCtx> {
RedisHelper::<RedisCtx> {
cache: nvti_cache,
task_kb: kb_cache,
}
}
}

Expand Down
90 changes: 46 additions & 44 deletions rust/openvasctl/src/pref_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,26 @@ where
}
}

pub fn prepare_preferences_for_openvas(&mut self) -> RedisStorageResult<()> {
self.prepare_scan_id_for_openvas()?;
self.prepare_target_for_openvas()?;
self.prepare_ports_for_openvas()?;
self.prepare_credentials_for_openvas()?;
self.prepare_plugins_for_openvas()?;
self.prepare_main_kbindex_for_openvas()?;
self.prepare_host_options_for_openvas()?;
self.prepare_scan_params_for_openvas()?;
self.prepare_reverse_lookup_opt_for_openvas()?;
self.prepare_alive_test_option_for_openvas()?;
pub async fn prepare_preferences_for_openvas(&mut self) -> RedisStorageResult<()> {
self.prepare_scan_id_for_openvas().await?;
self.prepare_target_for_openvas().await?;
self.prepare_ports_for_openvas().await?;
self.prepare_credentials_for_openvas().await?;
self.prepare_plugins_for_openvas().await?;
self.prepare_main_kbindex_for_openvas().await?;
self.prepare_host_options_for_openvas().await?;
self.prepare_scan_params_for_openvas().await?;
self.prepare_reverse_lookup_opt_for_openvas().await?;
self.prepare_alive_test_option_for_openvas().await?;

// VT preferences are stored after all preferences have been processed,
// since alive tests preferences have to be able to overwrite default
// preferences of ping_host.nasl for the classic method.
self.prepare_nvt_preferences()?;
self.prepare_boreas_alive_test()
self.prepare_nvt_preferences().await?;
self.prepare_boreas_alive_test().await
}

fn prepare_main_kbindex_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_main_kbindex_for_openvas(&mut self) -> RedisStorageResult<()> {
self.redis_connector.push_kb_item(
format!(
"internal/{}/scanprefs",
Expand All @@ -76,7 +76,7 @@ where
Ok(())
}

fn prepare_scan_id_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_scan_id_for_openvas(&mut self) -> RedisStorageResult<()> {
self.redis_connector.push_kb_item(
format!(
"internal/{}",
Expand All @@ -93,7 +93,7 @@ where
Ok(())
}

fn process_vts(&self, vts: &Vec<VT>) -> (Vec<String>, HashMap<String, String>) {
async fn process_vts(&self, vts: &Vec<VT>) -> (Vec<String>, HashMap<String, String>) {
let mut vts_list: Vec<String> = vec![];
let mut pref_list: HashMap<String, String> = HashMap::new();

Expand All @@ -103,11 +103,12 @@ where
vts_list.push(vt.oid.clone());

// prepare vt preferences
for pref in vt.parameters.iter() {
for pref in &vt.parameters {
let (prefid, class, name, value): (String, String, String, String) = nvt
.preferences
.get(pref.id as usize)
.expect("Valid pref id")
.iter()
.find(|p| p.id.unwrap() as u16 == pref.id)
.unwrap()
.into();

let value_aux: String = if class == *"checkbox" {
Expand All @@ -126,18 +127,17 @@ where
continue;
}
}

(vts_list, pref_list)
}

fn prepare_plugins_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_plugins_for_openvas(&mut self) -> RedisStorageResult<()> {
let nvts = &self.scan_config.vts;

if nvts.is_empty() {
return Ok(());
}

let (nvts, prefs) = self.process_vts(nvts);
let (nvts, prefs) = self.process_vts(nvts).await;
// update list of preferences
self.nvt_params.extend(prefs);

Expand All @@ -152,14 +152,16 @@ where
)
}

fn prepare_nvt_preferences(&mut self) -> RedisStorageResult<()> {
async fn prepare_nvt_preferences(&mut self) -> RedisStorageResult<()> {
let mut items: Vec<String> = vec![];
for (k, v) in self.nvt_params.iter() {
items.push(format!("{}|||{}", k, v))
}

if items.is_empty() {
return Ok(());
}

let _ = self
.nvt_params
.clone()
.into_iter()
.map(|(k, v)| items.push(format!("{}|||{}", k, v)));
self.redis_connector.push_kb_item(
format!(
"internal/{}/scanprefs",
Expand All @@ -170,7 +172,7 @@ where
)
}

fn prepare_alive_test_option_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_alive_test_option_for_openvas(&mut self) -> RedisStorageResult<()> {
let mut prefs: HashMap<String, String> = HashMap::new();
let mut alive_test = ALIVE_TEST_SCAN_CONFIG_DEFAULT;
let mut value: &str = "no";
Expand Down Expand Up @@ -251,7 +253,7 @@ where
Ok(())
}

fn prepare_boreas_alive_test(&mut self) -> RedisStorageResult<()> {
async fn prepare_boreas_alive_test(&mut self) -> RedisStorageResult<()> {
// Check "test_alive_hosts_only" configuration from openvas.conf
// If set no, boreas is disabled and alive_host.nasl is used instead.
if let Ok(config) = cmd::read_openvas_config() {
Expand Down Expand Up @@ -306,7 +308,7 @@ where
Ok(())
}

fn prepare_reverse_lookup_opt_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_reverse_lookup_opt_for_openvas(&mut self) -> RedisStorageResult<()> {
let mut lookup_opts: Vec<String> = vec![];

if let Some(reverse_lookup_only) = self.scan_config.target.reverse_lookup_only {
Expand Down Expand Up @@ -335,7 +337,7 @@ where
)
}

fn prepare_target_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_target_for_openvas(&mut self) -> RedisStorageResult<()> {
let target = self.scan_config.target.hosts.join(",");
self.redis_connector.push_kb_item(
format!(
Expand All @@ -347,7 +349,7 @@ where
)
}

fn prepare_ports_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_ports_for_openvas(&mut self) -> RedisStorageResult<()> {
let ports = self.scan_config.target.ports.clone();
if let Some(ports) = ports_to_openvas_port_list(ports) {
self.redis_connector.push_kb_item(
Expand All @@ -363,7 +365,7 @@ where
Ok(())
}

fn prepare_host_options_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_host_options_for_openvas(&mut self) -> RedisStorageResult<()> {
let excluded_hosts = self.scan_config.target.excluded_hosts.join(",");
if excluded_hosts.is_empty() {
return Ok(());
Expand All @@ -379,7 +381,7 @@ where
)
}

fn prepare_scan_params_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_scan_params_for_openvas(&mut self) -> RedisStorageResult<()> {
let options = self
.scan_config
.scanner_preferences
Expand All @@ -401,7 +403,7 @@ where
options,
)
}
fn prepare_credentials_for_openvas(&mut self) -> RedisStorageResult<()> {
async fn prepare_credentials_for_openvas(&mut self) -> RedisStorageResult<()> {
let credentials = self.scan_config.target.credentials.clone();

let mut credential_preferences: Vec<String> = vec![];
Expand Down Expand Up @@ -571,8 +573,8 @@ mod tests {
use super::PreferenceHandler;
use crate::openvas_redis::{FakeRedis, KbAccess};

#[test]
fn test_prefs() {
#[tokio::test]
async fn test_prefs() {
let mut scan = Scan::default();
scan.scan_id = Some("123-456".to_string());
scan.target.alive_test_methods = vec![AliveTestMethods::Icmp, AliveTestMethods::TcpSyn];
Expand Down Expand Up @@ -606,28 +608,28 @@ mod tests {

let mut prefh = PreferenceHandler::new(scan, rc);
assert_eq!(prefh.redis_connector.kb_id().unwrap(), 3);
assert!(prefh.prepare_scan_id_for_openvas().is_ok());
assert!(prefh.prepare_scan_id_for_openvas().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/scanid", "123-456"));
assert!(prefh.redis_connector.item_exists("internal/123-456", "new"));

assert!(prefh.prepare_main_kbindex_for_openvas().is_ok());
assert!(prefh.prepare_main_kbindex_for_openvas().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/123-456/scanprefs", "ov_maindbid|||3"));

assert!(prefh.prepare_boreas_alive_test().is_ok());
assert!(prefh.prepare_boreas_alive_test().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/123-456/scanprefs", "ALIVE_TEST|||3"));

assert!(prefh.prepare_host_options_for_openvas().is_ok());
assert!(prefh.prepare_host_options_for_openvas().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/123-456/scanprefs", "excluded_hosts|||127.0.0.1"));

assert!(prefh.prepare_credentials_for_openvas().is_ok());
assert!(prefh.prepare_credentials_for_openvas().await.is_ok());
assert!(prefh.redis_connector.item_exists(
"internal/123-456/scanprefs",
"1.3.6.1.4.1.25623.1.0.103591:3:password:SSH password (unsafe!):|||pass"
Expand All @@ -637,7 +639,7 @@ mod tests {
"1.3.6.1.4.1.25623.1.0.103591:1:entry:SSH login name:|||user"
));

assert!(prefh.prepare_ports_for_openvas().is_ok());
assert!(prefh.prepare_ports_for_openvas().await.is_ok());
assert!(prefh
.redis_connector
.item_exists("internal/123-456/scanprefs", "PORTS|||tcp:22-25,80,"));
Expand Down

0 comments on commit c741857

Please sign in to comment.