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    Report(String),
45    Cve(String),
46    Cwe(String),
47    Reference(String),
48    Cvss(String),
49    CvssScore(String),
50    Mitigation(String),
51    Tag(String),
52    Version(String),
53    Family(String),
54
55    Set {
56        name: String,
57        value: Value,
58    },
59
60    ForIn {
61        item: String,
62        list: ListSource,
63        body: Vec<Stmt>,
64    },
65
66    Http {
67        name: String,
68        items: Vec<HttpItem>,
69    },
70    Dns(SocketProbe),
71    Tcp(SocketProbe),
72    Udp(SocketProbe),
73    Send {
74        probe: String,
75        payload: Option<Vec<u8>>,
76    },
77    Break,
78
79    Match(QualifiedMatch),
80    MatchAll(Vec<QualifiedMatch>),
81    MatchAny(Vec<QualifiedMatch>),
82    Assert(QualifiedMatch),
83
84    Extract {
85        name: String,
86        source: ExtractSource,
87    },
88
89    If {
90        condition: QualifiedMatch,
91        body: Vec<Stmt>,
92    },
93
94    Save {
95        request: String,
96        alias: String,
97    },
98
99    Evidence(EvidenceKind),
100
101    Stop,
102    Fail,
103    Continue,
104    Exit,
105
106    Retry {
107        request: String,
108        count: u32,
109    },
110    RetryDelay(String),
111    Sleep(String),
112}
113
114impl Stmt {
115    pub fn is_metadata(&self) -> bool {
116        matches!(
117            self,
118            Self::Name(_)
119                | Self::Description(_)
120                | Self::Impact(_)
121                | Self::Severity(_)
122                | Self::Author(_)
123                | Self::Report(_)
124                | Self::Cve(_)
125                | Self::Cwe(_)
126                | Self::Reference(_)
127                | Self::Cvss(_)
128                | Self::CvssScore(_)
129                | Self::Mitigation(_)
130                | Self::Tag(_)
131                | Self::Version(_)
132                | Self::Family(_)
133        )
134    }
135
136    pub fn is_probe_definition(&self) -> bool {
137        matches!(
138            self,
139            Self::Http { .. } | Self::Dns(_) | Self::Tcp(_) | Self::Udp(_)
140        )
141    }
142}
143
144#[derive(Debug, Clone, PartialEq)]
145pub enum HttpItem {
146    Method(HttpMethod),
147    Path(String),
148    Timeout(String),
149    FollowRedirect(bool),
150    VerifySsl(bool),
151    Proxy(String),
152    UserAgent(String),
153    Header { name: String, value: String },
154    Cookie { name: String, value: String },
155    Query { name: String, value: String },
156    Data(ObjectBody),
157    Json(ObjectBody),
158    Raw(String),
159    BodyBytes(String),
160    Multipart(ObjectBody),
161}