aboutsummaryrefslogtreecommitdiff
path: root/util/util.go
blob: 1c4f84ccb7d6e1c875ba884e5e461f06380f123d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// utility functions
package util

import (
  "compress/gzip"
  "encoding/json"
  "encoding/xml"
  "github.com/pablotron/cvez/cisa"
  "github.com/pablotron/cvez/cpedict"
  "github.com/pablotron/cvez/cpematch"
  "github.com/pablotron/cvez/nvdmirror"
  nvd_feed "github.com/pablotron/cvez/feed"
  "os"
  "path/filepath"
)

// read gzipped file, pass reader to callback.
func gzOpen(path string, fn func(*gzip.Reader) error) error {
  f, err := os.Open(path)
  if err != nil {
    return err
  }
  defer f.Close()

  // create gzip reader
  r, err := gzip.NewReader(f)
  if err != nil {
    return err
  }

  // call func, return result
  return fn(r)
}

// read gzipped json, pass decoder to callback
func jsonGzOpen(path string, fn func(*json.Decoder) error) error {
  return gzOpen(path, func(r *gzip.Reader) error {
    return fn(json.NewDecoder(r))
  })
}

// read gzipped xml, pass decoder to callback
func xmlGzOpen(path string, fn func(*xml.Decoder) error) error {
  return gzOpen(path, func(r *gzip.Reader) error {
    return fn(xml.NewDecoder(r))
  })
}

type getFeedResult struct {
  feed nvd_feed.Feed
  err  error
}

// Read feed from file.
func getFeed(path string) getFeedResult {
  var feed nvd_feed.Feed

  err := jsonGzOpen(path, func(d *json.Decoder) error {
    return d.Decode(&feed)
  })

  return getFeedResult { feed, err }
}

// Load CVE feeds in parallel.
func GetFeeds(cacheDir string, updates []nvdmirror.Update) ([]nvd_feed.Feed, error) {
  numFeeds := 0

  // load feeds in parallel
  ch := make(chan getFeedResult)
  for _, row := range(updates) {
    if row.Type == nvdmirror.UpdateCveYear {
      numFeeds += 1
      go func(path string) {
        ch <- getFeed(path)
      }(filepath.Join(cacheDir, row.Path))
    }
  }

  // collect feeds
  feeds := make([]nvd_feed.Feed, numFeeds)
  for i := 0; i < numFeeds; i++ {
    if r := <-ch; r.err != nil {
      return feeds, r.err
    } else {
      feeds[i] = r.feed
    }
  }

  return feeds, nil
}

// Read cpe matches from file.
func GetCpeMatches(path string) (cpematch.Matches, error) {
  var matches cpematch.Matches

  return matches, jsonGzOpen(path, func(d *json.Decoder) error {
    return d.Decode(&matches)
  })
}

// Read cpe dictionary from file.
func GetCpeDict(path string) (cpedict.Dictionary, error) {
  var dict cpedict.Dictionary

  return dict, xmlGzOpen(path, func(d *xml.Decoder) error {
    return d.Decode(&dict)
  })
}

// Read cisa catalog from file.
func GetCisaCatalog(path string) (cisa.Catalog, error) {
  var cat cisa.Catalog

  f, err := os.Open(path)
  if err != nil {
    return cat, err
  }
  defer f.Close()

  // decode/return catalog
  d := json.NewDecoder(f)
  return cat, d.Decode(&cat)
}