File: interactive.py

package info (click to toggle)
python-cvss 3.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 107,168 kB
  • sloc: python: 3,230; makefile: 15; sh: 6
file content (131 lines) | stat: -rw-r--r-- 4,187 bytes parent folder | download
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
# Copyright (c) 2016 Red Hat, Inc.
# Author: Stanislav Kontar, Red Hat Product Security
# License: LGPLv3+

"""
Functions for interactively building CVSS vector string.

Compatible with both Python 2 and Python 3.
"""

from __future__ import print_function, unicode_literals

try:
    # noinspection PyUnresolvedReferences
    string_input = raw_input
except NameError:
    string_input = input


def color(text):
    """
    Replaces text in brackets with yellow bold variant for terminal. Also replaces | symbol with
    blue one. Should improve readability. Uses ANSI Styling codes.
    """
    colored = text.replace("(", "\033[33m\033[1m").replace(")", "\033[0m")
    colored = colored.replace("|", "\033[94m\033[1m|\033[0m")
    return colored


def ask_interactively(version=3.1, all_metrics=False, no_colors=False):
    """
    Asks user to build CVSS vector string interactively.

    Args:
        version (float): 2 or 3.0/3.1 or 4 for CVSS2 or CVSS3 or CVSS4 respectively
        all_metrics (bool): If true, temporal and environmental metrics are asked, else only base
                            metrics are asked for
        no_colors (bool): If true, terminal coloring is not used in interactive mode

    Returns:
        (str): CVSS vector
    """
    # Import correct constants
    if version == 2:
        print("Interactive CVSS2 calculator")
        from .constants2 import (
            METRICS_ABBREVIATIONS,
            METRICS_MANDATORY,
            METRICS_VALUE_NAMES,
        )
    elif 3.0 <= version < 4.0:
        print("Interactive CVSS3 calculator")
        from .constants3 import (
            METRICS_ABBREVIATIONS,
            METRICS_MANDATORY,
            METRICS_VALUE_NAMES,
        )
    elif version == 4.0:
        print("Interactive CVSS4 calculator")
        from .constants4 import (
            METRICS_ABBREVIATIONS,
            METRICS_MANDATORY,
            METRICS_VALUE_NAMES,
        )
    else:
        raise ValueError("Unknown version: {0}".format(version))
    print()

    vector = []

    if all_metrics:
        metrics = METRICS_ABBREVIATIONS.keys()
    else:
        metrics = METRICS_MANDATORY

    for metric in metrics:
        # Print full metric name
        print(METRICS_ABBREVIATIONS[metric] + ":", end=" ")

        # Create metric value names with hints
        values = METRICS_VALUE_NAMES[metric]
        value_names = []
        for value in values:
            name = METRICS_VALUE_NAMES[metric][value]
            name_with_hints = name
            for letter in value:
                name_with_hints = name_with_hints.replace(letter, "(" + letter + ")")

            # Exceptions for hints
            if version >= 3.0 and name_with_hints == "Not Defined":
                name_with_hints = "(X)Not Defined"
            elif version < 3.0:
                name_with_hints = {
                    "(P)roof-of-(C)oncept": "(P)roof-(O)f-(C)oncept",
                    "(U)nconfirmed": "(U)n(C)onfirmed",
                    "(U)ncorroborated": "(U)nco(R)roborated",
                }.get(name_with_hints, name_with_hints)

            value_names.append(name_with_hints)

        # Print value names with hints
        value_names_string = " | ".join(value_names)
        if no_colors:
            print(value_names_string)
        else:
            print(color(value_names_string))

        # Ask for input
        while True:
            print(METRICS_ABBREVIATIONS[metric] + ":", end=" ")
            print("/".join(values), end=" ")
            input_value = string_input().strip().upper()
            if not input_value:
                if version == 2:
                    input_value = "ND"
                else:
                    input_value = "X"
            if input_value in values:
                vector.append(metric + ":" + input_value)
                break
        print()

    if version == 3.0:
        vector_string = "CVSS:3.0/" + "/".join(vector)
    elif version == 3.1:
        vector_string = "CVSS:3.1/" + "/".join(vector)
    elif version == 4.0:
        vector_string = "CVSS:4.0/" + "/".join(vector)
    else:
        vector_string = "/".join(vector)
    return vector_string