cwe_xml/cwe/
weaknesses.rs

1use std::hash::{Hash, Hasher};
2use std::rc::Rc;
3
4use serde::Deserialize;
5
6use crate::cwe::content_history::ContentHistory;
7use crate::cwe::notes::Notes;
8use crate::cwe::structured_text::{StructuredCode, StructuredText};
9
10#[derive(Debug, Deserialize)]
11#[serde(deny_unknown_fields)]
12pub struct Weaknesses {
13    #[serde(rename = "Weakness", default)]
14    pub weaknesses: Vec<Rc<Weakness>>,
15}
16
17#[derive(Debug, Deserialize)]
18#[serde(rename = "Weakness")]
19#[serde(deny_unknown_fields)]
20pub struct Weakness {
21    #[serde(rename = "@ID")]
22    pub id: i64,
23    #[serde(rename = "@Name")]
24    pub name: String,
25    #[serde(rename = "@Abstraction")]
26    pub abstraction: String,
27    #[serde(rename = "@Structure")]
28    pub structure: String,
29    #[serde(rename = "@Status")]
30    pub status: String,
31    #[serde(rename = "Description")]
32    pub description: String,
33    #[serde(rename = "Extended_Description")]
34    pub extended_description: Option<StructuredText>,
35    #[serde(rename = "Related_Weaknesses")]
36    pub related_weaknesses: Option<RelatedWeaknesses>,
37    #[serde(rename = "Demonstrative_Examples")]
38    pub demonstrative_examples: Option<DemonstrativeExamples>,
39    #[serde(rename = "Weakness_Ordinalities")]
40    pub weakness_ordinalities: Option<WeaknessOrdinalities>,
41    #[serde(rename = "Applicable_Platforms")]
42    pub applicable_platforms: Option<ApplicablePlatforms>,
43    #[serde(rename = "Background_Details")]
44    pub background_details: Option<BackgroundDetails>,
45    #[serde(rename = "Modes_Of_Introduction")]
46    pub modes_of_introduction: Option<ModesOfIntroduction>,
47    #[serde(rename = "Likelihood_Of_Exploit")]
48    pub likelihood_of_exploit: Option<String>,
49    #[serde(rename = "Alternate_Terms")]
50    pub alternate_terms: Option<AlternateTerms>,
51    #[serde(rename = "Common_Consequences")]
52    pub common_consequences: Option<CommonConsequences>,
53    #[serde(rename = "Detection_Methods")]
54    pub detection_methods: Option<DetectionMethods>,
55    #[serde(rename = "Potential_Mitigations")]
56    pub potential_mitigations: Option<PotentialMitigations>,
57    #[serde(rename = "Observed_Examples")]
58    pub observed_examples: Option<ObservedExamples>,
59    #[serde(rename = "Related_Attack_Patterns")]
60    pub related_attack_patterns: Option<RelatedAttackPatterns>,
61    #[serde(rename = "References")]
62    pub references: Option<References>,
63    #[serde(rename = "Content_History")]
64    pub content_history: ContentHistory,
65    #[serde(rename = "Exploitation_Factors")]
66    pub exploitation_factors: Option<ExploitationFactors>,
67    #[serde(rename = "Functional_Areas")]
68    pub functional_areas: Option<FunctionalAreas>,
69    #[serde(rename = "Affected_Resources")]
70    pub affected_resources: Option<AffectedResources>,
71    #[serde(rename = "Taxonomy_Mappings")]
72    pub taxonomy_mappings: Option<TaxonomyMappings>,
73    #[serde(rename = "Notes")]
74    pub notes: Option<Notes>,
75    #[serde(rename = "Mapping_Notes")]
76    pub mapping_notes: Option<MappingNotes>,
77}
78
79impl PartialEq<Self> for Weakness {
80    fn eq(&self, other: &Self) -> bool {
81        self.id == other.id
82    }
83}
84
85impl Eq for Weakness {}
86
87impl Hash for Weakness {
88    fn hash<H: Hasher>(&self, state: &mut H) {
89        state.write_i64(self.id)
90    }
91}
92
93impl Weakness {
94    /// Returns a vector of CWE IDs of weaknesses that are direct ancestors of this weakness.
95    /// In other word the current weakness is a child of the returned weaknesses.
96    pub fn direct_ancestors(&self) -> Vec<i64> {
97        let mut ancestors = Vec::new();
98        if let Some(related_weaknesses) = &self.related_weaknesses {
99            for related_weakness in &related_weaknesses.related_weaknesses {
100                if related_weakness.nature == RelatedNature::ChildOf {
101                    ancestors.push(related_weakness.cwe_id);
102                }
103            }
104        }
105        ancestors
106    }
107}
108
109#[derive(Debug, Deserialize, PartialEq)]
110#[serde(deny_unknown_fields)]
111pub enum RelatedNature {
112    ChildOf,
113    ParentOf,
114    StartsWith,
115    CanFollow,
116    CanPrecede,
117    RequiredBy,
118    Requires,
119    CanAlsoBe,
120    PeerOf,
121}
122
123#[derive(Debug, Deserialize)]
124#[serde(deny_unknown_fields)]
125pub struct WeaknessOrdinalities {
126    #[serde(rename = "$value")]
127    pub weakness_ordinalities: Vec<WeaknessOrdinality>,
128}
129
130#[derive(Debug, Deserialize)]
131#[serde(deny_unknown_fields)]
132pub struct WeaknessOrdinality {
133    #[serde(rename = "Ordinality")]
134    pub ordinality: Option<String>,
135    #[serde(rename = "Description")]
136    pub description: Option<String>,
137}
138
139#[derive(Debug, Deserialize)]
140#[serde(rename = "Related_Weaknesses")]
141#[serde(deny_unknown_fields)]
142pub struct RelatedWeaknesses {
143    #[serde(rename = "Related_Weakness", default)]
144    pub related_weaknesses: Vec<RelatedWeakness>,
145}
146
147#[derive(Debug, Deserialize)]
148#[serde(rename = "Related_Weakness")]
149#[serde(deny_unknown_fields)]
150pub struct RelatedWeakness {
151    #[serde(rename = "@Nature")]
152    pub nature: RelatedNature,
153    #[serde(rename = "@CWE_ID")]
154    pub cwe_id: i64,
155    #[serde(rename = "@View_ID")]
156    pub view_id: i64,
157    #[serde(rename = "@Chain_ID")]
158    pub chain_id: Option<i64>,
159    #[serde(rename = "@Ordinal")]
160    pub ordinal: Option<String>,
161}
162
163#[derive(Debug, Deserialize)]
164pub struct MappingNotes {
165}
166
167#[derive(Debug, Deserialize)]
168#[serde(deny_unknown_fields)]
169pub struct TaxonomyMappings {
170    #[serde(rename = "$value")]
171    pub taxonomy_mappings: Vec<TaxonomyMapping>,
172}
173
174#[derive(Debug, Deserialize)]
175#[serde(deny_unknown_fields)]
176pub struct TaxonomyMapping {
177    #[serde(rename = "@Taxonomy_Name")]
178    pub taxonomy_name: String,
179    #[serde(rename = "Entry_ID")]
180    pub entry_id: Option<String>,
181    #[serde(rename = "Entry_Name")]
182    pub entry_name: Option<String>,
183    #[serde(rename = "Mapping_Fit")]
184    pub mapping_fit: Option<String>,
185}
186
187#[derive(Debug, Deserialize)]
188#[serde(deny_unknown_fields)]
189pub struct FunctionalAreas {
190    #[serde(rename = "$value")]
191    pub functional_areas: Vec<String>,
192}
193
194#[derive(Debug, Deserialize)]
195#[serde(deny_unknown_fields)]
196pub struct AffectedResources {
197    #[serde(rename = "$value")]
198    pub affected_resources: Vec<String>,
199}
200
201#[derive(Debug, Deserialize)]
202#[serde(deny_unknown_fields)]
203pub struct References {
204    #[serde(rename = "$value")]
205    pub references: Vec<Reference>,
206}
207
208#[derive(Debug, Deserialize)]
209#[serde(deny_unknown_fields)]
210pub struct Reference {
211    #[serde(rename = "@External_Reference_ID")]
212    pub external_reference_id: String,
213    #[serde(rename = "@Section")]
214    pub section: Option<String>,
215}
216
217#[derive(Debug, Deserialize)]
218#[serde(deny_unknown_fields)]
219pub struct RelatedAttackPatterns {
220    #[serde(rename = "$value")]
221    pub related_attack_patterns: Vec<RelatedAttackPattern>,
222}
223
224#[derive(Debug, Deserialize)]
225#[serde(deny_unknown_fields)]
226pub struct RelatedAttackPattern {
227    #[serde(rename = "@CAPEC_ID")]
228    pub caped_id: i64,
229}
230
231#[derive(Debug, Deserialize)]
232#[serde(deny_unknown_fields)]
233pub struct ObservedExamples {
234    #[serde(rename = "$value")]
235    pub observed_examples: Vec<ObservedExample>,
236}
237
238#[derive(Debug, Deserialize)]
239#[serde(deny_unknown_fields)]
240pub struct ObservedExample {
241    #[serde(rename = "Reference")]
242    pub reference: String,
243    #[serde(rename = "Description")]
244    pub description: String,
245    #[serde(rename = "Link")]
246    pub link: String,
247}
248
249#[derive(Debug, Deserialize)]
250#[serde(deny_unknown_fields)]
251pub struct DemonstrativeExamples {
252    #[serde(rename = "Demonstrative_Example")]
253    pub examples: Vec<DemonstrativeExample>,
254}
255
256#[derive(Debug, Deserialize)]
257#[serde(deny_unknown_fields)]
258pub struct DemonstrativeExample {
259    #[serde(rename = "@Demonstrative_Example_ID")]
260    pub demonstrative_example_id: Option<String>,
261    #[serde(rename = "$value")]
262    pub children: Vec<DemonstrativeExampleChild>,
263}
264
265#[derive(Debug, Deserialize)]
266#[serde(deny_unknown_fields)]
267pub enum DemonstrativeExampleChild {
268    #[serde(rename = "Title_Text")]
269    TitleText(String),
270    #[serde(rename = "Intro_Text")]
271    IntroText(StructuredText),
272    #[serde(rename = "Body_Text")]
273    BodyText(StructuredText),
274    #[serde(rename = "Example_Code")]
275    ExampleCode(StructuredCode),
276    #[serde(rename = "References")]
277    References {
278        #[serde(rename = "$value")]
279        children: Vec<Reference>,
280    },
281}
282
283#[derive(Debug, Deserialize)]
284#[serde(deny_unknown_fields)]
285pub struct PotentialMitigations {
286    #[serde(rename = "$value")]
287    pub potential_mitigations: Vec<PotentialMitigation>,
288}
289
290#[derive(Debug, Deserialize)]
291#[serde(deny_unknown_fields)]
292pub struct PotentialMitigation {
293    #[serde(rename = "@Mitigation_ID")]
294    pub mitigation_id: Option<String>,
295    #[serde(rename = "$value")]
296    pub children: Vec<PotentialMitigationChild>,
297}
298
299#[derive(Debug, Deserialize)]
300#[serde(deny_unknown_fields)]
301pub enum PotentialMitigationChild {
302    #[serde(rename = "Phase")]
303    Phase(String),
304    #[serde(rename = "Strategy")]
305    Strategy(String),
306    #[serde(rename = "Description")]
307    Description(StructuredText),
308    #[serde(rename = "Effectiveness")]
309    Effectiveness(String),
310    #[serde(rename = "Effectiveness_Notes")]
311    EffectivenessNotes(StructuredText),
312}
313
314#[derive(Debug, Deserialize)]
315#[serde(deny_unknown_fields)]
316pub struct DetectionMethods {
317    #[serde(rename = "$value")]
318    pub detection_methods: Vec<DetectionMethod>,
319}
320
321#[derive(Debug, Deserialize)]
322#[serde(deny_unknown_fields)]
323pub struct DetectionMethod {
324    #[serde(rename = "@Detection_Method_ID")]
325    pub detection_method_id: Option<String>,
326    #[serde(rename = "$value")]
327    pub children: Vec<DetectionMethodChild>,
328}
329
330#[derive(Debug, Deserialize)]
331#[serde(deny_unknown_fields)]
332pub enum DetectionMethodChild {
333    #[serde(rename = "Method")]
334    Method(String),
335    #[serde(rename = "Description")]
336    Description(StructuredText),
337    #[serde(rename = "Effectiveness")]
338    Effectiveness(String),
339    #[serde(rename = "Effectiveness_Notes")]
340    EffectivenessNotes(String),
341}
342
343#[derive(Debug, Deserialize)]
344#[serde(deny_unknown_fields)]
345pub struct CommonConsequences {
346    #[serde(rename = "$value")]
347    pub common_consequences: Vec<Consequence>,
348}
349
350#[derive(Debug, Deserialize)]
351#[serde(deny_unknown_fields)]
352pub struct Consequence {
353    #[serde(rename = "$value")]
354    pub children: Vec<ConsequenceChild>,
355}
356
357#[derive(Debug, Deserialize)]
358#[serde(deny_unknown_fields)]
359pub enum ConsequenceChild {
360    #[serde(rename = "Scope")]
361    Scope(String),
362    #[serde(rename = "Impact")]
363    Impact(String),
364    #[serde(rename = "Note")]
365    Note(String),
366    #[serde(rename = "Likelihood")]
367    Likelihood(String),
368}
369
370#[derive(Debug, Deserialize)]
371#[serde(deny_unknown_fields)]
372pub struct AlternateTerms {
373    #[serde(rename = "$value")]
374    pub alternate_terms: Vec<AlternateTerm>,
375}
376
377#[derive(Debug, Deserialize)]
378#[serde(deny_unknown_fields)]
379pub struct ExploitationFactors {
380    #[serde(rename = "$value")]
381    pub children: Vec<StructuredText>,
382}
383
384#[derive(Debug, Deserialize)]
385#[serde(deny_unknown_fields)]
386pub struct AlternateTerm {
387    #[serde(rename = "Term")]
388    pub term: String,
389    #[serde(rename = "Description")]
390    pub description: Option<StructuredText>,
391}
392
393#[derive(Debug, Deserialize)]
394#[serde(deny_unknown_fields)]
395pub struct ModesOfIntroduction {
396    #[serde(rename = "$value")]
397    pub introductions: Vec<Introduction>,
398}
399
400#[derive(Debug, Deserialize)]
401#[serde(deny_unknown_fields)]
402pub struct Introduction {
403    #[serde(rename = "Phase")]
404    pub phase: String,
405    #[serde(rename = "Note")]
406    pub note: Option<StructuredText>,
407}
408
409#[derive(Debug, Deserialize)]
410#[serde(deny_unknown_fields)]
411pub struct BackgroundDetails {
412    #[serde(rename = "$value", default)]
413    pub background_details: Vec<StructuredText>,
414}
415
416#[derive(Debug, Deserialize)]
417#[serde(deny_unknown_fields)]
418pub struct ApplicablePlatforms {
419    #[serde(rename = "$value")]
420    pub applicable_platforms: Vec<ApplicablePlatform>,
421}
422
423#[derive(Debug, Deserialize)]
424#[serde(deny_unknown_fields)]
425pub enum ApplicablePlatform {
426    Language {
427        #[serde(rename = "@Class")]
428        class: Option<String>,
429        #[serde(rename = "@Name")]
430        name: Option<String>,
431        #[serde(rename = "@Prevalence")]
432        prevalence: String,
433    },
434    Technology {
435        #[serde(rename = "@Name")]
436        name: Option<String>,
437        #[serde(rename = "@Class")]
438        class: Option<String>,
439        #[serde(rename = "@Prevalence")]
440        prevalence: String,
441    },
442    #[serde(rename = "Operating_System")]
443    OperatingSystem {
444        #[serde(rename = "@Name")]
445        name: Option<String>,
446        #[serde(rename = "@Version")]
447        version: Option<String>,
448        #[serde(rename = "@CPE_ID")]
449        cpe_id: Option<String>,
450        #[serde(rename = "@Class")]
451        class: Option<String>,
452        #[serde(rename = "@Prevalence")]
453        prevalence: String,
454    },
455    #[serde(rename = "Architecture")]
456    Architecture {
457        #[serde(rename = "@Name")]
458        name: Option<String>,
459        #[serde(rename = "@Class")]
460        class: Option<String>,
461        #[serde(rename = "@Prevalence")]
462        prevalence: String,
463    },
464}