aboutsummaryrefslogtreecommitdiff
path: root/internal/cvss/cvss.go
blob: 6f1cafe4d9269f2d9886703a76342554033fdd96 (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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// CVSS vector parser.
package cvss

import (
  "strings"
)

// CVSS v3.0 prefix
var v30Prefix = "CVSS:3.0/"

// CVSS 3.0 vector.
type v30Vector []v3Metric

// Convert vector to string
func (v v30Vector) String() string {
  // convert to slice of metrics
  metrics := []v3Metric(v)

  // build vector
  r := make([]string, len(metrics))
  for i, m := range(metrics) {
    r[i] = m.String()
  }

  // build and return string
  return v30Prefix + strings.Join(r, "/")
}

// Return CVSS version.
func (v30Vector) Version() Version {
  return V30
}

// Return metrics in this vector.
func (v v30Vector) Metrics() []Metric {
  // build result
  r := make([]Metric, len(v))
  for i, m := range(v) {
    r[i] = m
  }

  // return result
  return r
}

// create CVSS 3.0 vector from string
func newV30Vector(s string) (Vector, error) {
  strs := strings.Split(s, "/")
  r := make([]v3Metric, len(strs))

  // walk metric strings
  for i, ms := range(strs) {
    // convert metric string to metric
    m, err := getV3Metric(V30, ms)
    if err != nil {
      return nil, err
    }

    // add to results
    r[i] = m
  }

  // build and return vector
  return v30Vector(r), nil
}

// CVSS v3.1 prefix
var v31Prefix = "CVSS:3.1/"

// CVSS 3.1 vector.
type v31Vector []v3Metric

// Convert vector to string
func (v v31Vector) String() string {
  // convert to slice of metrics
  metrics := []v3Metric(v)

  // build vector
  r := make([]string, len(metrics))
  for i, m := range(metrics) {
    r[i] = m.String()
  }

  // build and return string
  return v31Prefix + strings.Join(r, "/")
}

// Return CVSS version.
func (v31Vector) Version() Version {
  return V31
}

// Return metrics in this vector.
func (v v31Vector) Metrics() []Metric {
  // build result
  r := make([]Metric, len(v))
  for i, m := range(v) {
    r[i] = m
  }

  // return result
  return r
}

// create CVSS 3.1 vector from string
func newV31Vector(s string) (Vector, error) {
  strs := strings.Split(s, "/")
  r := make([]v3Metric, len(strs))

  // walk metric strings
  for i, ms := range(strs) {
    // get metric from string
    m, err := getV3Metric(V31, ms)
    if err != nil {
      return nil, err
    }

    // add to results
    r[i] = m
  }

  // build and return vector
  return v31Vector(r), nil
}

// Metric key.
type Key interface {
  // Get full name.
  Name() string

  // Get category.
  Category() Category

  // Return string representation.
  String() string
}

// CVSS metric.
type Metric interface {
  // Get metric key.
  Key() Key

  // Return string representation of metric.
  String() string
}

// CVSS metric vector.
type Vector interface {
  // Get CVSS version.
  Version() Version

  // Get CVSS vector string.
  String() string

  // Return metrics in this vector.
  Metrics() []Metric
}

// Create new CVSS vector from vector string.
func NewVector(s string) (Vector, error) {
  if len(s) > len(v31Prefix) && s[:len(v31Prefix)] == v31Prefix {
    // create CVSS v2.0 vector.
    return newV31Vector(s[len(v31Prefix):])
  } else if len(s) > len(v30Prefix) && s[:len(v30Prefix)] == v30Prefix {
    // create CVSS v3.0 vector.
    return newV30Vector(s[len(v30Prefix):])
  } else {
    // create CVSS V2 vector
    return newV2Vector(s)
  }
}