From: Ralf Jung Date: Sat, 26 Jul 2014 14:06:50 +0000 (+0200) Subject: Colorful, aligned output X-Git-Url: https://git.ralfj.de/tls-check.git/commitdiff_plain/8891dd322baf391504d4c1091962ab238f450be7?ds=inline Colorful, aligned output --- diff --git a/tls-check b/tls-check index 27651d5..5e8e19e 100755 --- a/tls-check +++ b/tls-check @@ -3,7 +3,9 @@ import subprocess, sys, argparse, time, re from collections import OrderedDict, namedtuple from enum import Enum -# progress bar +# progress bar and other console output fun +STATE_WIDTH = 30 + def terminal_size(): import fcntl, termios, struct try: @@ -24,7 +26,6 @@ def compute_frac(fracs): return frac def print_progress(state, fracs): - STATE_WIDTH = 30 w, h = terminal_size() if w < STATE_WIDTH+10: return # not a (wide enough) terminal bar_width = w-STATE_WIDTH-3 @@ -35,7 +36,17 @@ def finish_progress(): w, h = terminal_size() sys.stdout.write('\r'+(' '*w)+'\r') sys.stdout.flush() + +class ConsoleFormat: + BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) + RESET_SEQ = "\033[0m" + COLOR_SEQ = "\033[1;3%dm" + BOLD_SEQ = "\033[1m" + @staticmethod + def color(text, color): + return (ConsoleFormat.COLOR_SEQ % color) + text + ConsoleFormat.RESET_SEQ + # cipher check def list_ciphers(spec="ALL:COMPLEMENTOFALL"): @@ -86,6 +97,17 @@ class CipherStrength(Enum): low = 1 medium = 2 high = 3 + + def colorName(self): + if self == CipherStrength.unknown: + return self.name + elif self.value == CipherStrength.high.value: + return ConsoleFormat.color(self.name, ConsoleFormat.GREEN) + elif self.value == CipherStrength.medium.value: + return ConsoleFormat.color(self.name, ConsoleFormat.YELLOW) + else: + return ConsoleFormat.color(self.name, ConsoleFormat.RED) + CipherProps = namedtuple('CipherProps', 'bits, strength, isPfs') class CipherPropsProvider: @@ -107,11 +129,11 @@ class CipherPropsProvider: raise Exception("Unexpected OpenSSL output: Cannot determine encryption strength from {1}\nComplete output: {0}".format(cipherInfo, cipherInfoFields[4])) bits = int(bitMatch.group(1)) # figure out whether the cipher is pfs - kxMatch = re.match(r'^Kx=([0-9A-Z/]+)$', cipherInfoFields[2]) + kxMatch = re.match(r'^Kx=([0-9A-Z/()]+)$', cipherInfoFields[2]) if kxMatch is None: - raise Exception("Unexpected OpenSSL output: Cannot determine key-exchange method from {1}\nComplete output: {0}".format(cipherInfo), cipherInfoFields[2]) + raise Exception("Unexpected OpenSSL output: Cannot determine key-exchange method from {1}\nComplete output: {0}".format(cipherInfo, cipherInfoFields[2])) kx = kxMatch.group(1) - isPfs = kx in ('DH', 'ECDH') + isPfs = kx in ('DH', 'DH(512)', 'ECDH') # determine security level isExp = cipher in self.exp isLow = cipher in self.low @@ -175,5 +197,7 @@ if __name__ == "__main__": for cipher, supported in ciphers.items(): if supported: cipherProps = propsProvider.getProps(cipher) - print(" {0} ({1}, {2} bits, {3})".format(cipher, cipherProps.strength.name, cipherProps.bits, "FS" if cipherProps.isPfs else "not FS")) + fsText = ConsoleFormat.color("FS", ConsoleFormat.GREEN) if cipherProps.isPfs else ConsoleFormat.color("no FS", ConsoleFormat.RED) + bitColor = ConsoleFormat.GREEN if cipherProps.bits > 128 else (ConsoleFormat.YELLOW if cipherProps.bits >= 100 else ConsoleFormat.RED) + print(" {0} ({1}, {2}, {3})".format(cipher.ljust(STATE_WIDTH), cipherProps.strength.colorName(), ConsoleFormat.color(str(cipherProps.bits)+" bits", bitColor), fsText)) print()