diff options
author | Paul Duncan <pabs@pablotron.org> | 2022-01-31 11:09:58 -0500 |
---|---|---|
committer | Paul Duncan <pabs@pablotron.org> | 2022-01-31 11:09:58 -0500 |
commit | b3dc36421f133ea6983574891720e974cf7974dd (patch) | |
tree | c6375903fa820bd0ac64ce40827c2c8302d38737 /internal/cvss/cvss.go | |
download | cvez-b3dc36421f133ea6983574891720e974cf7974dd.tar.bz2 cvez-b3dc36421f133ea6983574891720e974cf7974dd.zip |
initial commit
Diffstat (limited to 'internal/cvss/cvss.go')
-rw-r--r-- | internal/cvss/cvss.go | 926 |
1 files changed, 926 insertions, 0 deletions
diff --git a/internal/cvss/cvss.go b/internal/cvss/cvss.go new file mode 100644 index 0000000..e50f718 --- /dev/null +++ b/internal/cvss/cvss.go @@ -0,0 +1,926 @@ +// CVSS vector parser. +package cvss + +import ( + "fmt" + "strings" +) + +//go:generate stringer -linecomment -type=Version +//go:generate stringer -linecomment -type=MetricCategory +//go:generate stringer -linecomment -type=V2MetricKey +//go:generate stringer -linecomment -type=V2Metric +//go:generate stringer -linecomment -type=V3MetricKey +//go:generate stringer -linecomment -type=V3Metric + +// CVSS version +type Version byte + +const ( + V20 Version = iota // 2.0 + V30 // 3.0 + V31 // 3.1 +) + +// CVSS metric category. +type MetricCategory byte + +const ( + Base MetricCategory = iota // Base + Temporal // Temporal + Environmental // Environmental +) + +// CVSS metric key +type V2MetricKey byte + +const ( + V2AccessVector V2MetricKey = iota // AV + V2AccessComplexity // AC + V2Authentication // Au + V2ConfidentialityImpact // C + V2IntegrityImpact // I + V2AvailabilityImpact // A + V2Exploitability // E + V2RemediationLevel // RL + V2ReportConfidence // RC + V2CollateralDamagePotential // CDP + V2TargetDistribution // TD + V2ConfidentialityRequirement // CR + V2IntegrityRequirement // IR + V2AvailabilityRequirement // AR +) + +// CVSS V2 metric key info lut +var v2MetricKeys = map[V2MetricKey]struct { + Name string + Category MetricCategory +} { + V2AccessVector: { "Access Vector", Base }, + V2AccessComplexity: { "Access Complexity", Base }, + V2Authentication: { "Authentication", Base }, + V2ConfidentialityImpact: { "Confidentiality Impact", Base }, + V2IntegrityImpact: { "Integrity Impact", Base }, + V2AvailabilityImpact: { "Availability Impact", Base }, + V2Exploitability: { "Exploitability", Temporal }, + V2RemediationLevel: { "Remediation Level", Temporal }, + V2ReportConfidence: { "Report Confidence", Temporal }, + V2CollateralDamagePotential: { "Collateral Damage Potential", Environmental }, + V2TargetDistribution: { "Target Distribution", Environmental }, + V2ConfidentialityRequirement: { "Confidentiality Requirement", Environmental }, + V2IntegrityRequirement: { "Integrity Requirement", Environmental }, + V2AvailabilityRequirement: { "Availability Requirement", Environmental }, +} + +// v2 metric key IDs lut +var v2MetricKeyIds = map[string]V2MetricKey { + "AV": V2AccessVector, + "AC": V2AccessComplexity, + "Au": V2Authentication, + "C": V2ConfidentialityImpact, + "I": V2IntegrityImpact, + "A": V2AvailabilityImpact, + "E": V2Exploitability, + "RL": V2RemediationLevel, + "RC": V2ReportConfidence, + "CDP": V2CollateralDamagePotential, + "TD": V2TargetDistribution, + "CR": V2ConfidentialityRequirement, + "IR": V2IntegrityRequirement, + "AR": V2AvailabilityRequirement, +} + +// Get metric key from string. +func GetV2MetricKeyFromString(s string) (V2MetricKey, error) { + k, ok := v2MetricKeyIds[s] + if ok { + return k, nil + } else { + return V2AccessVector, fmt.Errorf("unknown metric key: %s", s) + } +} + +// Get metric key name. +func (k V2MetricKey) Name() string { + return v2MetricKeys[k].Name +} + +// Get metric key category. +func (k V2MetricKey) Category() MetricCategory { + return v2MetricKeys[k].Category +} + +// CVSS v2 metric value +type V2Metric byte + +const ( + V2AVNetwork V2Metric = iota // AV:N + V2AVAdjacentNetwork // AV:A + V2AVLocal // AV:L + + V2ACLow // AC:L + V2ACMedium // AC:L + V2ACHigh // AC:H + + V2AuMultiple // Au:M + V2AuSingle // Au:S + V2AuNone // Au:N + + V2CNone // C:N + V2CPartial // C:P + V2CComplete // C:C + + V2INone // I:N + V2IPartial // I:P + V2IComplete // I:C + + V2ANone // A:N + V2APartial // A:P + V2AComplete // A:C + + V2ENotDefined // E:ND + V2EUnproven // E:U + V2EProofOfConcept // E:POC + V2EFunctional // E:F + V2EHigh // E:H + + V2RLOfficialFix // RL:OF + V2RLTemporaryFix // RL:TF + V2RLWorkaround // RL:W + V2RLUnavailable // RL:U + V2RLNotDefined // RL:ND + + V2RCUnconfirmed // RC:UC + V2RCUncorroborated // RC:UR + V2RCConfirmed // RC:C + V2RCNotDefined // RC:ND + + V2CDPNone // CDP:N + V2CDPLow // CDP:L + V2CDPLowMedium // CDP:LM + V2CDPMediumHigh // CDP:MH + V2CDPHigh // CDP:H + V2CDPNotDefined // CDP:ND + + V2TDNone // TD:N + V2TDLow // TD:L + V2TDMedium // TD:M + V2TDHigh // TD:H + V2TDNotDefined // TD:ND + + V2CRLow // CR:L + V2CRMedium // CR:M + V2CRHigh // CR:H + V2CRNotDefined // CR:ND + + V2IRLow // IR:L + V2IRMedium // IR:M + V2IRHigh // IR:H + V2IRNotDefined // IR:ND + + V2ARLow // AR:L + V2ARMedium // AR:M + V2ARHigh // AR:H + V2ARNotDefined // AR:ND +) + +// map of metrics to metric keys +var v2MetricKeyLut = map[V2Metric]V2MetricKey { + V2AVNetwork: V2AccessVector, + V2AVAdjacentNetwork: V2AccessVector, + V2AVLocal: V2AccessVector, + + V2ACLow: V2AccessComplexity, + V2ACMedium: V2AccessComplexity, + V2ACHigh: V2AccessComplexity, + + V2AuMultiple: V2Authentication, + V2AuSingle: V2Authentication, + V2AuNone: V2Authentication, + + V2CNone: V2ConfidentialityImpact, + V2CPartial: V2ConfidentialityImpact, + V2CComplete: V2ConfidentialityImpact, + + V2INone: V2IntegrityImpact, + V2IPartial: V2IntegrityImpact, + V2IComplete: V2IntegrityImpact, + + V2ANone: V2AvailabilityImpact, + V2APartial: V2AvailabilityImpact, + V2AComplete: V2AvailabilityImpact, + + V2ENotDefined: V2Exploitability, + V2EUnproven: V2Exploitability, + V2EProofOfConcept: V2Exploitability, + V2EFunctional: V2Exploitability, + V2EHigh: V2Exploitability, + + V2RLOfficialFix: V2RemediationLevel, + V2RLTemporaryFix: V2RemediationLevel, + V2RLWorkaround: V2RemediationLevel, + V2RLUnavailable: V2RemediationLevel, + V2RLNotDefined: V2RemediationLevel, + + V2RCUnconfirmed: V2ReportConfidence, + V2RCUncorroborated: V2ReportConfidence, + V2RCConfirmed: V2ReportConfidence, + V2RCNotDefined: V2ReportConfidence, + + V2CDPNone: V2CollateralDamagePotential, + V2CDPLow: V2CollateralDamagePotential, + V2CDPLowMedium: V2CollateralDamagePotential, + V2CDPMediumHigh: V2CollateralDamagePotential, + V2CDPHigh: V2CollateralDamagePotential, + V2CDPNotDefined: V2CollateralDamagePotential, + + V2TDNone: V2TargetDistribution, + V2TDLow: V2TargetDistribution, + V2TDMedium: V2TargetDistribution, + V2TDHigh: V2TargetDistribution, + V2TDNotDefined: V2TargetDistribution, + + V2CRLow: V2ConfidentialityRequirement, + V2CRMedium: V2ConfidentialityRequirement, + V2CRHigh: V2ConfidentialityRequirement, + V2CRNotDefined: V2ConfidentialityRequirement, + + V2IRLow: V2IntegrityRequirement, + V2IRMedium: V2IntegrityRequirement, + V2IRHigh: V2IntegrityRequirement, + V2IRNotDefined: V2IntegrityRequirement, + + V2ARLow: V2AvailabilityRequirement, + V2ARMedium: V2AvailabilityRequirement, + V2ARHigh: V2AvailabilityRequirement, + V2ARNotDefined: V2AvailabilityRequirement, +} + +// map of metric strings to metrics +var v2MetricStrLut = map[string]V2Metric { + "AV:N": V2AVNetwork, + "AV:A": V2AVAdjacentNetwork, + "AV:L": V2AVLocal, + + "AC:L": V2ACLow, + "AC:M": V2ACMedium, + "AC:H": V2ACHigh, + + "Au:M": V2AuMultiple, + "Au:S": V2AuSingle, + "Au:N": V2AuNone, + + "C:N": V2CNone, + "C:P": V2CPartial, + "C:C": V2CComplete, + + "I:N": V2INone, + "I:P": V2IPartial, + "I:C": V2IComplete, + + "A:N": V2ANone, + "A:P": V2APartial, + "A:C": V2AComplete, + + "E:ND": V2ENotDefined, + "E:U": V2EUnproven, + "E:POC": V2EProofOfConcept, + "E:F": V2EFunctional, + "E:H": V2EHigh, + + "RL:OF": V2RLOfficialFix, + "RL:TF": V2RLTemporaryFix, + "RL:W": V2RLWorkaround, + "RL:U": V2RLUnavailable, + "RL:ND": V2RLNotDefined, + + "RC:UC": V2RCUnconfirmed, + "RC:UR": V2RCUncorroborated, + "RC:C": V2RCConfirmed, + "RC:ND": V2RCNotDefined, + + "CDP:N": V2CDPNone, + "CDP:L": V2CDPLow, + "CDP:LM": V2CDPLowMedium, + "CDP:MH": V2CDPMediumHigh, + "CDP:H": V2CDPHigh, + "CDP:ND": V2CDPNotDefined, + + "TD:N": V2TDNone, + "TD:L": V2TDLow, + "TD:M": V2TDMedium, + "TD:H": V2TDHigh, + "TD:ND": V2TDNotDefined, + + "CR:L": V2CRLow, + "CR:M": V2CRMedium, + "CR:H": V2CRHigh, + "CR:ND": V2CRNotDefined, + + "IR:L": V2IRLow, + "IR:M": V2IRMedium, + "IR:H": V2IRHigh, + "IR:ND": V2IRNotDefined, + + "AR:L": V2ARLow, + "AR:M": V2ARMedium, + "AR:H": V2ARHigh, + "AR:ND": V2ARNotDefined, +} + +// Convert string to CVSS 2.0 metric. +func GetV2MetricFromString(s string) (V2Metric, error) { + // get metric + m, ok := v2MetricStrLut[s] + if !ok { + return V2AVNetwork, fmt.Errorf("invalid metric: %s", s) + } + + // return success + return m, nil +} + +// CVSS 2.0 vector. +type v2Vector []V2Metric + +// Convert vector to string +func (v v2Vector) String() string { + // convert to slice of metrics + metrics := []V2Metric(v) + + // build vector + r := make([]string, len(metrics)) + for i, m := range(metrics) { + r[i] = m.String() + } + + // build and return string + return strings.Join(r, "/") +} + +// Return CVSS version. +func (v2Vector) Version() Version { + return V20 +} + +// create CVSS 2.0 vector from string +func NewV2VectorFromString(s string) (Vector, error) { + strs := strings.Split(s, "/") + r := make([]V2Metric, len(strs)) + + // walk metric strings + for i, ms := range(strs) { + // convert string to vector + m, err := GetV2MetricFromString(ms) + if err != nil { + return nil, err + } + + // add to results + r[i] = m + } + + // build and return vector + return v2Vector(r), nil +} + +// CVSS v3 metric key +type V3MetricKey byte + +const ( + V3AttackVector V3MetricKey = iota // AV + V3AttackComplexity // AC + V3PrivilegesRequired // PR + V3UserInteraction // UI + V3Scope // S + V3Confidentiality // C + V3Integrity // I + V3Availability // A + V3ExploitCodeMaturity // E + V3RemediationLevel // RL + V3ReportConfidence // RC + V3ConfidentialityRequirement // CR + V3IntegrityRequirement // IR + V3AvailabilityRequirement // AR + V3ModifiedAttackVector // MAV + V3ModifiedAttackComplexity // MAC + V3ModifiedPrivilegesRequired // MPR + V3ModifiedUserInteraction // MUI + V3ModifiedScope // MS + V3ModifiedConfidentiality // MC + V3ModifiedIntegrity // MI + V3ModifiedAvailability // MA +) + +// CVSS V3 metric key info lut +var v3MetricKeys = map[V3MetricKey]struct { + Name string + Category MetricCategory +} { + V3AttackVector: { "Attack Vector", Base }, + V3AttackComplexity: { "Attack Complexity", Base }, + V3PrivilegesRequired: { "Privileges Required", Base }, + V3UserInteraction: { "User Interaction", Base }, + V3Scope: { "Scope", Base }, + V3Confidentiality: { "Confidentiality", Base }, + V3Integrity: { "Integrity", Base }, + V3Availability: { "Availability", Base }, + V3ExploitCodeMaturity: { "Exploit Code Maturity", Temporal }, + V3RemediationLevel: { "Remediation Level", Temporal }, + V3ReportConfidence: { "Report Confidence", Temporal }, + V3ConfidentialityRequirement: { "Confidentiality Requirement", Environmental }, + V3IntegrityRequirement: { "Integrity Requirement", Environmental }, + V3AvailabilityRequirement: { "Availability Requirement", Environmental }, + V3ModifiedAttackVector: { "Modified Attack Vector", Environmental }, + V3ModifiedAttackComplexity: { "Modified Attack Complexity", Environmental }, + V3ModifiedPrivilegesRequired: { "Modified Privileges Required", Environmental }, + V3ModifiedUserInteraction: { "Modified User Interaction", Environmental }, + V3ModifiedScope: { "Modified Scope", Environmental }, + V3ModifiedConfidentiality: { "Modified Confidentiality", Environmental }, + V3ModifiedIntegrity: { "Modified Integrity", Environmental }, + V3ModifiedAvailability: { "Modified Availability", Environmental }, +} + +// metric key IDs lut +var v3MetricKeyIds = map[string]V3MetricKey { + "AV": V3AttackVector, + "AC": V3AttackComplexity, + "PR": V3PrivilegesRequired, + "UI": V3UserInteraction, + "S": V3Scope, + "C": V3Confidentiality, + "I": V3Integrity, + "A": V3Availability, + "E": V3ExploitCodeMaturity, + "RL": V3RemediationLevel, + "RC": V3ReportConfidence, + "CR": V3ConfidentialityRequirement, + "IR": V3IntegrityRequirement, + "AR": V3AvailabilityRequirement, + "MAV": V3ModifiedAttackVector, + "MAC": V3ModifiedAttackComplexity, + "MPR": V3ModifiedPrivilegesRequired, + "MUI": V3ModifiedUserInteraction, + "MS": V3ModifiedScope, + "MC": V3ModifiedConfidentiality, + "MI": V3ModifiedIntegrity, + "MA": V3ModifiedAvailability, +} + +// Get metric key from string. +func GetV3MetricKeyFromString(s string) (V3MetricKey, error) { + k, ok := v3MetricKeyIds[s] + if ok { + return k, nil + } else { + return V3AttackVector, fmt.Errorf("unknown metric key: %s", s) + } +} + +// Get metric key name. +func (k V3MetricKey) Name() string { + return v3MetricKeys[k].Name +} + +// Get metric key category. +func (k V3MetricKey) Category() MetricCategory { + return v3MetricKeys[k].Category +} + +// metric value +type V3Metric byte + +const ( + V3AVNetwork V3Metric = iota // AV:N + V3AVAdjacentNetwork // AV:A + V3AVLocal // AV:L + V3AVPhysical // AV:P + + V3ACLow // AC:L + V3ACHigh // AC:H + + V3PRNone // PR:N + V3PRLow // PR:L + V3PRHigh // PR:H + + V3UINone // UI:N + V3UIRequired // UI:R + + V3SUnchanged // S:U + V3SChanged // S:C + + V3CHigh // C:H + V3CLow // C:L + V3CNone // C:N + + V3IHigh // I:H + V3ILow // I:L + V3INone // I:N + + V3AHigh // A:H + V3ALow // A:L + V3ANone // A:N + + V3ENotDefined // E:X + V3EHigh // E:H + V3EFunctional // E:F + V3EProofOfConcept // E:P + V3EUnproven // E:U + + V3RLNotDefined // RL:X + V3RLUnavailable // RL:U + V3RLWorkaround // RL:W + V3RLTemporaryFix // RL:T + V3RLOfficialFix // RL:O + + V3RCNotDefined // RC:X + V3RCConfirmed // RC:C + V3RCReasonable // RC:R + V3RCUnknown // RC:U + + V3CRNotDefined // CR:X + V3CRHigh // CR:H + V3CRMedium // CR:M + V3CRLow // CR:L + + V3IRNotDefined // IR:X + V3IRHigh // IR:H + V3IRMedium // IR:M + V3IRLow // IR:L + + V3ARNotDefined // AR:X + V3ARHigh // AR:H + V3ARMedium // AR:M + V3ARLow // AR:L + + V3MAVNotDefined // MAV:X + V3MAVNetwork // MAV:N + V3MAVAdjacentNetwork // MAV:A + V3MAVLocal // MAV:L + V3MAVPhysical // MAV:P + + V3MACNotDefined // MAC:X + V3MACLow // MAC:L + V3MACHigh // MAC:H + + V3MMRNotDefined // MPR:X + V3MPRLow // MPR:L + V3MPRHigh // MPR:H + + V3MUINotDefined // MUI:X + V3MUINone // MUI:N + V3MUIRequired // MUI:R + + V3MSNotDefined // MMS:X + V3MSUnchanged // MMS:U + V3MSChanged // MMS:C + + V3MCNotDefined // MC:X + V3MCHigh // MC:H + V3MCLow // MC:L + V3MCNone // MC:N + + V3MINotDefined // MI:X + V3MIHigh // MI:H + V3MILow // MI:L + V3MINone // MI:N + + V3MANotDefined // MA:X + V3MAHigh // MA:H + V3MALow // MA:L + V3MANone // MA:N + V3UnknownMetric // unknown +) + +// map of metrics to metric keys +var v3MetricKeyLut = map[V3Metric]V3MetricKey { + V3AVNetwork: V3AttackVector, // AV:N + V3AVAdjacentNetwork: V3AttackVector, // AV:A + V3AVLocal: V3AttackVector, // AV:L + V3AVPhysical: V3AttackVector, // AV:P + + V3ACLow: V3AttackComplexity, // AC:L + V3ACHigh: V3AttackComplexity, // AC:H + + V3PRNone: V3PrivilegesRequired, // PR:N + V3PRLow: V3PrivilegesRequired, // PR:L + V3PRHigh: V3PrivilegesRequired, // PR:H + + V3UINone: V3UserInteraction, // UI:N + V3UIRequired: V3UserInteraction, // UI:R + + V3SUnchanged: V3Scope, // S:U + V3SChanged: V3Scope, // S:C + + V3CHigh: V3Confidentiality, // C:H + V3CLow: V3Confidentiality, // C:L + V3CNone: V3Confidentiality, // C:N + + V3IHigh: V3Integrity, // I:H + V3ILow: V3Integrity, // I:L + V3INone: V3Integrity, // I:N + + V3AHigh: V3Availability, // A:H + V3ALow: V3Availability, // A:L + V3ANone: V3Availability, // A:N + + V3ENotDefined: V3ExploitCodeMaturity, // E:X + V3EHigh: V3ExploitCodeMaturity, // E:H + V3EFunctional: V3ExploitCodeMaturity, // E:F + V3EProofOfConcept: V3ExploitCodeMaturity, // E:P + V3EUnproven: V3ExploitCodeMaturity, // E:U + + V3RLNotDefined: V3RemediationLevel, // RL:X + V3RLUnavailable: V3RemediationLevel, // RL:U + V3RLWorkaround: V3RemediationLevel, // RL:W + V3RLTemporaryFix: V3RemediationLevel, // RL:T + V3RLOfficialFix: V3RemediationLevel, // RL:O + + V3RCNotDefined: V3ReportConfidence, // RC:X + V3RCConfirmed: V3ReportConfidence, // RC:C + V3RCReasonable: V3ReportConfidence, // RC:R + V3RCUnknown: V3ReportConfidence, // RC:U + + V3CRNotDefined: V3ConfidentialityRequirement, // CR:X + V3CRHigh: V3ConfidentialityRequirement, // CR:H + V3CRMedium: V3ConfidentialityRequirement, // CR:M + V3CRLow: V3ConfidentialityRequirement, // CR:L + + V3IRNotDefined: V3IntegrityRequirement, // IR:X + V3IRHigh: V3IntegrityRequirement, // IR:H + V3IRMedium: V3IntegrityRequirement, // IR:M + V3IRLow: V3IntegrityRequirement, // IR:L + + V3ARNotDefined: V3AvailabilityRequirement, // AR:X + V3ARHigh: V3AvailabilityRequirement, // AR:H + V3ARMedium: V3AvailabilityRequirement, // AR:M + V3ARLow: V3AvailabilityRequirement, // AR:L + + V3MAVNotDefined: V3ModifiedAttackVector, // MAV:X + V3MAVNetwork: V3ModifiedAttackVector, // MAV:N + V3MAVAdjacentNetwork: V3ModifiedAttackVector, // MAV:A + V3MAVLocal: V3ModifiedAttackVector, // MAV:L + V3MAVPhysical: V3ModifiedAttackVector, // MAV:P + + V3MACNotDefined: V3ModifiedAttackComplexity, // MAC:X + V3MACLow: V3ModifiedAttackComplexity, // MAC:L + V3MACHigh: V3ModifiedAttackComplexity, // MAC:H + + V3MMRNotDefined: V3ModifiedPrivilegesRequired, // MPR:X + V3MPRLow: V3ModifiedPrivilegesRequired, // MPR:L + V3MPRHigh: V3ModifiedPrivilegesRequired, // MPR:H + + V3MUINotDefined: V3ModifiedUserInteraction, // MUI:X + V3MUINone: V3ModifiedUserInteraction, // MUI:N + V3MUIRequired: V3ModifiedUserInteraction, // MUI:R + + V3MSNotDefined: V3ModifiedScope, // MMS:X + V3MSUnchanged: V3ModifiedConfidentiality, // MMS:U + V3MSChanged: V3ModifiedIntegrity, // MMS:C + + V3MCNotDefined: V3ModifiedConfidentiality, // MC:X + V3MCHigh: V3ModifiedConfidentiality, // MC:H + V3MCLow: V3ModifiedConfidentiality, // MC:L + V3MCNone: V3ModifiedConfidentiality, // MC:N + + V3MINotDefined: V3ModifiedIntegrity, // MI:X + V3MIHigh: V3ModifiedIntegrity, // MI:H + V3MILow: V3ModifiedIntegrity, // MI:L + V3MINone: V3ModifiedIntegrity, // MI:N + + V3MANotDefined: V3ModifiedAvailability, // MA:X + V3MAHigh: V3ModifiedAvailability, // MA:H + V3MALow: V3ModifiedAvailability, // MA:L + V3MANone: V3ModifiedAvailability, // MA:N +} + +// map of metric strings to metrics +var v3MetricStrLut = map[string]V3Metric { + "AV:N": V3AVNetwork, + "AV:A": V3AVAdjacentNetwork, + "AV:L": V3AVLocal, + "AV:P": V3AVPhysical, + + "AC:L": V3ACLow, + "AC:H": V3ACHigh, + + "PR:N": V3PRNone, + "PR:L": V3PRLow, + "PR:H": V3PRHigh, + + "UI:N": V3UINone, + "UI:R": V3UIRequired, + + "S:U": V3SUnchanged, + "S:C": V3SChanged, + + "C:H": V3CHigh, + "C:L": V3CLow, + "C:N": V3CNone, + + "I:H": V3IHigh, + "I:L": V3ILow, + "I:N": V3INone, + + "A:H": V3AHigh, + "A:L": V3ALow, + "A:N": V3ANone, + + "E:X": V3ENotDefined, + "E:H": V3EHigh, + "E:F": V3EFunctional, + "E:P": V3EProofOfConcept, + "E:U": V3EUnproven, + + "RL:X": V3RLNotDefined, + "RL:U": V3RLUnavailable, + "RL:W": V3RLWorkaround, + "RL:T": V3RLTemporaryFix, + "RL:O": V3RLOfficialFix, + + "RC:X": V3RCNotDefined, + "RC:C": V3RCConfirmed, + "RC:R": V3RCReasonable, + "RC:U": V3RCUnknown, + + "CR:X": V3CRNotDefined, + "CR:H": V3CRHigh, + "CR:M": V3CRMedium, + "CR:L": V3CRLow, + + "IR:X": V3IRNotDefined, + "IR:H": V3IRHigh, + "IR:M": V3IRMedium, + "IR:L": V3IRLow, + + "AR:X": V3ARNotDefined, + "AR:H": V3ARHigh, + "AR:M": V3ARMedium, + "AR:L": V3ARLow, + + "MAV:X": V3MAVNotDefined, + "MAV:N": V3MAVNetwork, + "MAV:A": V3MAVAdjacentNetwork, + "MAV:L": V3MAVLocal, + "MAV:P": V3MAVPhysical, + + "MAC:X": V3MACNotDefined, + "MAC:L": V3MACLow, + "MAC:H": V3MACHigh, + + "MPR:X": V3MMRNotDefined, + "MPR:L": V3MPRLow, + "MPR:H": V3MPRHigh, + + "MUI:X": V3MUINotDefined, + "MUI:N": V3MUINone, + "MUI:R": V3MUIRequired, + + "MMS:X": V3MSNotDefined, + "MMS:U": V3MSUnchanged, + "MMS:C": V3MSChanged, + + "MC:X": V3MCNotDefined, + "MC:H": V3MCHigh, + "MC:L": V3MCLow, + "MC:N": V3MCNone, + + "MI:X": V3MINotDefined, + "MI:H": V3MIHigh, + "MI:L": V3MILow, + "MI:N": V3MINone, + + "MA:X": V3MANotDefined, + "MA:H": V3MAHigh, + "MA:L": V3MALow, + "MA:N": V3MANone, +} + +// Convert string to CVSS 3.1 metric. +func GetV3MetricFromString(s string) (V3Metric, error) { + // get metric + m, ok := v3MetricStrLut[s] + if !ok { + return V3AVNetwork, fmt.Errorf("invalid metric: %s", s) + } + + // return success + return m, nil +} + +// 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 +} + +// create CVSS 3.0 vector from string +func NewV30VectorFromString(s string) (Vector, error) { + strs := strings.Split(s, "/") + r := make([]V3Metric, len(strs)) + + // walk metric strings + for i, ms := range(strs) { + // convert string to vector + m, err := GetV3MetricFromString(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 +} + +// create CVSS 3.1 vector from string +func NewV31VectorFromString(s string) (Vector, error) { + strs := strings.Split(s, "/") + r := make([]V3Metric, len(strs)) + + // walk metric strings + for i, ms := range(strs) { + // convert string to vector + m, err := GetV3MetricFromString(ms) + if err != nil { + return nil, err + } + + // add to results + r[i] = m + } + + // build and return vector + return v31Vector(r), nil +} + +// CVSS vector +type Vector interface { + // Get CVSS version. + Version() Version + + // Get CVSS vector string. + String() string +} + +// 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 NewV31VectorFromString(s[len(v31Prefix):]) + } else if len(s) > len(v30Prefix) && s[:len(v30Prefix)] == v30Prefix { + // create CVSS v3.0 vector. + return NewV30VectorFromString(s[len(v30Prefix):]) + } else { + // create CVSS V2 vector + return NewV2VectorFromString(s) + } +} |