83#define G_LOG_DOMAIN "libgvm base"
100#define AV_ADJACENT_NETWORK 0.646
101#define AV_LOCAL 0.395
107#define AC_MEDIUM 0.61
113#define Au_MULTIPLE_INSTANCES 0.45
114#define Au_SINGLE_INSTANCE 0.56
121#define C_PARTIAL 0.275
122#define C_COMPLETE 0.660
128#define I_PARTIAL 0.275
129#define I_COMPLETE 0.660
135#define A_PARTIAL 0.275
136#define A_COMPLETE 0.660
263#define CVSS_METRICS_STR_BLANK "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
268#define CVSS_MACROVECTOR_BLANK "XXXXXX"
351 {
"000000", 10}, {
"000001", 9.9}, {
"000010", 9.8}, {
"000011", 9.5},
352 {
"000020", 9.5}, {
"000021", 9.2}, {
"000100", 10}, {
"000101", 9.6},
353 {
"000110", 9.3}, {
"000111", 8.7}, {
"000120", 9.1}, {
"000121", 8.1},
354 {
"000200", 9.3}, {
"000201", 9}, {
"000210", 8.9}, {
"000211", 8},
355 {
"000220", 8.1}, {
"000221", 6.8}, {
"001000", 9.8}, {
"001001", 9.5},
356 {
"001010", 9.5}, {
"001011", 9.2}, {
"001020", 9}, {
"001021", 8.4},
357 {
"001100", 9.3}, {
"001101", 9.2}, {
"001110", 8.9}, {
"001111", 8.1},
358 {
"001120", 8.1}, {
"001121", 6.5}, {
"001200", 8.8}, {
"001201", 8},
359 {
"001210", 7.8}, {
"001211", 7}, {
"001220", 6.9}, {
"001221", 4.8},
360 {
"002001", 9.2}, {
"002011", 8.2}, {
"002021", 7.2}, {
"002101", 7.9},
361 {
"002111", 6.9}, {
"002121", 5}, {
"002201", 6.9}, {
"002211", 5.5},
362 {
"002221", 2.7}, {
"010000", 9.9}, {
"010001", 9.7}, {
"010010", 9.5},
363 {
"010011", 9.2}, {
"010020", 9.2}, {
"010021", 8.5}, {
"010100", 9.5},
364 {
"010101", 9.1}, {
"010110", 9}, {
"010111", 8.3}, {
"010120", 8.4},
365 {
"010121", 7.1}, {
"010200", 9.2}, {
"010201", 8.1}, {
"010210", 8.2},
366 {
"010211", 7.1}, {
"010220", 7.2}, {
"010221", 5.3}, {
"011000", 9.5},
367 {
"011001", 9.3}, {
"011010", 9.2}, {
"011011", 8.5}, {
"011020", 8.5},
368 {
"011021", 7.3}, {
"011100", 9.2}, {
"011101", 8.2}, {
"011110", 8},
369 {
"011111", 7.2}, {
"011120", 7}, {
"011121", 5.9}, {
"011200", 8.4},
370 {
"011201", 7}, {
"011210", 7.1}, {
"011211", 5.2}, {
"011220", 5},
371 {
"011221", 3}, {
"012001", 8.6}, {
"012011", 7.5}, {
"012021", 5.2},
372 {
"012101", 7.1}, {
"012111", 5.2}, {
"012121", 2.9}, {
"012201", 6.3},
373 {
"012211", 2.9}, {
"012221", 1.7}, {
"100000", 9.8}, {
"100001", 9.5},
374 {
"100010", 9.4}, {
"100011", 8.7}, {
"100020", 9.1}, {
"100021", 8.1},
375 {
"100100", 9.4}, {
"100101", 8.9}, {
"100110", 8.6}, {
"100111", 7.4},
376 {
"100120", 7.7}, {
"100121", 6.4}, {
"100200", 8.7}, {
"100201", 7.5},
377 {
"100210", 7.4}, {
"100211", 6.3}, {
"100220", 6.3}, {
"100221", 4.9},
378 {
"101000", 9.4}, {
"101001", 8.9}, {
"101010", 8.8}, {
"101011", 7.7},
379 {
"101020", 7.6}, {
"101021", 6.7}, {
"101100", 8.6}, {
"101101", 7.6},
380 {
"101110", 7.4}, {
"101111", 5.8}, {
"101120", 5.9}, {
"101121", 5},
381 {
"101200", 7.2}, {
"101201", 5.7}, {
"101210", 5.7}, {
"101211", 5.2},
382 {
"101220", 5.2}, {
"101221", 2.5}, {
"102001", 8.3}, {
"102011", 7},
383 {
"102021", 5.4}, {
"102101", 6.5}, {
"102111", 5.8}, {
"102121", 2.6},
384 {
"102201", 5.3}, {
"102211", 2.1}, {
"102221", 1.3}, {
"110000", 9.5},
385 {
"110001", 9}, {
"110010", 8.8}, {
"110011", 7.6}, {
"110020", 7.6},
386 {
"110021", 7}, {
"110100", 9}, {
"110101", 7.7}, {
"110110", 7.5},
387 {
"110111", 6.2}, {
"110120", 6.1}, {
"110121", 5.3}, {
"110200", 7.7},
388 {
"110201", 6.6}, {
"110210", 6.8}, {
"110211", 5.9}, {
"110220", 5.2},
389 {
"110221", 3}, {
"111000", 8.9}, {
"111001", 7.8}, {
"111010", 7.6},
390 {
"111011", 6.7}, {
"111020", 6.2}, {
"111021", 5.8}, {
"111100", 7.4},
391 {
"111101", 5.9}, {
"111110", 5.7}, {
"111111", 5.7}, {
"111120", 4.7},
392 {
"111121", 2.3}, {
"111200", 6.1}, {
"111201", 5.2}, {
"111210", 5.7},
393 {
"111211", 2.9}, {
"111220", 2.4}, {
"111221", 1.6}, {
"112001", 7.1},
394 {
"112011", 5.9}, {
"112021", 3}, {
"112101", 5.8}, {
"112111", 2.6},
395 {
"112121", 1.5}, {
"112201", 2.3}, {
"112211", 1.3}, {
"112221", 0.6},
396 {
"200000", 9.3}, {
"200001", 8.7}, {
"200010", 8.6}, {
"200011", 7.2},
397 {
"200020", 7.5}, {
"200021", 5.8}, {
"200100", 8.6}, {
"200101", 7.4},
398 {
"200110", 7.4}, {
"200111", 6.1}, {
"200120", 5.6}, {
"200121", 3.4},
399 {
"200200", 7}, {
"200201", 5.4}, {
"200210", 5.2}, {
"200211", 4},
400 {
"200220", 4}, {
"200221", 2.2}, {
"201000", 8.5}, {
"201001", 7.5},
401 {
"201010", 7.4}, {
"201011", 5.5}, {
"201020", 6.2}, {
"201021", 5.1},
402 {
"201100", 7.2}, {
"201101", 5.7}, {
"201110", 5.5}, {
"201111", 4.1},
403 {
"201120", 4.6}, {
"201121", 1.9}, {
"201200", 5.3}, {
"201201", 3.6},
404 {
"201210", 3.4}, {
"201211", 1.9}, {
"201220", 1.9}, {
"201221", 0.8},
405 {
"202001", 6.4}, {
"202011", 5.1}, {
"202021", 2}, {
"202101", 4.7},
406 {
"202111", 2.1}, {
"202121", 1.1}, {
"202201", 2.4}, {
"202211", 0.9},
407 {
"202221", 0.4}, {
"210000", 8.8}, {
"210001", 7.5}, {
"210010", 7.3},
408 {
"210011", 5.3}, {
"210020", 6}, {
"210021", 5}, {
"210100", 7.3},
409 {
"210101", 5.5}, {
"210110", 5.9}, {
"210111", 4}, {
"210120", 4.1},
410 {
"210121", 2}, {
"210200", 5.4}, {
"210201", 4.3}, {
"210210", 4.5},
411 {
"210211", 2.2}, {
"210220", 2}, {
"210221", 1.1}, {
"211000", 7.5},
412 {
"211001", 5.5}, {
"211010", 5.8}, {
"211011", 4.5}, {
"211020", 4},
413 {
"211021", 2.1}, {
"211100", 6.1}, {
"211101", 5.1}, {
"211110", 4.8},
414 {
"211111", 1.8}, {
"211120", 2}, {
"211121", 0.9}, {
"211200", 4.6},
415 {
"211201", 1.8}, {
"211210", 1.7}, {
"211211", 0.7}, {
"211220", 0.8},
416 {
"211221", 0.2}, {
"212001", 5.3}, {
"212011", 2.4}, {
"212021", 1.4},
417 {
"212101", 2.4}, {
"212111", 1.2}, {
"212121", 0.5}, {
"212201", 1},
418 {
"212211", 0.3}, {
"212221", 0.1}, {NULL, 0.0}};
442 if (g_strcmp0 (str,
"A") == 0)
444 else if (g_strcmp0 (str,
"I") == 0)
446 else if (g_strcmp0 (str,
"C") == 0)
448 else if (g_strcmp0 (str,
"Au") == 0)
450 else if (g_strcmp0 (str,
"AU") == 0)
452 else if (g_strcmp0 (str,
"AV") == 0)
454 else if (g_strcmp0 (str,
"AC") == 0)
509 for (i = 0; i < 3; i++)
515 if (g_strcmp0 (impact->
name, value) == 0)
563 double impact = 1.176;
565 double exploitability_sub;
570 if (impact_sub < 0.1)
573 return (((0.6 * impact_sub) + (0.4 * exploitability_sub) - 1.5) * impact)
590 if (cvss_str == NULL)
593 if (g_str_has_prefix (cvss_str,
"CVSS:3.1/")
594 || g_str_has_prefix (cvss_str,
"CVSS:3.0/"))
596 + strlen (
"CVSS:3.X/"));
597 if (g_str_has_prefix (cvss_str,
"CVSS:4.0/"))
600 memset (&
cvss, 0x00,
sizeof (
struct cvss));
602 base_str =
base_metrics = g_strdup_printf (
"%s/", cvss_str);
607 char *metric_name = token2;
614 if (metric_name == NULL)
617 metric_value = strtok (NULL,
":");
619 if (metric_value == NULL)
622 rc =
toenum (metric_name, &mval);
663 trim = round (
cvss * 100000);
664 if ((trim % 10000) == 0)
665 return ((
double) trim) / 100000;
666 return (floor (trim / 10000) + 1) / 10.0;
679 if (strcasecmp (value,
"N") == 0)
681 if (strcasecmp (value,
"L") == 0)
683 if (strcasecmp (value,
"H") == 0)
698 gchar **split, **point;
700 double impact_conf, impact_integ, impact_avail;
701 double vector, complexity, privilege, user;
702 double isc_base, impact, exploitability, base;
719 split = g_strsplit (cvss_str,
"/", 0);
724 if (strncasecmp (
"S:", *point, 2) == 0)
726 if (strcasecmp (*point + 2,
"U") == 0)
728 else if (strcasecmp (*point + 2,
"C") == 0)
733 if (strncasecmp (
"C:", *point, 2) == 0)
737 if (strncasecmp (
"I:", *point, 2) == 0)
741 if (strncasecmp (
"A:", *point, 2) == 0)
745 if (strncasecmp (
"AV:", *point, 3) == 0)
747 if (strcasecmp (*point + 3,
"N") == 0)
749 else if (strcasecmp (*point + 3,
"A") == 0)
751 else if (strcasecmp (*point + 3,
"L") == 0)
753 else if (strcasecmp (*point + 3,
"P") == 0)
758 if (strncasecmp (
"AC:", *point, 3) == 0)
760 if (strcasecmp (*point + 3,
"L") == 0)
762 else if (strcasecmp (*point + 3,
"H") == 0)
767 if (strncasecmp (
"PR:", *point, 3) == 0)
769 if (strcasecmp (*point + 3,
"N") == 0)
771 else if (strcasecmp (*point + 3,
"L") == 0)
773 else if (strcasecmp (*point + 3,
"H") == 0)
780 if (strncasecmp (
"UI:", *point, 3) == 0)
782 if (strcasecmp (*point + 3,
"N") == 0)
784 else if (strcasecmp (*point + 3,
"R") == 0)
795 if (scope_changed == -1 || impact_conf == -1.0 || impact_integ == -1.0
796 || impact_avail == -1.0 || vector == -1.0 || complexity == -1.0
797 || privilege == -1.0 || user == -1.0)
802 if (scope_changed && privilege == 0.62)
804 else if (scope_changed && privilege == 0.27)
809 isc_base = 1 - ((1 - impact_conf) * (1 - impact_integ) * (1 - impact_avail));
812 impact = 7.52 * (isc_base - 0.029) - 3.25 * pow ((isc_base - 0.02), 15);
814 impact = 6.42 * isc_base;
821 exploitability = 8.22 * vector * complexity * privilege * user;
826 base = 1.08 * (impact + exploitability);
828 base = impact + exploitability;
890 char selected = simplified_vec[metric];
893 if (metric ==
CVSS4_E && selected ==
'X')
907 if (modified_selected !=
'X')
908 return modified_selected;
931 gchar **split_cvss_str, **split_cvss_point;
932 gboolean valid = TRUE;
936 if (cvss_str == NULL || strcmp (cvss_str,
"") == 0)
941 split_cvss_str = g_strsplit (cvss_str,
"/", -1);
942 split_cvss_point = split_cvss_str;
943 while (valid && *split_cvss_point)
945 if (strcmp (*split_cvss_point,
"") == 0)
951 gchar **split_component = g_strsplit (*split_cvss_point,
":", 2);
952 const gchar *metric_str = split_component[0], *value = split_component[1];
958 g_debug (
"%s: value for metric %s missing", __func__, metric_str);
961 else if (strcasecmp (metric_str,
"U") == 0)
964 if (strcasecmp (value,
"Red") && strcasecmp (value,
"Amber")
965 && strcasecmp (value,
"Green") && strcasecmp (value,
"Clear")
966 && strcasecmp (value,
"X"))
968 g_debug (
"%s: value for metric %s must be one of"
969 " 'Red', 'Amber', 'Green', 'Clear', 'X'",
970 __func__, metric_str);
976 else if (strlen (value) != 1)
978 g_debug (
"%s: value for metric %s must be 1 character", __func__,
986 if (strcasecmp (metric_str, metric_def->
metric_str) == 0)
988 char value_char = g_ascii_toupper (value[0]);
991 if (vec[metric_def->
metric] !=
'X')
993 g_debug (
"%s: duplicate metric %s", __func__, metric_str);
998 if (strchr (metric_def->
values, value_char))
1001 vec[metric_def->
metric] = value_char;
1005 g_debug (
"%s: invalid metric: %s:%c", __func__, metric_str,
1014 g_strfreev (split_component);
1016 g_strfreev (split_cvss_str);
1020 if (vec[metric] ==
'X')
1022 g_debug (
"%s: mandatory metric %s is undefined", __func__,
1030 g_debug (
"%s: vector %s is invalid", __func__, cvss_str);
1049 GString *str = g_string_new (
"CVSS:4.0");
1052 const char *expanded_value;
1053 if (vec[metric] ==
'X')
1058 switch (vec[metric])
1061 expanded_value =
"Red";
1064 expanded_value =
"Amber";
1067 expanded_value =
"Green";
1070 expanded_value =
"Clear";
1073 expanded_value = NULL;
1077 expanded_value = NULL;
1080 g_string_append_printf (str,
"/%s:%s", def.
metric_str, expanded_value);
1082 g_string_append_printf (str,
"/%s:%c", def.
metric_str, vec[metric]);
1084 return g_string_free (str, FALSE);
1094static inline gchar *
1110 if (av ==
'N' && pr ==
'N' && ui ==
'N')
1111 macrovector[0] =
'0';
1112 else if ((av ==
'N' || pr ==
'N' || ui ==
'N') && !(av ==
'P'))
1113 macrovector[0] =
'1';
1115 macrovector[0] =
'2';
1122 if (ac ==
'L' && at ==
'N')
1123 macrovector[1] =
'0';
1125 macrovector[1] =
'1';
1134 if (vc ==
'H' && vi ==
'H')
1135 macrovector[2] =
'0';
1136 else if (vc ==
'H' || vi ==
'H' || va ==
'H')
1137 macrovector[2] =
'1';
1139 macrovector[2] =
'2';
1150 if (si ==
'S' || sa ==
'S')
1151 macrovector[3] =
'0';
1152 else if (sc ==
'H' || si ==
'H' || sa ==
'H')
1153 macrovector[3] =
'1';
1155 macrovector[3] =
'2';
1162 macrovector[4] =
'0';
1164 macrovector[4] =
'1';
1166 macrovector[4] =
'2';
1173 if ((cr ==
'H' && vc ==
'H') || (ir ==
'H' && vi ==
'H')
1174 || (ar ==
'H' && va ==
'H'))
1175 macrovector[5] =
'0';
1177 macrovector[5] =
'1';
1194 double *available_distance_eq1,
1195 double *available_distance_eq2,
1196 double *available_distance_eq3eq6,
1197 double *available_distance_eq4,
1198 double *available_distance_eq5)
1201 double score_eq1_next_lower_macro, score_eq2_next_lower_macro;
1202 double score_eq3eq6_next_lower_macro;
1203 double score_eq4_next_lower_macro, score_eq5_next_lower_macro;
1206 if (macrovector[0] <=
'1')
1208 gchar *eq1_next_lower_macro = g_strdup (macrovector);
1209 eq1_next_lower_macro[0]++;
1210 score_eq1_next_lower_macro =
1212 g_free (eq1_next_lower_macro);
1215 score_eq1_next_lower_macro = -1.0;
1218 if (macrovector[1] ==
'0')
1220 gchar *eq2_next_lower_macro = g_strdup (macrovector);
1221 eq2_next_lower_macro[1]++;
1222 score_eq2_next_lower_macro =
1226 score_eq2_next_lower_macro = -1.0;
1229 if ((macrovector[2] ==
'0' || macrovector[2] ==
'1') && macrovector[5] ==
'1')
1231 gchar *eq3eq6_next_lower_macro = g_strdup (macrovector);
1232 eq3eq6_next_lower_macro[2]++;
1233 score_eq3eq6_next_lower_macro =
1235 g_free (eq3eq6_next_lower_macro);
1237 else if (macrovector[2] ==
'1' && macrovector[5] ==
'0')
1239 gchar *eq3eq6_next_lower_macro = g_strdup (macrovector);
1240 eq3eq6_next_lower_macro[5]++;
1241 score_eq3eq6_next_lower_macro =
1243 g_free (eq3eq6_next_lower_macro);
1245 else if (macrovector[2] ==
'0' && macrovector[5] ==
'0')
1247 gchar *eq3eq6_next_lower_macro_left = g_strdup (macrovector);
1248 eq3eq6_next_lower_macro_left[5]++;
1249 gchar *eq3eq6_next_lower_macro_right = g_strdup (macrovector);
1250 eq3eq6_next_lower_macro_right[2]++;
1251 double score_eq3eq6_next_lower_macro_left =
1253 double score_eq3eq6_next_lower_macro_right =
1256 if (score_eq3eq6_next_lower_macro_left
1257 > score_eq3eq6_next_lower_macro_right)
1258 score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_left;
1260 score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_right;
1262 g_free (eq3eq6_next_lower_macro_left);
1263 g_free (eq3eq6_next_lower_macro_right);
1266 score_eq3eq6_next_lower_macro = -1.0;
1269 if (macrovector[3] <=
'1')
1271 gchar *eq4_next_lower_macro = g_strdup (macrovector);
1272 eq4_next_lower_macro[3]++;
1273 score_eq4_next_lower_macro =
1275 g_free (eq4_next_lower_macro);
1278 score_eq4_next_lower_macro = -1.0;
1281 if (macrovector[4] <=
'1')
1283 gchar *eq5_next_lower_macro = g_strdup (macrovector);
1284 eq5_next_lower_macro[4]++;
1285 score_eq5_next_lower_macro =
1287 g_free (eq5_next_lower_macro);
1290 score_eq5_next_lower_macro = -1.0;
1294 *available_distance_eq1 = score_eq1_next_lower_macro != -1.0
1295 ? value - score_eq1_next_lower_macro
1297 *available_distance_eq2 = score_eq2_next_lower_macro != -1.0
1298 ? value - score_eq2_next_lower_macro
1300 *available_distance_eq3eq6 = score_eq3eq6_next_lower_macro != -1.0
1301 ? value - score_eq3eq6_next_lower_macro
1303 *available_distance_eq4 = score_eq4_next_lower_macro != -1.0
1304 ? value - score_eq4_next_lower_macro
1306 *available_distance_eq5 = score_eq5_next_lower_macro != -1.0
1307 ? value - score_eq5_next_lower_macro
1312 *available_distance_eq1 = -1.0;
1313 *available_distance_eq2 = -1.0;
1314 *available_distance_eq3eq6 = -1.0;
1315 *available_distance_eq4 = -1.0;
1316 *available_distance_eq5 = -1.0;
1330 const char **eq1_maxes, **eq2_maxes, **eq3eq6_maxes;
1331 const char *eq4_max, *eq5_max;
1335 static const char *eq1_maxes_0[] = {
"AV:N/PR:N/UI:N/", NULL};
1336 static const char *eq1_maxes_1[] = {
"AV:A/PR:N/UI:N/",
"AV:N/PR:L/UI:N/",
1337 "AV:N/PR:N/UI:P/", NULL};
1338 static const char *eq1_maxes_2[] = {
"AV:P/PR:N/UI:N/",
"AV:A/PR:L/UI:P/",
1340 if (macrovector[0] ==
'0')
1341 eq1_maxes = eq1_maxes_0;
1342 else if (macrovector[0] ==
'1')
1343 eq1_maxes = eq1_maxes_1;
1345 eq1_maxes = eq1_maxes_2;
1348 static const char *eq2_maxes_0[] = {
"AC:L/AT:N/", NULL};
1349 static const char *eq2_maxes_1[] = {
"AC:H/AT:N/",
"AC:L/AT:P/", NULL};
1350 if (macrovector[1] ==
'0')
1351 eq2_maxes = eq2_maxes_0;
1353 eq2_maxes = eq2_maxes_1;
1356 static const char *eq3eq6_maxes_00[] = {
"VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/",
1358 static const char *eq3eq6_maxes_01[] = {
1359 "VC:H/VI:H/VA:L/CR:M/IR:M/AR:H/",
"VC:H/VI:H/VA:H/CR:M/IR:M/AR:M/", NULL};
1360 static const char *eq3eq6_maxes_10[] = {
1361 "VC:L/VI:H/VA:H/CR:H/IR:H/AR:H/",
"VC:H/VI:L/VA:H/CR:H/IR:H/AR:H/", NULL};
1362 static const char *eq3eq6_maxes_11[] = {
1363 "VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/",
"VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/",
1364 "VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/",
"VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/",
1365 "VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/", NULL};
1366 static const char *eq3eq6_maxes_21[] = {
"VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/",
1368 if ((macrovector[2] ==
'0'))
1370 if (macrovector[5] ==
'0')
1371 eq3eq6_maxes = eq3eq6_maxes_00;
1373 eq3eq6_maxes = eq3eq6_maxes_01;
1375 else if ((macrovector[2] ==
'1'))
1377 if (macrovector[5] ==
'0')
1378 eq3eq6_maxes = eq3eq6_maxes_10;
1380 eq3eq6_maxes = eq3eq6_maxes_11;
1383 eq3eq6_maxes = eq3eq6_maxes_21;
1386 if (macrovector[3] ==
'0')
1387 eq4_max =
"SC:H/SI:S/SA:S/";
1388 else if (macrovector[3] ==
'1')
1389 eq4_max =
"SC:H/SI:H/SA:H/";
1391 eq4_max =
"SC:L/SI:L/SA:L/";
1394 if (macrovector[4] ==
'0')
1396 else if (macrovector[4] ==
'1')
1401 GPtrArray *max_vectors = g_ptr_array_new ();
1402 const char **eq1_max, **eq2_max, **eq3eq6_max;
1403 for (eq1_max = eq1_maxes; *eq1_max != NULL; eq1_max++)
1405 for (eq2_max = eq2_maxes; *eq2_max != NULL; eq2_max++)
1407 for (eq3eq6_max = eq3eq6_maxes; *eq3eq6_max != NULL; eq3eq6_max++)
1409 gchar *full_vector =
1410 g_strdup_printf (
"%s%s%s%s%s", *eq1_max, *eq2_max, *eq3eq6_max,
1414 g_warning (
"%s: generated vector %s is invalid", __func__,
1417 g_ptr_array_add (max_vectors, vector);
1418 g_free (full_vector);
1423 g_ptr_array_add (max_vectors, NULL);
1425 ret = (gchar **) max_vectors->pdata;
1426 g_ptr_array_free (max_vectors, FALSE);
1582 const char *max_vec)
1601 double *current_severity_distance_eq1,
1602 double *current_severity_distance_eq2,
1603 double *current_severity_distance_eq3eq6,
1604 double *current_severity_distance_eq4,
1605 double *current_severity_distance_eq5)
1607 double severity_distance_AV, severity_distance_PR, severity_distance_UI;
1608 double severity_distance_AC, severity_distance_AT;
1609 double severity_distance_VC, severity_distance_VI, severity_distance_VA;
1610 double severity_distance_SC, severity_distance_SI, severity_distance_SA;
1611 double severity_distance_CR, severity_distance_IR, severity_distance_AR;
1613 severity_distance_AV = severity_distance_PR = severity_distance_UI = -99.0;
1614 severity_distance_AC = severity_distance_AT = -99.0;
1615 severity_distance_VC = severity_distance_VI = severity_distance_VA = -99.0;
1616 severity_distance_SC = severity_distance_SI = severity_distance_SA = -99.0;
1617 severity_distance_CR = severity_distance_IR = severity_distance_AR = -99.0;
1619 char **max_vectors, **max_vec;
1621 for (max_vec = max_vectors; *max_vec != NULL; max_vec++)
1642 if (severity_distance_AV < 0.0 || severity_distance_PR < 0.0
1643 || severity_distance_UI < 0.0 || severity_distance_AC < 0.0
1644 || severity_distance_AT < 0.0 || severity_distance_VC < 0.0
1645 || severity_distance_VI < 0.0 || severity_distance_VA < 0.0
1646 || severity_distance_SC < 0.0 || severity_distance_SI < 0.0
1647 || severity_distance_SA < 0.0 || severity_distance_CR < 0.0
1648 || severity_distance_IR < 0.0 || severity_distance_AR < 0.0)
1651 g_debug (
"%s AV:%0.1f PR:%0.1f UI:%0.1f |"
1652 " AC:%0.1f AT:%0.1f |"
1653 " VC:%0.1f VI:%0.1f VA:%0.1f |"
1654 " SC:%0.1f SI:%0.1f SA:%0.1f |"
1655 " CR:%0.1f IR:%0.1f AR:%0.1f",
1656 __func__, severity_distance_AV, severity_distance_PR,
1657 severity_distance_UI, severity_distance_AC, severity_distance_AT,
1658 severity_distance_VC, severity_distance_VI, severity_distance_VA,
1659 severity_distance_SC, severity_distance_SI, severity_distance_SA,
1660 severity_distance_CR, severity_distance_IR,
1661 severity_distance_AR);
1666 g_debug (
"%s: max_vec: %s", __func__, max_vec_expanded);
1667 g_free (max_vec_expanded);
1668 g_strfreev (max_vectors);
1670 *current_severity_distance_eq1 =
1671 severity_distance_AV + severity_distance_PR + severity_distance_UI;
1672 *current_severity_distance_eq2 = severity_distance_AC + severity_distance_AT;
1673 *current_severity_distance_eq3eq6 =
1674 severity_distance_VC + severity_distance_VI + severity_distance_VA
1675 + severity_distance_CR + severity_distance_IR + severity_distance_AR;
1676 *current_severity_distance_eq4 =
1677 severity_distance_SC + severity_distance_SI + severity_distance_SA;
1678 *current_severity_distance_eq5 = 0.0;
1694 double *max_severity_eq2,
double *max_severity_eq3eq6,
1695 double *max_severity_eq4)
1697 switch (macrovector[0])
1700 *max_severity_eq1 = 0.1;
1703 *max_severity_eq1 = 0.4;
1706 *max_severity_eq1 = 0.5;
1709 *max_severity_eq1 = -99.0;
1712 switch (macrovector[1])
1715 *max_severity_eq2 = 0.1;
1718 *max_severity_eq2 = 0.2;
1721 *max_severity_eq2 = -99.0;
1724 switch (macrovector[2])
1727 if (macrovector[5] ==
'0')
1728 *max_severity_eq3eq6 = 0.7;
1730 *max_severity_eq3eq6 = 0.6;
1733 *max_severity_eq3eq6 = 0.8;
1736 *max_severity_eq3eq6 = 1.0;
1739 *max_severity_eq3eq6 = -99.0;
1742 switch (macrovector[3])
1745 *max_severity_eq4 = 0.6;
1748 *max_severity_eq4 = 0.5;
1751 *max_severity_eq4 = 0.4;
1754 *max_severity_eq4 = -99.0;
1769 char *macrovector = NULL;
1771 double available_distance_eq1, available_distance_eq2;
1772 double available_distance_eq3eq6;
1773 double available_distance_eq4, available_distance_eq5;
1775 double current_severity_distance_eq1, current_severity_distance_eq2;
1776 double current_severity_distance_eq3eq6;
1777 double current_severity_distance_eq4, current_severity_distance_eq5;
1779 double max_severity_eq1, max_severity_eq2, max_severity_eq3eq6;
1780 double max_severity_eq4;
1782 double mean_distance, value;
1784 int n_existing_lower = 0;
1787 g_debug (
"%s: CVSS string: %s", __func__, cvss_str);
1789 g_debug (
"%s: simplified vector: %s", __func__, vec);
1796 g_debug (
"%s: macrovector: %s, value: %0.1f", __func__, macrovector, value);
1797 if (macrovector == NULL || value == -1.0)
1805 macrovector, &available_distance_eq1, &available_distance_eq2,
1806 &available_distance_eq3eq6, &available_distance_eq4,
1807 &available_distance_eq5);
1808 g_debug (
"%s: maximal scoring diffs:"
1809 " EQ1:%0.1f EQ2:%0.1f EQ3+EQ6:%0.1f EQ5:%0.1f EQ6:%0.1f",
1810 __func__, available_distance_eq1, available_distance_eq2,
1811 available_distance_eq3eq6, available_distance_eq4,
1812 available_distance_eq5);
1816 vec, macrovector, ¤t_severity_distance_eq1,
1817 ¤t_severity_distance_eq2, ¤t_severity_distance_eq3eq6,
1818 ¤t_severity_distance_eq4, ¤t_severity_distance_eq5);
1820 g_debug (
"%s: current severity distances:"
1821 "EQ1:%0.1f EQ2:%0.1f EQ3+EQ6:%0.1f EQ4:%0.1f EQ5:%0.1f",
1822 __func__, current_severity_distance_eq1,
1823 current_severity_distance_eq2, current_severity_distance_eq3eq6,
1824 current_severity_distance_eq4, current_severity_distance_eq5);
1828 &max_severity_eq3eq6, &max_severity_eq4);
1831 g_free (macrovector);
1834 mean_distance = 0.0;
1835 if (available_distance_eq1 >= 0.0)
1838 double percent_to_next_severity =
1839 (current_severity_distance_eq1) / max_severity_eq1;
1840 mean_distance += (available_distance_eq1 * percent_to_next_severity);
1843 if (available_distance_eq2 >= 0.0)
1846 double percent_to_next_severity =
1847 (current_severity_distance_eq2) / max_severity_eq2;
1848 mean_distance += (available_distance_eq2 * percent_to_next_severity);
1851 if (available_distance_eq3eq6 >= 0.0)
1854 double percent_to_next_severity =
1855 (current_severity_distance_eq3eq6) / max_severity_eq3eq6;
1856 mean_distance += (available_distance_eq3eq6 * percent_to_next_severity);
1859 if (available_distance_eq4 >= 0.0)
1862 double percent_to_next_severity =
1863 (current_severity_distance_eq4) / max_severity_eq4;
1864 mean_distance += (available_distance_eq4 * percent_to_next_severity);
1867 if (available_distance_eq5 >= 0.0)
1873 mean_distance = mean_distance / n_existing_lower;
1876 value = value - mean_distance;
1879 else if (value > 10.0)
1882 return round (value * 10.0) / 10.0;
static void cvss4_current_severity_distances(const char *vec, const char *macrovector, double *current_severity_distance_eq1, double *current_severity_distance_eq2, double *current_severity_distance_eq3eq6, double *current_severity_distance_eq4, double *current_severity_distance_eq5)
Calculate current severity distances for given CVSS 4.0 vector.
Definition cvss.c:1600
#define C_COMPLETE
Definition cvss.c:122
cvss4_metric_t
CVSS 4.0 metrics.
Definition cvss.c:219
@ CVSS4_PR
Definition cvss.c:224
@ CVSS4_VA
Definition cvss.c:228
@ CVSS4_V
Definition cvss.c:253
@ CVSS4_AV
Definition cvss.c:221
@ CVSS4_MSA
Definition cvss.c:248
@ CVSS4_MAC
Definition cvss.c:239
@ CVSS4_MSC
Definition cvss.c:246
@ CVSS4_E
Definition cvss.c:233
@ CVSS4_RE
Definition cvss.c:254
@ CVSS4_U
Definition cvss.c:255
@ CVSS4_MAV
Definition cvss.c:238
@ CVSS4_AR
Definition cvss.c:237
@ CVSS4_R
Definition cvss.c:252
@ CVSS4_SA
Definition cvss.c:231
@ CVSS4_S
Definition cvss.c:250
@ CVSS4_VI
Definition cvss.c:227
@ CVSS4_MPR
Definition cvss.c:241
@ CVSS4_UI
Definition cvss.c:225
@ CVSS4_VC
Definition cvss.c:226
@ CVSS4_SC
Definition cvss.c:229
@ CVSS4_AU
Definition cvss.c:251
@ CVSS4_MSI
Definition cvss.c:247
@ CVSS4_MVC
Definition cvss.c:243
@ CVSS4_MUI
Definition cvss.c:242
@ CVSS4_MAT
Definition cvss.c:240
@ CVSS4_AT
Definition cvss.c:223
@ CVSS4_AC
Definition cvss.c:222
@ CVSS4_CR
Definition cvss.c:235
@ CVSS4_MVI
Definition cvss.c:244
@ CVSS4_METRICS_MAX
Definition cvss.c:257
@ CVSS4_MVA
Definition cvss.c:245
@ CVSS4_SI
Definition cvss.c:230
@ CVSS4_IR
Definition cvss.c:236
static void cvss4_init_macrovector_table()
Initialize the CVSS 4.0 macrovector lookup table.
Definition cvss.c:840
static int set_impact_from_str(const char *value, enum base_metrics metric, struct cvss *cvss)
Set impact score from string representation.
Definition cvss.c:504
#define AV_LOCAL
Definition cvss.c:101
static double get_exploitability_subscore(const struct cvss *cvss)
Calculate Exploitability Sub Score.
Definition cvss.c:488
#define Au_SINGLE_INSTANCE
Definition cvss.c:114
static double cvss4_macrovector_score(const char *vector)
Get the CVSS 4.0 score for a given macrovector string.
Definition cvss.c:865
#define A_PARTIAL
Definition cvss.c:135
#define CVSS_MACROVECTOR_BLANK
Blank simplified CVSS 4.0 macrovector string.
Definition cvss.c:268
static int toenum(const char *str, enum base_metrics *res)
Determine base metric enumeration from a string.
Definition cvss.c:438
#define C_NONE
ConfidentialityImpact (C) Constants.
Definition cvss.c:120
#define I_PARTIAL
Definition cvss.c:128
static cvss4_metric_def_t cvss4_metric_defs[]
String to enum mappings and allowed values for CVSS 4.0 metrics.
Definition cvss.c:294
static double v3_impact(const char *value)
Get impact.
Definition cvss.c:677
#define AV_NETWORK
AccessVector (AV) Constants.
Definition cvss.c:99
static const cvss4_macrovector_mapping_t cvss4_macrovector_mappings[]
CVSS 4.0 macrovector mappings.
Definition cvss.c:350
static GHashTable * cvss4_macrovector_table
Hashtable for quick lookup of CVSS macrovector scores.
Definition cvss.c:427
#define C_PARTIAL
Definition cvss.c:121
static char cvss4_m(const char *simplified_vec, cvss4_metric_t metric)
Get the effective value of a metric in a simplified CVSS4 vector.
Definition cvss.c:888
#define CVSS_METRICS_STR_BLANK
Blank simplified CVSS 4.0 metrics string.
Definition cvss.c:263
#define A_COMPLETE
Definition cvss.c:136
static gchar * cvss4_macrovector(const char *vec)
Calculate CVSS 4.0 macrovector from a simplified vector.
Definition cvss.c:1095
static gchar * simplify_cvss4_vector(const char *cvss_str)
Simplify CVSS 4.0 base vector so metrics can be indexed by enum.
Definition cvss.c:929
static gchar * cvss4_vector_expand(const char *vec)
Expands a simplified CVSS 4.0 vector into its full string form.
Definition cvss.c:1046
#define Au_MULTIPLE_INSTANCES
Authentication (Au) Constants.
Definition cvss.c:113
static double get_impact_subscore(const struct cvss *cvss)
Calculate Impact Sub Score.
Definition cvss.c:471
#define AC_LOW
AccessComplexity (AC) Constants.
Definition cvss.c:106
#define I_NONE
IntegrityImpact (I) Constants.
Definition cvss.c:127
static double get_cvss_score_from_metrics_v4(const char *)
Calculate CVSS 4.0 Score.
Definition cvss.c:1766
static const struct impact_item impact_map[][3]
Definition cvss.c:174
static double cvss4_metric_level(cvss4_metric_t metric, char value)
Get the index of a CVSS 4.0 metric value for severity distances.
Definition cvss.c:1439
base_metrics
CVSS v2 Base metrics.
Definition cvss.c:143
@ AC
Definition cvss.c:148
@ Au
Definition cvss.c:147
@ AV
Definition cvss.c:149
static double get_cvss_score_from_base_metrics_v3(const char *)
Calculate CVSS Score.
Definition cvss.c:696
#define A_NONE
AvailabilityImpact (A) Constants.
Definition cvss.c:134
double get_cvss_score_from_base_metrics(const char *cvss_str)
Calculate CVSS Score.
Definition cvss.c:585
static void cvss4_max_severities(const char *macrovector, double *max_severity_eq1, double *max_severity_eq2, double *max_severity_eq3eq6, double *max_severity_eq4)
Get the max severity values for a CVSS 4.0 macrovector.
Definition cvss.c:1693
static double __get_cvss_score(struct cvss *cvss)
Final CVSS score computation helper.
Definition cvss.c:561
#define I_COMPLETE
Definition cvss.c:129
static double cvss4_severity_distance(cvss4_metric_t metric, const char *vec, const char *max_vec)
Calculate severity distance for a metric in two CVSS 4.0 vectors.
Definition cvss.c:1581
#define AC_MEDIUM
Definition cvss.c:107
#define AV_ADJACENT_NETWORK
Definition cvss.c:100
static double roundup(double cvss)
Round final score as in spec.
Definition cvss.c:650
static gchar ** cvss4_max_vectors(const char *macrovector)
Composes a list of max vectors for the given CVSS 4.0 macrovector.
Definition cvss.c:1328
#define AC_HIGH
Definition cvss.c:108
static void cvss4_maximal_scoring_differences(const char *macrovector, double *available_distance_eq1, double *available_distance_eq2, double *available_distance_eq3eq6, double *available_distance_eq4, double *available_distance_eq5)
Calulate the maximal scoring differences from a CVSS 4.0 macrovector.
Definition cvss.c:1193
#define Au_NONE
Definition cvss.c:115
Protos for CVSS utility functions.
Key-Value mappings of CVSS 4.0 macrovectors to scores.
Definition cvss.c:338
const char * vector
Definition cvss.c:339
double score
Definition cvss.c:340
String to enum mapping and allowed values for a CVSS 4.0 metric.
Definition cvss.c:278
const char * metric_str
Definition cvss.c:279
const char * values
Definition cvss.c:281
const cvss4_metric_t metric
Definition cvss.c:280
Describe a CVSS metrics.
Definition cvss.c:165
double integ_impact
Definition cvss.c:167
double access_vector
Definition cvss.c:169
double avail_impact
Definition cvss.c:168
double authentication
Definition cvss.c:171
double access_complexity
Definition cvss.c:170
double conf_impact
Definition cvss.c:166
Describe a CVSS impact element.
Definition cvss.c:156
const char * name
Definition cvss.c:157
double nvalue
Definition cvss.c:158