diff --git a/rust/src/nasl/builtin/error.rs b/rust/src/nasl/builtin/error.rs index 21f7b64a5..9e6ef08b3 100644 --- a/rust/src/nasl/builtin/error.rs +++ b/rust/src/nasl/builtin/error.rs @@ -2,6 +2,7 @@ use thiserror::Error; use super::super::prelude::NaslError; use super::cryptographic::CryptographicError; +use super::regex::RegexError; use super::{misc::MiscError, network::socket::SocketError, ssh::SshError, string::StringError}; #[derive(Debug, Clone, PartialEq, Eq, Error)] @@ -16,23 +17,28 @@ pub enum BuiltinError { Socket(SocketError), #[error("{0}")] Cryptographic(CryptographicError), + #[error("{0}")] + Regex(RegexError), + #[cfg(feature = "nasl-builtin-raw-ip")] + #[error("{0}")] + PacketForgery(super::raw_ip::PacketForgeryError), } macro_rules! builtin_error_variant ( - ($ty: ty, $variant: ident) => { - impl From<$ty> for BuiltinError { - fn from(value: $ty) -> Self { + ($err: path, $variant: ident) => { + impl From<$err> for BuiltinError { + fn from(value: $err) -> Self { BuiltinError::$variant(value) } } - impl From<$ty> for NaslError { - fn from(value: $ty) -> Self { + impl From<$err> for NaslError { + fn from(value: $err) -> Self { NaslError::Builtin(BuiltinError::$variant(value)) } } - impl TryFrom for $ty { + impl TryFrom for $err { type Error = (); fn try_from(value: NaslError) -> Result { @@ -50,3 +56,6 @@ builtin_error_variant!(MiscError, Misc); builtin_error_variant!(SocketError, Socket); builtin_error_variant!(CryptographicError, Cryptographic); builtin_error_variant!(SshError, Ssh); +builtin_error_variant!(RegexError, Regex); +#[cfg(feature = "nasl-builtin-raw-ip")] +builtin_error_variant!(super::raw_ip::PacketForgeryError, PacketForgery); diff --git a/rust/src/nasl/builtin/misc/mod.rs b/rust/src/nasl/builtin/misc/mod.rs index f2e7693a8..3d7e56ce3 100644 --- a/rust/src/nasl/builtin/misc/mod.rs +++ b/rust/src/nasl/builtin/misc/mod.rs @@ -27,16 +27,20 @@ use flate2::{ }; #[derive(Debug, Clone, PartialEq, Eq, Error)] -#[error("{0}")] // It would be nicer to derive this using #[from] from // thiserror, but io::Error does not impl `PartialEq`, // `Eq` or `Clone`, so we wrap `io::ErrorKind` instead, which // does not impl `Error` which is why this `From` impl exists. -pub struct MiscError(io::ErrorKind); +pub enum MiscError { + #[error("IO Error: {0}")] + IO(io::ErrorKind), + #[error("Encountered time before 1970. {0}")] + TimeBefore1970(String), +} impl From for MiscError { fn from(value: io::Error) -> Self { - Self(value.kind()) + Self::IO(value.kind()) } } @@ -106,11 +110,11 @@ fn isnull(val: NaslValue) -> bool { /// Returns the seconds counted from 1st January 1970 as an integer. #[nasl_function] -fn unixtime() -> Result { +fn unixtime() -> Result { std::time::SystemTime::now() .duration_since(UNIX_EPOCH) .map(|t| t.as_secs()) - .map_err(|_| NaslError::Dirty("System time set to time before 1st January 1960".into())) + .map_err(|e| MiscError::TimeBefore1970(e.to_string())) } /// Compress given data with gzip, when headformat is set to 'gzip' it uses gzipheader. @@ -239,13 +243,13 @@ fn defined_func(ctx: &Context, register: &Register, fn_name: Option> /// /// For example: “1067352015.030757” means 1067352015 seconds and 30757 microseconds. #[nasl_function] -fn gettimeofday() -> Result { +fn gettimeofday() -> Result { match time::SystemTime::now().duration_since(time::SystemTime::UNIX_EPOCH) { Ok(time) => { let time = time.as_micros(); Ok(format!("{}.{:06}", time / 1000000, time % 1000000)) } - Err(e) => Err(NaslError::Dirty(format!("{e}"))), + Err(e) => Err(MiscError::TimeBefore1970(e.to_string())), } } diff --git a/rust/src/nasl/builtin/raw_ip/mod.rs b/rust/src/nasl/builtin/raw_ip/mod.rs index 2d87d2a91..952b2c71f 100644 --- a/rust/src/nasl/builtin/raw_ip/mod.rs +++ b/rust/src/nasl/builtin/raw_ip/mod.rs @@ -8,6 +8,7 @@ mod raw_ip_utils; use crate::nasl::utils::{IntoFunctionSet, NaslVars, StoredFunctionSet}; use frame_forgery::FrameForgery; use packet_forgery::PacketForgery; +pub use packet_forgery::PacketForgeryError; pub struct RawIp; diff --git a/rust/src/nasl/builtin/raw_ip/packet_forgery.rs b/rust/src/nasl/builtin/raw_ip/packet_forgery.rs index 04f32d4af..5744cc251 100644 --- a/rust/src/nasl/builtin/raw_ip/packet_forgery.rs +++ b/rust/src/nasl/builtin/raw_ip/packet_forgery.rs @@ -32,8 +32,19 @@ use pnet::packet::{ use pnet_macros_support::types::u9be; use socket2::{Domain, Protocol, Socket}; +use thiserror::Error; use tracing::debug; +#[derive(Debug, Clone, PartialEq, Eq, Error)] +pub enum PacketForgeryError { + #[error("{0}")] + Custom(String), +} + +fn error(s: String) -> NaslError { + PacketForgeryError::Custom(s).into() +} + macro_rules! custom_error { ($a:expr, $b:expr) => { Err(NaslError::Diagnostic( @@ -97,7 +108,7 @@ fn safe_copy_from_slice( || d_buf.len() < d_fin || o_buf.len() < o_fin { - return Err(NaslError::Dirty( + return Err(error( "Error copying from slice. Index out of range".to_string(), )); } @@ -365,9 +376,8 @@ fn get_ip_element(register: &Register, _configs: &Context) -> Result match e.as_str() { @@ -403,7 +413,7 @@ fn dump_ip_packet(register: &Register, _: &Context) -> Result { let pkt = packet::ipv4::Ipv4Packet::new(data).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) + error("No possible to create a packet from buffer".to_string()) })?; println!("\tip_hl={}", pkt.get_header_length()); @@ -513,9 +523,8 @@ fn insert_ip_options(register: &Register, _configs: &Context) -> Result Result Result (*x as u16).to_be(), _ => { - let pkt = packet::ipv4::Ipv4Packet::new(&ip_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; - let tcp_aux = TcpPacket::new(tcp_seg.packet()).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let pkt = packet::ipv4::Ipv4Packet::new(&ip_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; + let tcp_aux = TcpPacket::new(tcp_seg.packet()) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::tcp::ipv4_checksum(&tcp_aux, &pkt.get_source(), &pkt.get_destination()) } }; - let mut tcp_seg = packet::tcp::MutableTcpPacket::new(&mut buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut tcp_seg = packet::tcp::MutableTcpPacket::new(&mut buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; tcp_seg.set_checksum(chksum); ip_buf.append(&mut buf); let l = ip_buf.len(); - let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pkt.set_total_length(l as u16); match register.named("update_ip_len") { Some(ContextType::Value(NaslValue::Boolean(l))) if !(*l) => { @@ -667,12 +671,10 @@ fn get_tcp_element(register: &Register, _configs: &Context) -> Result match el.as_str() { @@ -712,12 +714,10 @@ fn get_tcp_option(register: &Register, _configs: &Context) -> Result Result Result Result Result (*x as u16).to_be(), _ => { - let pkt = packet::ipv4::Ipv4Packet::new(&buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; - let tcp_aux = TcpPacket::new(ori_tcp.packet()).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let pkt = packet::ipv4::Ipv4Packet::new(&buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; + let tcp_aux = TcpPacket::new(ori_tcp.packet()) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::tcp::ipv4_checksum(&tcp_aux, &pkt.get_source(), &pkt.get_destination()) } }; @@ -890,9 +885,8 @@ fn set_tcp_elements(register: &Register, _configs: &Context) -> Result Result d.clone(), _ => { - return Err(NaslError::Dirty( - "insert_tcp_options: missing field".to_string(), - )); + return Err(error("insert_tcp_options: missing field".to_string())); } }; - let ip = packet::ipv4::Ipv4Packet::new(&buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let ip = packet::ipv4::Ipv4Packet::new(&buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; let iph_len = ip.get_header_length() as usize * 4; // the header length is given in 32-bits words let ori_tcp_buf = <&[u8]>::clone(&ip.payload()).to_owned(); let mut ori_tcp: packet::tcp::MutableTcpPacket; @@ -945,9 +936,8 @@ fn insert_tcp_options(register: &Register, _configs: &Context) -> Result d.as_bytes().to_vec(), Some(ContextType::Value(NaslValue::Number(d))) => d.to_be_bytes().to_vec(), _ => { - let tcp = TcpPacket::new(&ori_tcp_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let tcp = TcpPacket::new(&ori_tcp_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; tcp.payload().to_vec() } }; @@ -955,7 +945,7 @@ fn insert_tcp_options(register: &Register, _configs: &Context) -> Result Result Result (*x as u16).to_be(), _ => { - let pkt = packet::ipv4::Ipv4Packet::new(&buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; - let tcp_aux = TcpPacket::new(ori_tcp.packet()).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let pkt = packet::ipv4::Ipv4Packet::new(&buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; + let tcp_aux = TcpPacket::new(ori_tcp.packet()) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::tcp::ipv4_checksum(&tcp_aux, &pkt.get_source(), &pkt.get_destination()) } }; @@ -1084,9 +1071,8 @@ fn insert_tcp_options(register: &Register, _configs: &Context) -> Result Result Result { let positional = register.positional(); if positional.is_empty() { - return Err(NaslError::Dirty( + return Err(error( "Missing arguments. It needs at least one tcp packet".to_string(), )); } @@ -1228,9 +1214,8 @@ fn forge_udp_packet(register: &Register, _configs: &Context) -> Result Result (*x as u16).to_be(), _ => { - let pkt = packet::ipv4::Ipv4Packet::new(&ip_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; - let udp_aux = UdpPacket::new(udp_datagram.packet()).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let pkt = packet::ipv4::Ipv4Packet::new(&ip_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; + let udp_aux = UdpPacket::new(udp_datagram.packet()) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::udp::ipv4_checksum(&udp_aux, &pkt.get_source(), &pkt.get_destination()) } }; - let mut udp_datagram = packet::udp::MutableUdpPacket::new(&mut buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut udp_datagram = packet::udp::MutableUdpPacket::new(&mut buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; udp_datagram.set_checksum(chksum); ip_buf.append(&mut buf); let l = ip_buf.len(); - let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pkt.set_total_length(l as u16); match register.named("update_ip_len") { Some(ContextType::Value(NaslValue::Boolean(l))) if !(*l) => { @@ -1302,9 +1283,8 @@ fn set_udp_elements(register: &Register, _configs: &Context) -> Result Result Result Result (*x as u16).to_be(), _ => { - let pkt = packet::ipv4::Ipv4Packet::new(&buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; - let udp_aux = UdpPacket::new(ori_udp.packet()).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let pkt = packet::ipv4::Ipv4Packet::new(&buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; + let udp_aux = UdpPacket::new(ori_udp.packet()) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::udp::ipv4_checksum(&udp_aux, &pkt.get_source(), &pkt.get_destination()) } }; @@ -1386,9 +1362,8 @@ fn set_udp_elements(register: &Register, _configs: &Context) -> Result Result Result { let positional = register.positional(); if positional.is_empty() { - return Err(NaslError::Dirty( + return Err(error( "Missing arguments. It needs at least one UDP packet".to_string(), )); } @@ -1461,12 +1436,10 @@ fn get_udp_element(register: &Register, _configs: &Context) -> Result match el.as_str() { @@ -1508,9 +1481,8 @@ fn forge_icmp_packet(register: &Register, _configs: &Context) -> Result { @@ -1544,23 +1516,20 @@ fn forge_icmp_packet(register: &Register, _configs: &Context) -> Result (*x as u16).to_be(), _ => { - let icmp_aux = IcmpPacket::new(&buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let icmp_aux = IcmpPacket::new(&buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pnet::packet::icmp::checksum(&icmp_aux) } }; - let mut icmp_pkt = packet::icmp::MutableIcmpPacket::new(&mut buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut icmp_pkt = packet::icmp::MutableIcmpPacket::new(&mut buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; icmp_pkt.set_checksum(chksum); ip_buf.append(&mut buf); let l = ip_buf.len(); - let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let mut pkt = packet::ipv4::MutableIpv4Packet::new(&mut ip_buf) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; pkt.set_total_length(l as u16); match register.named("update_ip_len") { Some(ContextType::Value(NaslValue::Boolean(l))) if !(*l) => { @@ -1593,12 +1562,10 @@ fn get_icmp_element(register: &Register, _configs: &Context) -> Result match el.as_str() { @@ -1657,12 +1624,10 @@ fn dump_icmp_packet(register: &Register, _: &Context) -> Result= 4 { @@ -1789,9 +1754,8 @@ fn forge_igmp_packet(register: &Register, _configs: &Context) -> Result { @@ -1813,7 +1777,7 @@ fn forge_igmp_packet(register: &Register, _configs: &Context) -> Result { - return Err(NaslError::Dirty(format!("Invalid address group: {}", e))); + return Err(error(format!("Invalid address group: {}", e))); } }; } @@ -1824,14 +1788,12 @@ fn forge_igmp_packet(register: &Register, _configs: &Context) -> Result Result { Some(Protocol::from(IPPROTO_RAW)), ) { Ok(s) => Ok(s), - Err(e) => Err(NaslError::Dirty(format!( - "Not possible to create a raw socket: {}", - e - ))), + Err(e) => Err(error(format!("Not possible to create a raw socket: {}", e))), } } @@ -1895,10 +1854,7 @@ fn nasl_tcp_ping(register: &Register, configs: &Context) -> Result Result Result Result { - return Err(NaslError::Dirty(format!("send_packet: {}", e))); + return Err(error(format!("send_packet: {}", e))); } } @@ -2067,10 +2021,7 @@ fn nasl_send_packet(register: &Register, configs: &Context) -> Result Result data as &[u8], _ => return Err(NaslError::wrong_unnamed_argument("Data", "Invalid packet")), }; - let packet = packet::ipv4::Ipv4Packet::new(packet_raw).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let packet = packet::ipv4::Ipv4Packet::new(packet_raw) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; if allow_broadcast { if let Err(err) = soc.set_broadcast(true) { @@ -2117,7 +2067,7 @@ fn nasl_send_packet(register: &Register, configs: &Context) -> Result Result { // Remove all from lower layer - let frame = EthernetPacket::new(packet.data).ok_or_else(|| { - NaslError::Dirty("No possible to create a packet from buffer".to_string()) - })?; + let frame = EthernetPacket::new(packet.data) + .ok_or_else(|| error("No possible to create a packet from buffer".to_string()))?; return Ok(NaslValue::Data(frame.payload().to_vec())); } Err(_) => Ok(NaslValue::Null), diff --git a/rust/src/nasl/builtin/regex/mod.rs b/rust/src/nasl/builtin/regex/mod.rs index ad52d8000..1a18fc082 100644 --- a/rust/src/nasl/builtin/regex/mod.rs +++ b/rust/src/nasl/builtin/regex/mod.rs @@ -7,6 +7,13 @@ mod tests; use crate::nasl::prelude::*; use regex::{Regex, RegexBuilder}; +use thiserror::Error; + +#[derive(Debug, Clone, PartialEq, Eq, Error)] +pub enum RegexError { + #[error("Error building regular expression pattern: {0}")] + BuildingError(String), +} fn parse_search_string(mut s: &str, rnul: bool, multiline: bool) -> &str { if !rnul { @@ -19,17 +26,14 @@ fn parse_search_string(mut s: &str, rnul: bool, multiline: bool) -> &str { s } -fn make_regex(pattern: &str, icase: bool, multiline: bool) -> Result { +fn make_regex(pattern: &str, icase: bool, multiline: bool) -> Result { match RegexBuilder::new(pattern.to_string().as_str()) .case_insensitive(icase) .multi_line(multiline) .build() { Ok(re) => Ok(re), - Err(e) => Err(NaslError::Dirty(format!( - " Error building regular expression pattern: {}", - e - ))), + Err(e) => Err(RegexError::BuildingError(e.to_string())), } } diff --git a/rust/src/nasl/utils/error.rs b/rust/src/nasl/utils/error.rs index 76283318d..0dc4c186b 100644 --- a/rust/src/nasl/utils/error.rs +++ b/rust/src/nasl/utils/error.rs @@ -18,10 +18,6 @@ pub enum NaslError { /// Diagnostic string is informational and the second arg is the return value for the user #[error("{0}")] Diagnostic(String, Option), - /// There is a deeper problem - /// An example would be that there is no free memory left in the system - #[error("{0}")] - Dirty(String), #[error("{0}")] Argument(#[from] ArgumentError), #[error("{0}")]