From bcc1a56f57aee10fc79a14084f425cdab8b0325b Mon Sep 17 00:00:00 2001
From: Paul Duncan <pabs@pablotron.org>
Date: Fri, 4 Feb 2022 00:01:14 -0500
Subject: add internal/cpematch

---
 internal/cpematch/cpematch.go             |  25 ++++++++
 internal/cpematch/cpematch_test.go        | 100 ++++++++++++++++++++++++++++++
 internal/cpematch/testdata/test-0.json.gz | Bin 0 -> 291 bytes
 3 files changed, 125 insertions(+)
 create mode 100644 internal/cpematch/cpematch.go
 create mode 100644 internal/cpematch/cpematch_test.go
 create mode 100644 internal/cpematch/testdata/test-0.json.gz

diff --git a/internal/cpematch/cpematch.go b/internal/cpematch/cpematch.go
new file mode 100644
index 0000000..9f879c6
--- /dev/null
+++ b/internal/cpematch/cpematch.go
@@ -0,0 +1,25 @@
+// CPE match feed 1.0 parser.
+package cpematch
+
+// CPE name
+type Name struct {
+  Cpe22Uri string `json:"cpe22Uri"`
+  Cpe23Uri string `json:"cpe23Uri"`
+}
+
+// CPE match string or range
+type Match struct {
+  Vulnerable *bool `json:"vulnerable"`
+  Cpe22Uri string `json:"cpe22Uri"`
+  Cpe23Uri string `json:"cpe23Uri"`
+  VersionStartExcluding string `json:"versionStartExcluding"`
+  VersionStartIncluding string `json:"versionStartIncluding"`
+  VersionEndExcluding string `json:"versionEndExcluding"`
+  VersionEndIncluding string `json:"versionEndIncluding"`
+  Names []Name `json:"cpe_name"` // CPE match strings
+}
+
+// CPE matches
+type Matches struct {
+  Matches []Match `json:"matches"` // Array of CPE matches
+}
diff --git a/internal/cpematch/cpematch_test.go b/internal/cpematch/cpematch_test.go
new file mode 100644
index 0000000..7d69410
--- /dev/null
+++ b/internal/cpematch/cpematch_test.go
@@ -0,0 +1,100 @@
+package cpematch
+
+import (
+  "compress/gzip"
+  "encoding/json"
+  "os"
+  "reflect"
+  "testing"
+)
+
+func TestMatchesUnmarshal(t *testing.T) {
+  // expected data
+  exp := Matches {
+    Matches: []Match {
+      Match {
+        Cpe23Uri: "cpe:2.3:a:101_project:101:*:*:*:*:*:node.js:*:*",
+        VersionStartIncluding: "1.0.0",
+        VersionEndIncluding: "1.6.3",
+        Names: []Name {
+          Name {
+            Cpe23Uri: "cpe:2.3:a:101_project:101:1.0.0:*:*:*:*:node.js:*:*",
+          },
+
+          Name {
+            Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.0:*:*:*:*:node.js:*:*",
+          },
+
+          Name {
+            Cpe23Uri: "cpe:2.3:a:101_project:101:1.1.1:*:*:*:*:node.js:*:*",
+          },
+        },
+      },
+
+      Match {
+        Cpe23Uri: "cpe:2.3:a:1password:1password:*:*:*:*:*:macos:*:*",
+        VersionStartIncluding: "7.7.0",
+        VersionEndExcluding: "7.8.7",
+        Names: []Name {
+          Name {
+            Cpe23Uri: "cpe:2.3:a:1password:1password:7.7.0:*:*:*:*:macos:*:*",
+          },
+        },
+      },
+
+      Match {
+        Cpe23Uri: "cpe:2.3:a:zimbra:collaboration:*:*:*:*:*:*:*:*",
+        VersionStartExcluding: "8.8.0",
+        VersionEndExcluding: "8.8.15",
+        Names: []Name {
+          Name {
+            Cpe23Uri: "cpe:2.3:a:zimbra:collaboration:8.8.6:*:*:*:*:*:*:*",
+          },
+
+          Name {
+            Cpe23Uri: "cpe:2.3:a:zimbra:collaboration:8.8.7:*:*:*:*:*:*:*",
+          },
+
+          Name {
+            Cpe23Uri: "cpe:2.3:a:zimbra:collaboration:8.8.8:-:*:*:*:*:*:*",
+          },
+
+          Name {
+            Cpe23Uri: "cpe:2.3:a:zimbra:collaboration:8.8.8:p1:*:*:*:*:*:*",
+          },
+        },
+      },
+    },
+  }
+
+  // open test data
+  f, err := os.Open("testdata/test-0.json.gz")
+  if err != nil {
+    t.Error(err)
+    return
+  }
+  defer f.Close()
+
+  // create gzip reader
+  gz, err := gzip.NewReader(f)
+  if err != nil {
+    t.Error(err)
+    return
+  }
+  defer gz.Close()
+
+  // create json decoder
+  d := json.NewDecoder(gz)
+  var got Matches
+
+  // decode match data, check for error
+  if err := d.Decode(&got); err != nil {
+    t.Error(err)
+    return
+  }
+
+  // check for match
+  if !reflect.DeepEqual(got, exp) {
+    t.Errorf("got \"%v\", exp \"%v\"", got, exp)
+  }
+}
diff --git a/internal/cpematch/testdata/test-0.json.gz b/internal/cpematch/testdata/test-0.json.gz
new file mode 100644
index 0000000..611bd58
Binary files /dev/null and b/internal/cpematch/testdata/test-0.json.gz differ
-- 
cgit v1.2.3