CVRF: 处理 vulnerabilities
Signed-off-by: Jia Chao <jiac13@chinaunicom.cn>
This commit is contained in:
parent
973e22c89e
commit
89c831a48b
201
src/lib.rs
201
src/lib.rs
|
@ -95,7 +95,7 @@ impl XmlReader {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct CVRF {
|
||||
pub struct CVRF {
|
||||
// <DocumentTitle xml:lang="en">
|
||||
pub documenttitle: String,
|
||||
|
||||
|
@ -118,7 +118,7 @@ struct CVRF {
|
|||
pub producttree: ProductTree,
|
||||
|
||||
// <Vulnerability xmlns="http://www.icasi.org/CVRF/schema/vuln/1.1" Ordinal="1">
|
||||
pub vulnerability: Vulnerability,
|
||||
pub vulnerabilities: Vec<Vulnerability>,
|
||||
}
|
||||
|
||||
impl CVRF {
|
||||
|
@ -133,7 +133,7 @@ impl CVRF {
|
|||
documentnotes: vec![],
|
||||
documentreferences: vec![],
|
||||
producttree: ProductTree::new(),
|
||||
vulnerability: Vulnerability::new(),
|
||||
vulnerabilities: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,6 +163,7 @@ impl CVRF {
|
|||
"DocumentNotes" => self.handle_notes(xmlreader),
|
||||
"DocumentReferences" => self.handle_references(xmlreader),
|
||||
"ProductTree" => self.producttree.load_from_xmlreader(xmlreader),
|
||||
"Vulnerability" => self.handle_vulnerabilities(xmlreader),
|
||||
_ => {}
|
||||
},
|
||||
Err(e) => {
|
||||
|
@ -199,6 +200,14 @@ impl CVRF {
|
|||
self.documentreferences.push(reference);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_vulnerabilities(&mut self, xmlreader: &mut XmlReader) {
|
||||
let mut vulnerability = Vulnerability::new();
|
||||
vulnerability.load_from_xmlreader(xmlreader);
|
||||
if vulnerability.cve != "" {
|
||||
self.vulnerabilities.push(vulnerability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth = 2
|
||||
|
@ -628,7 +637,6 @@ impl ProductTree {
|
|||
_type.clear();
|
||||
_name.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
|
@ -756,6 +764,84 @@ impl Vulnerability {
|
|||
remediations: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
fn load_from_xmlreader(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let key = if let Some(key) = xmlreader.next_start_name_under_depth(1) {
|
||||
key
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
|
||||
match key.as_str() {
|
||||
"Notes" => self.handle_notes(xmlreader),
|
||||
"ReleaseDate" => self.releasedate = xmlreader.next_characters(),
|
||||
"CVE" => self.cve = xmlreader.next_characters(),
|
||||
"ProductStatuses" => self.handle_productstatuses(xmlreader),
|
||||
"Threats" => self.handle_threats(xmlreader),
|
||||
"CVSSScoreSets" => self.handle_cvssscoresets(xmlreader),
|
||||
"Remediations" => self.handle_remediations(xmlreader),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_notes(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let mut note = Note::new();
|
||||
note.load_from_xmlreader(xmlreader);
|
||||
|
||||
if xmlreader.depth < 3 {
|
||||
break;
|
||||
}
|
||||
self.notes.push(note);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_productstatuses(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let mut status = ProductStatus::new();
|
||||
status.load_from_xmlreader(xmlreader);
|
||||
if xmlreader.depth < 3 {
|
||||
break;
|
||||
}
|
||||
self.productstatuses.push(status);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_threats(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let mut threat = Threat::new();
|
||||
threat.load_from_xmlreader(xmlreader);
|
||||
if xmlreader.depth < 3 {
|
||||
break;
|
||||
}
|
||||
self.threats.push(threat);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_cvssscoresets(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let mut scoreset = ScoreSet::new();
|
||||
scoreset.load_from_xmlreader(xmlreader);
|
||||
if xmlreader.depth < 3 {
|
||||
break;
|
||||
}
|
||||
self.cvssscoresets.push(scoreset);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_remediations(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let mut remediation = Remediation::new();
|
||||
remediation.load_from_xmlreader(xmlreader);
|
||||
if xmlreader.depth < 3 {
|
||||
break;
|
||||
}
|
||||
self.remediations.push(remediation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth = 4
|
||||
|
@ -779,6 +865,30 @@ impl ProductStatus {
|
|||
products: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
fn load_from_xmlreader(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
match xmlreader.next() {
|
||||
Ok(XmlEvent::StartElement { attributes, .. }) => {
|
||||
if xmlreader.depth == 4 {
|
||||
self.status = attributes[0].value.clone();
|
||||
}
|
||||
self.products.push(xmlreader.next_characters());
|
||||
}
|
||||
Ok(XmlEvent::EndElement { .. }) => {
|
||||
if xmlreader.depth < 4 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("XmlReader Error: {e}");
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth = 4
|
||||
|
@ -801,6 +911,31 @@ impl Threat {
|
|||
description: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
fn load_from_xmlreader(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
match xmlreader.next() {
|
||||
Ok(XmlEvent::StartElement { attributes, .. }) => {
|
||||
if xmlreader.depth == 4 {
|
||||
self.r#type = attributes[0].value.clone();
|
||||
} else {
|
||||
self.description = xmlreader.next_characters();
|
||||
}
|
||||
}
|
||||
Ok(XmlEvent::EndElement { .. }) => {
|
||||
if xmlreader.depth < 4 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("XmlReader Error: {e}");
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth = 4
|
||||
|
@ -824,6 +959,23 @@ impl ScoreSet {
|
|||
vector: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
fn load_from_xmlreader(&mut self, xmlreader: &mut XmlReader) {
|
||||
loop {
|
||||
let key = if let Some(key) = xmlreader.next_start_name_under_depth(3) {
|
||||
key
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
|
||||
match key.as_str() {
|
||||
"BaseScore" => self.basescore = xmlreader.next_characters(),
|
||||
"Vector" => self.vector = xmlreader.next_characters(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// depth = 4
|
||||
|
@ -858,4 +1010,45 @@ impl Remediation {
|
|||
url: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, xmlreader))]
|
||||
fn load_from_xmlreader(&mut self, xmlreader: &mut XmlReader) {
|
||||
// 读取类型
|
||||
loop {
|
||||
match xmlreader.next() {
|
||||
Ok(XmlEvent::StartElement { attributes, .. }) => {
|
||||
if xmlreader.depth == 4 {
|
||||
self.r#type = attributes[0].value.clone();
|
||||
}
|
||||
break;
|
||||
}
|
||||
Ok(XmlEvent::EndElement { .. }) => {
|
||||
if xmlreader.depth < 4 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("XmlReader Error: {e}");
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 其它字段
|
||||
loop {
|
||||
let key = if let Some(key) = xmlreader.next_start_name_under_depth(3) {
|
||||
key
|
||||
} else {
|
||||
break;
|
||||
};
|
||||
|
||||
match key.as_str() {
|
||||
"Description" => self.description = xmlreader.next_characters(),
|
||||
"DATE" => self.date = xmlreader.next_characters(),
|
||||
"URL" => self.url = xmlreader.next_characters(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
48
src/test.rs
48
src/test.rs
|
@ -84,4 +84,52 @@ fn cvrf_works() {
|
|||
cvrf.producttree.packages.get(producttree_src).unwrap()[2].content,
|
||||
producttree_src_content
|
||||
);
|
||||
|
||||
// vulnerabilities
|
||||
let cvrf_vulner_releasedate = "2024-04-19";
|
||||
let cvrf_vulner_cve = "CVE-2023-45288";
|
||||
let cvrf_vulner_productstatues_status = "Fixed";
|
||||
let cvrf_vulner_productstatues_product = "openEuler-22.03-LTS";
|
||||
let cvrf_vulner_basescore = "7.5";
|
||||
let cvrf_vulner_vector = "AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H";
|
||||
let cvrf_vulner_remedition_type = "Vendor Fix";
|
||||
let cvrf_vulner_remedition_descrition = "golang security update";
|
||||
let cvrf_vulner_remedition_date = "2024-04-19";
|
||||
let cvrf_vulner_remedition_url = "https://www.openeuler.org/en/security/safety-bulletin/detail.html?id=openEuler-SA-2024-1488";
|
||||
|
||||
assert_eq!(cvrf.vulnerabilities[0].notes.len(), 1);
|
||||
assert_eq!(cvrf.vulnerabilities[0].releasedate, cvrf_vulner_releasedate);
|
||||
assert_eq!(cvrf.vulnerabilities[0].cve, cvrf_vulner_cve);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].productstatuses[0].status,
|
||||
cvrf_vulner_productstatues_status
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].productstatuses[0].products[2],
|
||||
cvrf_vulner_productstatues_product
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].cvssscoresets[0].basescore,
|
||||
cvrf_vulner_basescore
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].cvssscoresets[0].vector,
|
||||
cvrf_vulner_vector
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].remediations[0].r#type,
|
||||
cvrf_vulner_remedition_type
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].remediations[0].description,
|
||||
cvrf_vulner_remedition_descrition
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].remediations[0].date,
|
||||
cvrf_vulner_remedition_date
|
||||
);
|
||||
assert_eq!(
|
||||
cvrf.vulnerabilities[0].remediations[0].url,
|
||||
cvrf_vulner_remedition_url
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user