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);
959 g_strfreev (split_component);
962 else if (strcasecmp (metric_str,
"U") == 0)
965 if (strcasecmp (value,
"Red") && strcasecmp (value,
"Amber")
966 && strcasecmp (value,
"Green") && strcasecmp (value,
"Clear")
967 && strcasecmp (value,
"X"))
969 g_debug (
"%s: value for metric %s must be one of"
970 " 'Red', 'Amber', 'Green', 'Clear', 'X'",
971 __func__, metric_str);
972 g_strfreev (split_component);
978 else if (strlen (value) != 1)
980 g_debug (
"%s: value for metric %s must be 1 character", __func__,
982 g_strfreev (split_component);
989 if (strcasecmp (metric_str, metric_def->
metric_str) == 0)
991 char value_char = g_ascii_toupper (value[0]);
994 if (vec[metric_def->
metric] !=
'X')
996 g_debug (
"%s: duplicate metric %s", __func__, metric_str);
1001 if (strchr (metric_def->
values, value_char))
1004 vec[metric_def->
metric] = value_char;
1008 g_debug (
"%s: invalid metric: %s:%c", __func__, metric_str,
1017 g_strfreev (split_component);
1019 g_strfreev (split_cvss_str);
1023 if (vec[metric] ==
'X')
1025 g_debug (
"%s: mandatory metric %s is undefined", __func__,
1033 g_debug (
"%s: vector %s is invalid", __func__, cvss_str);
1052 GString *str = g_string_new (
"CVSS:4.0");
1055 const char *expanded_value;
1056 if (vec[metric] ==
'X')
1061 switch (vec[metric])
1064 expanded_value =
"Red";
1067 expanded_value =
"Amber";
1070 expanded_value =
"Green";
1073 expanded_value =
"Clear";
1076 expanded_value = NULL;
1080 expanded_value = NULL;
1083 g_string_append_printf (str,
"/%s:%s", def.
metric_str, expanded_value);
1085 g_string_append_printf (str,
"/%s:%c", def.
metric_str, vec[metric]);
1087 return g_string_free (str, FALSE);
1097static inline gchar *
1113 if (av ==
'N' && pr ==
'N' && ui ==
'N')
1114 macrovector[0] =
'0';
1115 else if ((av ==
'N' || pr ==
'N' || ui ==
'N') && !(av ==
'P'))
1116 macrovector[0] =
'1';
1118 macrovector[0] =
'2';
1125 if (ac ==
'L' && at ==
'N')
1126 macrovector[1] =
'0';
1128 macrovector[1] =
'1';
1137 if (vc ==
'H' && vi ==
'H')
1138 macrovector[2] =
'0';
1139 else if (vc ==
'H' || vi ==
'H' || va ==
'H')
1140 macrovector[2] =
'1';
1142 macrovector[2] =
'2';
1153 if (si ==
'S' || sa ==
'S')
1154 macrovector[3] =
'0';
1155 else if (sc ==
'H' || si ==
'H' || sa ==
'H')
1156 macrovector[3] =
'1';
1158 macrovector[3] =
'2';
1165 macrovector[4] =
'0';
1167 macrovector[4] =
'1';
1169 macrovector[4] =
'2';
1176 if ((cr ==
'H' && vc ==
'H') || (ir ==
'H' && vi ==
'H')
1177 || (ar ==
'H' && va ==
'H'))
1178 macrovector[5] =
'0';
1180 macrovector[5] =
'1';
1197 double *available_distance_eq1,
1198 double *available_distance_eq2,
1199 double *available_distance_eq3eq6,
1200 double *available_distance_eq4,
1201 double *available_distance_eq5)
1204 double score_eq1_next_lower_macro, score_eq2_next_lower_macro;
1205 double score_eq3eq6_next_lower_macro;
1206 double score_eq4_next_lower_macro, score_eq5_next_lower_macro;
1209 if (macrovector[0] <=
'1')
1211 gchar *eq1_next_lower_macro = g_strdup (macrovector);
1212 eq1_next_lower_macro[0]++;
1213 score_eq1_next_lower_macro =
1215 g_free (eq1_next_lower_macro);
1218 score_eq1_next_lower_macro = -1.0;
1221 if (macrovector[1] ==
'0')
1223 gchar *eq2_next_lower_macro = g_strdup (macrovector);
1224 eq2_next_lower_macro[1]++;
1225 score_eq2_next_lower_macro =
1227 g_free (eq2_next_lower_macro);
1230 score_eq2_next_lower_macro = -1.0;
1233 if ((macrovector[2] ==
'0' || macrovector[2] ==
'1') && macrovector[5] ==
'1')
1235 gchar *eq3eq6_next_lower_macro = g_strdup (macrovector);
1236 eq3eq6_next_lower_macro[2]++;
1237 score_eq3eq6_next_lower_macro =
1239 g_free (eq3eq6_next_lower_macro);
1241 else if (macrovector[2] ==
'1' && macrovector[5] ==
'0')
1243 gchar *eq3eq6_next_lower_macro = g_strdup (macrovector);
1244 eq3eq6_next_lower_macro[5]++;
1245 score_eq3eq6_next_lower_macro =
1247 g_free (eq3eq6_next_lower_macro);
1249 else if (macrovector[2] ==
'0' && macrovector[5] ==
'0')
1251 gchar *eq3eq6_next_lower_macro_left = g_strdup (macrovector);
1252 eq3eq6_next_lower_macro_left[5]++;
1253 gchar *eq3eq6_next_lower_macro_right = g_strdup (macrovector);
1254 eq3eq6_next_lower_macro_right[2]++;
1255 double score_eq3eq6_next_lower_macro_left =
1257 double score_eq3eq6_next_lower_macro_right =
1260 if (score_eq3eq6_next_lower_macro_left
1261 > score_eq3eq6_next_lower_macro_right)
1262 score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_left;
1264 score_eq3eq6_next_lower_macro = score_eq3eq6_next_lower_macro_right;
1266 g_free (eq3eq6_next_lower_macro_left);
1267 g_free (eq3eq6_next_lower_macro_right);
1270 score_eq3eq6_next_lower_macro = -1.0;
1273 if (macrovector[3] <=
'1')
1275 gchar *eq4_next_lower_macro = g_strdup (macrovector);
1276 eq4_next_lower_macro[3]++;
1277 score_eq4_next_lower_macro =
1279 g_free (eq4_next_lower_macro);
1282 score_eq4_next_lower_macro = -1.0;
1285 if (macrovector[4] <=
'1')
1287 gchar *eq5_next_lower_macro = g_strdup (macrovector);
1288 eq5_next_lower_macro[4]++;
1289 score_eq5_next_lower_macro =
1291 g_free (eq5_next_lower_macro);
1294 score_eq5_next_lower_macro = -1.0;
1298 *available_distance_eq1 = score_eq1_next_lower_macro != -1.0
1299 ? value - score_eq1_next_lower_macro
1301 *available_distance_eq2 = score_eq2_next_lower_macro != -1.0
1302 ? value - score_eq2_next_lower_macro
1304 *available_distance_eq3eq6 = score_eq3eq6_next_lower_macro != -1.0
1305 ? value - score_eq3eq6_next_lower_macro
1307 *available_distance_eq4 = score_eq4_next_lower_macro != -1.0
1308 ? value - score_eq4_next_lower_macro
1310 *available_distance_eq5 = score_eq5_next_lower_macro != -1.0
1311 ? value - score_eq5_next_lower_macro
1316 *available_distance_eq1 = -1.0;
1317 *available_distance_eq2 = -1.0;
1318 *available_distance_eq3eq6 = -1.0;
1319 *available_distance_eq4 = -1.0;
1320 *available_distance_eq5 = -1.0;
1334 const char **eq1_maxes, **eq2_maxes, **eq3eq6_maxes;
1335 const char *eq4_max, *eq5_max;
1339 static const char *eq1_maxes_0[] = {
"AV:N/PR:N/UI:N/", NULL};
1340 static const char *eq1_maxes_1[] = {
"AV:A/PR:N/UI:N/",
"AV:N/PR:L/UI:N/",
1341 "AV:N/PR:N/UI:P/", NULL};
1342 static const char *eq1_maxes_2[] = {
"AV:P/PR:N/UI:N/",
"AV:A/PR:L/UI:P/",
1344 if (macrovector[0] ==
'0')
1345 eq1_maxes = eq1_maxes_0;
1346 else if (macrovector[0] ==
'1')
1347 eq1_maxes = eq1_maxes_1;
1349 eq1_maxes = eq1_maxes_2;
1352 static const char *eq2_maxes_0[] = {
"AC:L/AT:N/", NULL};
1353 static const char *eq2_maxes_1[] = {
"AC:H/AT:N/",
"AC:L/AT:P/", NULL};
1354 if (macrovector[1] ==
'0')
1355 eq2_maxes = eq2_maxes_0;
1357 eq2_maxes = eq2_maxes_1;
1360 static const char *eq3eq6_maxes_00[] = {
"VC:H/VI:H/VA:H/CR:H/IR:H/AR:H/",
1362 static const char *eq3eq6_maxes_01[] = {
1363 "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};
1364 static const char *eq3eq6_maxes_10[] = {
1365 "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};
1366 static const char *eq3eq6_maxes_11[] = {
1367 "VC:L/VI:H/VA:L/CR:H/IR:M/AR:H/",
"VC:L/VI:H/VA:H/CR:H/IR:M/AR:M/",
1368 "VC:H/VI:L/VA:H/CR:M/IR:H/AR:M/",
"VC:H/VI:L/VA:L/CR:M/IR:H/AR:H/",
1369 "VC:L/VI:L/VA:H/CR:H/IR:H/AR:M/", NULL};
1370 static const char *eq3eq6_maxes_21[] = {
"VC:L/VI:L/VA:L/CR:H/IR:H/AR:H/",
1372 if ((macrovector[2] ==
'0'))
1374 if (macrovector[5] ==
'0')
1375 eq3eq6_maxes = eq3eq6_maxes_00;
1377 eq3eq6_maxes = eq3eq6_maxes_01;
1379 else if ((macrovector[2] ==
'1'))
1381 if (macrovector[5] ==
'0')
1382 eq3eq6_maxes = eq3eq6_maxes_10;
1384 eq3eq6_maxes = eq3eq6_maxes_11;
1387 eq3eq6_maxes = eq3eq6_maxes_21;
1390 if (macrovector[3] ==
'0')
1391 eq4_max =
"SC:H/SI:S/SA:S/";
1392 else if (macrovector[3] ==
'1')
1393 eq4_max =
"SC:H/SI:H/SA:H/";
1395 eq4_max =
"SC:L/SI:L/SA:L/";
1398 if (macrovector[4] ==
'0')
1400 else if (macrovector[4] ==
'1')
1405 GPtrArray *max_vectors = g_ptr_array_new ();
1406 const char **eq1_max, **eq2_max, **eq3eq6_max;
1407 for (eq1_max = eq1_maxes; *eq1_max != NULL; eq1_max++)
1409 for (eq2_max = eq2_maxes; *eq2_max != NULL; eq2_max++)
1411 for (eq3eq6_max = eq3eq6_maxes; *eq3eq6_max != NULL; eq3eq6_max++)
1413 gchar *full_vector =
1414 g_strdup_printf (
"%s%s%s%s%s", *eq1_max, *eq2_max, *eq3eq6_max,
1418 g_warning (
"%s: generated vector %s is invalid", __func__,
1421 g_ptr_array_add (max_vectors, vector);
1422 g_free (full_vector);
1427 g_ptr_array_add (max_vectors, NULL);
1429 ret = (gchar **) max_vectors->pdata;
1430 g_ptr_array_free (max_vectors, FALSE);
1586 const char *max_vec)
1605 double *current_severity_distance_eq1,
1606 double *current_severity_distance_eq2,
1607 double *current_severity_distance_eq3eq6,
1608 double *current_severity_distance_eq4,
1609 double *current_severity_distance_eq5)
1611 double severity_distance_AV, severity_distance_PR, severity_distance_UI;
1612 double severity_distance_AC, severity_distance_AT;
1613 double severity_distance_VC, severity_distance_VI, severity_distance_VA;
1614 double severity_distance_SC, severity_distance_SI, severity_distance_SA;
1615 double severity_distance_CR, severity_distance_IR, severity_distance_AR;
1617 severity_distance_AV = severity_distance_PR = severity_distance_UI = -99.0;
1618 severity_distance_AC = severity_distance_AT = -99.0;
1619 severity_distance_VC = severity_distance_VI = severity_distance_VA = -99.0;
1620 severity_distance_SC = severity_distance_SI = severity_distance_SA = -99.0;
1621 severity_distance_CR = severity_distance_IR = severity_distance_AR = -99.0;
1623 char **max_vectors, **max_vec;
1625 for (max_vec = max_vectors; *max_vec != NULL; max_vec++)
1646 if (severity_distance_AV < 0.0 || severity_distance_PR < 0.0
1647 || severity_distance_UI < 0.0 || severity_distance_AC < 0.0
1648 || severity_distance_AT < 0.0 || severity_distance_VC < 0.0
1649 || severity_distance_VI < 0.0 || severity_distance_VA < 0.0
1650 || severity_distance_SC < 0.0 || severity_distance_SI < 0.0
1651 || severity_distance_SA < 0.0 || severity_distance_CR < 0.0
1652 || severity_distance_IR < 0.0 || severity_distance_AR < 0.0)
1655 g_debug (
"%s AV:%0.1f PR:%0.1f UI:%0.1f |"
1656 " AC:%0.1f AT:%0.1f |"
1657 " VC:%0.1f VI:%0.1f VA:%0.1f |"
1658 " SC:%0.1f SI:%0.1f SA:%0.1f |"
1659 " CR:%0.1f IR:%0.1f AR:%0.1f",
1660 __func__, severity_distance_AV, severity_distance_PR,
1661 severity_distance_UI, severity_distance_AC, severity_distance_AT,
1662 severity_distance_VC, severity_distance_VI, severity_distance_VA,
1663 severity_distance_SC, severity_distance_SI, severity_distance_SA,
1664 severity_distance_CR, severity_distance_IR,
1665 severity_distance_AR);
1670 g_debug (
"%s: max_vec: %s", __func__, max_vec_expanded);
1671 g_free (max_vec_expanded);
1672 g_strfreev (max_vectors);
1674 *current_severity_distance_eq1 =
1675 severity_distance_AV + severity_distance_PR + severity_distance_UI;
1676 *current_severity_distance_eq2 = severity_distance_AC + severity_distance_AT;
1677 *current_severity_distance_eq3eq6 =
1678 severity_distance_VC + severity_distance_VI + severity_distance_VA
1679 + severity_distance_CR + severity_distance_IR + severity_distance_AR;
1680 *current_severity_distance_eq4 =
1681 severity_distance_SC + severity_distance_SI + severity_distance_SA;
1682 *current_severity_distance_eq5 = 0.0;
1698 double *max_severity_eq2,
double *max_severity_eq3eq6,
1699 double *max_severity_eq4)
1701 switch (macrovector[0])
1704 *max_severity_eq1 = 0.1;
1707 *max_severity_eq1 = 0.4;
1710 *max_severity_eq1 = 0.5;
1713 *max_severity_eq1 = -99.0;
1716 switch (macrovector[1])
1719 *max_severity_eq2 = 0.1;
1722 *max_severity_eq2 = 0.2;
1725 *max_severity_eq2 = -99.0;
1728 switch (macrovector[2])
1731 if (macrovector[5] ==
'0')
1732 *max_severity_eq3eq6 = 0.7;
1734 *max_severity_eq3eq6 = 0.6;
1737 *max_severity_eq3eq6 = 0.8;
1740 *max_severity_eq3eq6 = 1.0;
1743 *max_severity_eq3eq6 = -99.0;
1746 switch (macrovector[3])
1749 *max_severity_eq4 = 0.6;
1752 *max_severity_eq4 = 0.5;
1755 *max_severity_eq4 = 0.4;
1758 *max_severity_eq4 = -99.0;
1773 char *macrovector = NULL;
1775 double available_distance_eq1, available_distance_eq2;
1776 double available_distance_eq3eq6;
1777 double available_distance_eq4, available_distance_eq5;
1779 double current_severity_distance_eq1, current_severity_distance_eq2;
1780 double current_severity_distance_eq3eq6;
1781 double current_severity_distance_eq4, current_severity_distance_eq5;
1783 double max_severity_eq1, max_severity_eq2, max_severity_eq3eq6;
1784 double max_severity_eq4;
1786 double mean_distance, value;
1788 int n_existing_lower = 0;
1791 g_debug (
"%s: CVSS string: %s", __func__, cvss_str);
1793 g_debug (
"%s: simplified vector: %s", __func__, vec);
1800 g_debug (
"%s: macrovector: %s, value: %0.1f", __func__, macrovector, value);
1801 if (macrovector == NULL || value == -1.0)
1809 macrovector, &available_distance_eq1, &available_distance_eq2,
1810 &available_distance_eq3eq6, &available_distance_eq4,
1811 &available_distance_eq5);
1812 g_debug (
"%s: maximal scoring diffs:"
1813 " EQ1:%0.1f EQ2:%0.1f EQ3+EQ6:%0.1f EQ5:%0.1f EQ6:%0.1f",
1814 __func__, available_distance_eq1, available_distance_eq2,
1815 available_distance_eq3eq6, available_distance_eq4,
1816 available_distance_eq5);
1820 vec, macrovector, ¤t_severity_distance_eq1,
1821 ¤t_severity_distance_eq2, ¤t_severity_distance_eq3eq6,
1822 ¤t_severity_distance_eq4, ¤t_severity_distance_eq5);
1824 g_debug (
"%s: current severity distances:"
1825 "EQ1:%0.1f EQ2:%0.1f EQ3+EQ6:%0.1f EQ4:%0.1f EQ5:%0.1f",
1826 __func__, current_severity_distance_eq1,
1827 current_severity_distance_eq2, current_severity_distance_eq3eq6,
1828 current_severity_distance_eq4, current_severity_distance_eq5);
1832 &max_severity_eq3eq6, &max_severity_eq4);
1835 g_free (macrovector);
1838 mean_distance = 0.0;
1839 if (available_distance_eq1 >= 0.0)
1842 double percent_to_next_severity =
1843 (current_severity_distance_eq1) / max_severity_eq1;
1844 mean_distance += (available_distance_eq1 * percent_to_next_severity);
1847 if (available_distance_eq2 >= 0.0)
1850 double percent_to_next_severity =
1851 (current_severity_distance_eq2) / max_severity_eq2;
1852 mean_distance += (available_distance_eq2 * percent_to_next_severity);
1855 if (available_distance_eq3eq6 >= 0.0)
1858 double percent_to_next_severity =
1859 (current_severity_distance_eq3eq6) / max_severity_eq3eq6;
1860 mean_distance += (available_distance_eq3eq6 * percent_to_next_severity);
1863 if (available_distance_eq4 >= 0.0)
1866 double percent_to_next_severity =
1867 (current_severity_distance_eq4) / max_severity_eq4;
1868 mean_distance += (available_distance_eq4 * percent_to_next_severity);
1871 if (available_distance_eq5 >= 0.0)
1877 mean_distance = mean_distance / n_existing_lower;
1880 value = value - mean_distance;
1883 else if (value > 10.0)
1886 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:1604
#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:1098
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:1049
#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:1770
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:1443
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:1697
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:1585
#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:1332
#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:1196
#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