Skip to main content

ruso_script/script/
ast.rs

1pub use ruso_runtime::contract::{
2    BodyValue, CmpOp, CmpValue, EvidenceKind, ExtractSource, FieldKind, HttpMethod, InlinePart,
3    InlinePartBody, MatchPredicate, ObjectBody, QualifiedField, QualifiedMatch, Severity,
4};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Program {
8    pub statements: Vec<Stmt>,
9}
10
11/// Generic socket probe fields shared by `dns`, `tcp`, and `udp`.
12#[derive(Debug, Clone, PartialEq)]
13pub struct SocketProbe {
14    pub name: String,
15    pub host: String,
16    pub port: Option<u16>,
17    /// UTF-8 text or raw bytes (from `payload "..."` or `payload "aabbcc"` hex).
18    pub payload: Option<Vec<u8>>,
19    pub tls: bool,
20    pub session: bool,
21    pub read_max: u32,
22    pub read_idle_ms: u32,
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub enum Value {
27    String(String),
28    List(Vec<String>),
29}
30
31#[derive(Debug, Clone, PartialEq)]
32pub enum ListSource {
33    Literal(Vec<String>),
34    Variable(String),
35}
36
37#[derive(Debug, Clone, PartialEq)]
38pub enum Stmt {
39    Name(String),
40    Description(String),
41    Impact(String),
42    Severity(Severity),
43    Author(String),
44    Cve(String),
45    Cwe(String),
46    Reference(String),
47    Cvss(String),
48    CvssScore(String),
49    Mitigation(String),
50    Tag(String),
51    Version(String),
52    Family(String),
53
54    Set {
55        name: String,
56        value: Value,
57    },
58
59    ForIn {
60        item: String,
61        list: ListSource,
62        body: Vec<Stmt>,
63    },
64
65    Http {
66        name: String,
67        items: Vec<HttpItem>,
68    },
69    Dns(SocketProbe),
70    Tcp(SocketProbe),
71    Udp(SocketProbe),
72    Send {
73        probe: String,
74        payload: Option<Vec<u8>>,
75    },
76    Break,
77
78    Match(QualifiedMatch),
79    MatchAll(Vec<QualifiedMatch>),
80    MatchAny(Vec<QualifiedMatch>),
81    Assert(QualifiedMatch),
82
83    Extract {
84        name: String,
85        source: ExtractSource,
86    },
87
88    If {
89        condition: QualifiedMatch,
90        body: Vec<Stmt>,
91    },
92
93    Save {
94        request: String,
95        alias: String,
96    },
97
98    Evidence(EvidenceKind),
99
100    Stop,
101    Fail,
102    Continue,
103    Exit,
104
105    Retry {
106        request: String,
107        count: u32,
108    },
109    RetryDelay(String),
110    Sleep(String),
111}
112
113impl Stmt {
114    pub fn is_metadata(&self) -> bool {
115        matches!(
116            self,
117            Self::Name(_)
118                | Self::Description(_)
119                | Self::Impact(_)
120                | Self::Severity(_)
121                | Self::Author(_)
122                | Self::Cve(_)
123                | Self::Cwe(_)
124                | Self::Reference(_)
125                | Self::Cvss(_)
126                | Self::CvssScore(_)
127                | Self::Mitigation(_)
128                | Self::Tag(_)
129                | Self::Version(_)
130                | Self::Family(_)
131        )
132    }
133
134    pub fn is_probe_definition(&self) -> bool {
135        matches!(
136            self,
137            Self::Http { .. } | Self::Dns(_) | Self::Tcp(_) | Self::Udp(_)
138        )
139    }
140}
141
142#[derive(Debug, Clone, PartialEq)]
143pub enum HttpItem {
144    Method(HttpMethod),
145    Path(String),
146    Timeout(String),
147    FollowRedirect(bool),
148    VerifySsl(bool),
149    Proxy(String),
150    UserAgent(String),
151    Header { name: String, value: String },
152    Cookie { name: String, value: String },
153    Query { name: String, value: String },
154    Data(ObjectBody),
155    Json(ObjectBody),
156    Raw(String),
157    BodyBytes(String),
158    Multipart(ObjectBody),
159}