Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement find_service #1802

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
12 changes: 12 additions & 0 deletions rust/crates/nasl-function-proc-macro/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ impl<'a> ArgsStruct<'a> {
_register
}
},
ArgKind::NaslSockets(arg) => {
if arg.mutable {
quote! {
&mut *_context.write_sockets().await
}
}
else {
quote! {
&*_context.read_sockets().await
}
}
},
ArgKind::PositionalIterator(arg) => {
let position = arg.position;
quote! {
Expand Down
7 changes: 6 additions & 1 deletion rust/crates/nasl-function-proc-macro/src/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use std::collections::HashSet;

use crate::error::{Error, ErrorKind, Result};
use crate::types::*;
use crate::utils::{get_subty_if_name_is, ty_is_context, ty_is_register, ty_name_is};
use crate::utils::{
get_subty_if_name_is, ty_is_context, ty_is_nasl_sockets, ty_is_register, ty_name_is,
};
use syn::punctuated::Punctuated;
use syn::token::Comma;
use syn::{parenthesized, parse::Parse, spanned::Spanned, FnArg, Ident, ItemFn, Token, Type};
Expand Down Expand Up @@ -43,6 +45,9 @@ impl Attrs {
if ty_is_register(ty) {
return ArgKind::Register;
}
if let Some(mutable) = ty_is_nasl_sockets(ty) {
return ArgKind::NaslSockets(NaslSocketsArg { mutable });
}
if ty_name_is(ty, "Positionals") {
return ArgKind::PositionalIterator(PositionalsArg { position });
}
Expand Down
16 changes: 11 additions & 5 deletions rust/crates/nasl-function-proc-macro/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ pub struct Arg<'a> {
pub mutable: bool,
}

pub struct NaslSocketsArg {
pub mutable: bool,
}

pub enum ArgKind {
Positional(PositionalArg),
Named(NamedArg),
MaybeNamed(PositionalArg, NamedArg),
Context,
Register,
NaslSockets(NaslSocketsArg),
PositionalIterator(PositionalsArg),
CheckedPositionalIterator(PositionalsArg),
}
Expand All @@ -66,11 +71,12 @@ impl ArgKind {
match self {
ArgKind::Context => 0,
ArgKind::Register => 0,
ArgKind::Positional(_) => 1,
ArgKind::MaybeNamed(_, _) => 2,
ArgKind::Named(_) => 3,
ArgKind::PositionalIterator(_) => 4,
ArgKind::CheckedPositionalIterator(_) => 4,
ArgKind::NaslSockets(_) => 1,
ArgKind::Positional(_) => 2,
ArgKind::MaybeNamed(_, _) => 3,
ArgKind::Named(_) => 4,
ArgKind::PositionalIterator(_) => 5,
ArgKind::CheckedPositionalIterator(_) => 5,
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions rust/crates/nasl-function-proc-macro/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ pub fn ty_is_register(ty: &Type) -> bool {
}
}

pub fn ty_is_nasl_sockets(ty: &Type) -> Option<bool> {
if let Type::Reference(TypeReference {
elem, mutability, ..
}) = ty
{
if ty_name_is(elem, "NaslSockets") {
Some(mutability.is_some())
} else {
None
}
} else {
None
}
}

pub fn get_subty_if_name_is<'a>(ty: &'a Type, name: &str) -> Option<&'a Type> {
get_last_segment(ty)
.filter(|segment| segment.ident == name)
Expand Down
13 changes: 13 additions & 0 deletions rust/src/models/port.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::iter::IntoIterator;
// SPDX-FileCopyrightText: 2023 Greenbone AG
//
// SPDX-License-Identifier: GPL-2.0-or-later WITH x11vnc-openssl-exception
Expand Down Expand Up @@ -42,6 +43,18 @@ pub struct PortRange {
pub end: Option<usize>,
}

impl IntoIterator for PortRange {
type Item = u16;

type IntoIter = std::ops::Range<u16>;

fn into_iter(self) -> Self::IntoIter {
let start = self.start as u16;
let end = self.end.map(|end| end as u16).unwrap_or(u16::MAX);
(start..end).into_iter()
}
}

impl Display for PortRange {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.end {
Expand Down
4 changes: 4 additions & 0 deletions rust/src/nasl/builtin/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::nasl::utils::error::FnErrorKind;

use super::cert::CertError;
use super::cryptographic::CryptographicError;
use super::find_service::FindServiceError;
use super::host::HostError;
use super::http::HttpError;
use super::isotime::IsotimeError;
Expand Down Expand Up @@ -43,6 +44,8 @@ pub enum BuiltinError {
Cert(CertError),
#[error("{0}")]
Sys(SysError),
#[error("{0}")]
FindService(FindServiceError),
#[cfg(feature = "nasl-builtin-raw-ip")]
#[error("{0}")]
RawIp(super::raw_ip::RawIpError),
Expand Down Expand Up @@ -89,6 +92,7 @@ builtin_error_variant!(KBError, KB);
builtin_error_variant!(HostError, Host);
builtin_error_variant!(CertError, Cert);
builtin_error_variant!(SysError, Sys);
builtin_error_variant!(FindServiceError, FindService);

#[cfg(feature = "nasl-builtin-raw-ip")]
builtin_error_variant!(super::raw_ip::RawIpError, RawIp);
92 changes: 92 additions & 0 deletions rust/src/nasl/builtin/find_service/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-FileCopyrightText: 2023 Greenbone AG
//
// SPDX-License-Identifier: GPL-2.0-or-later WITH x11vnc-openssl-exception

use std::{io, net::IpAddr, time::Duration};

use thiserror::Error;

use crate::nasl::prelude::*;

use super::network::socket::{make_tcp_socket, SocketError};

const TIMEOUT_MILLIS: u64 = 10000;

#[derive(Debug, Error)]
pub enum FindServiceError {
#[error("{0}")]
SocketError(#[from] SocketError),
}

struct Service {
name: String,
generate_result: GenerateResult,
save_banner: bool,
special_behavior: Option<SpecialBehavior>,
}

enum GenerateResult {
No,
Yes { is_vulnerability: bool },
}

enum SpecialBehavior {
// TODO fill this in for services
}

enum ReadResult {
Data(String),
Timeout,
}

enum ScanPortResult {
Service(Service),
Timeout,
}

async fn read_from_tcp_at_port(target: IpAddr, port: u16) -> Result<ReadResult, FindServiceError> {
let mut socket = make_tcp_socket(target, port, 0)?;
let mut buf: &mut [u8] = &mut [0; 100];
let result = socket.read_with_timeout(buf, Duration::from_millis(TIMEOUT_MILLIS));
match result {
Ok(pos) => Ok(ReadResult::Data(
String::from_utf8(buf[0..pos].to_vec()).unwrap(),
)),
Err(e) if e.kind() == io::ErrorKind::TimedOut => Ok(ReadResult::Timeout),
Err(e) => Err(SocketError::IO(e).into()),
}
}

async fn scan_port(target: IpAddr, port: u16) -> Result<ScanPortResult, FindServiceError> {
let result = read_from_tcp_at_port(target, port).await?;
match result {
ReadResult::Data(data) => Ok(ScanPortResult::Service(find_service(data))),
ReadResult::Timeout => Ok(ScanPortResult::Timeout),
}
}

fn find_service(data: String) -> Service {
todo!()
}

#[nasl_function]
async fn plugin_run_find_service(context: &Context<'_>) -> () {
for port in context.port_range() {
match scan_port(context.target_ip(), port).await {
Ok(_) => {}
Err(e) => {}
}
}
}

#[derive(Default)]
pub struct FindService {
services: Vec<Service>,
}

function_set! {
FindService,
(
plugin_run_find_service
)
}
8 changes: 4 additions & 4 deletions rust/src/nasl/builtin/host/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn get_host_names(context: &Context) -> Result<NaslValue, FnError> {
if !hns.is_empty() {
let hns = hns
.into_iter()
.map(|(h, _s)| NaslValue::String(h))
.map(|vhost| NaslValue::String(vhost.hostname().to_string()))
.collect::<Vec<_>>();
return Ok(NaslValue::Array(hns));
};
Expand Down Expand Up @@ -91,7 +91,7 @@ pub fn get_host_name(_register: &Register, context: &Context) -> Result<NaslValu
let vh = context.target_vhosts();
let v = if !vh.is_empty() {
vh.iter()
.map(|(v, _s)| NaslValue::String(v.to_string()))
.map(|vhost| NaslValue::String(vhost.hostname().to_string()))
.collect::<Vec<_>>()
} else {
vec![]
Expand Down Expand Up @@ -122,8 +122,8 @@ pub fn get_host_name(_register: &Register, context: &Context) -> Result<NaslValu
pub fn get_host_name_source(context: &Context, hostname: Hostname) -> String {
let vh = context.target_vhosts();
if !vh.is_empty() {
if let Some((_, source)) = vh.into_iter().find(|(v, _)| v == &hostname.0) {
return source;
if let Some(vhost) = vh.into_iter().find(|vhost| vhost.hostname() == &hostname.0) {
return vhost.source().to_string();
};
}
context.target().to_string()
Expand Down
6 changes: 5 additions & 1 deletion rust/src/nasl/builtin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod cert;
mod cryptographic;
mod description;
mod error;
mod find_service;
mod host;
mod http;
mod isotime;
Expand Down Expand Up @@ -36,6 +37,8 @@ use crate::storage::{ContextKey, DefaultDispatcher, Storage};

use super::utils::context::Target;

pub use network::socket::NaslSockets;

/// Creates a new Executor and adds all the functions to it.
///
/// When you have a function that is considered experimental due to either dependencies on
Expand All @@ -52,7 +55,7 @@ pub fn nasl_std_functions() -> Executor {
.add_set(string::NaslString)
.add_set(host::Host)
.add_set(http::NaslHttp::default())
.add_set(network::socket::NaslSockets::default())
.add_set(network::socket::SocketFns)
.add_set(network::network::Network)
.add_set(regex::RegularExpressions)
.add_set(cryptographic::Cryptographic)
Expand All @@ -61,6 +64,7 @@ pub fn nasl_std_functions() -> Executor {
.add_set(cryptographic::rc4::CipherHandlers::default())
.add_set(sys::Sys)
.add_set(ssh::Ssh::default())
.add_set(find_service::FindService::default())
.add_set(cert::NaslCerts::default());

#[cfg(feature = "nasl-builtin-raw-ip")]
Expand Down
2 changes: 1 addition & 1 deletion rust/src/nasl/builtin/network/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub fn get_retry(context: &Context) -> u8 {
}
}

struct Port(u16);
pub struct Port(u16);

impl FromNaslValue<'_> for Port {
fn from_nasl_value(value: &NaslValue) -> Result<Self, FnError> {
Expand Down
Loading
Loading