X-Git-Url: https://git.ralfj.de/tls-check.git/blobdiff_plain/162a2cded2b9e3b13de4b1439037df2b571c3a19..e07bca134da4fe65e1ebe88624bad606b81e073c:/tls-check diff --git a/tls-check b/tls-check index 33529d9..8be067e 100755 --- a/tls-check +++ b/tls-check @@ -59,7 +59,7 @@ def test_cipher(host, port, protocol, cipher = None, wait_time=0, options=[]): try: if cipher is not None: options = ["-cipher", cipher]+options - subprocess.check_call(["openssl", "s_client", "-"+protocol, "-connect", host+":"+str(port)]+options, + subprocess.check_call(["openssl", "s_client", "-"+protocol, "-connect", host+":"+str(port), "-servername", host]+options, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) except subprocess.CalledProcessError: return False @@ -118,10 +118,14 @@ class CipherPropsProvider: self.high = set(list_ciphers("HIGH")) self.props = {} - def __getProps(self, cipher): + def getProps(self, protocol, cipher): + # strip the sub-version-number from the protocol + pos = protocol.find('_') + if pos >= 0: + protocol = protocol[:pos] # as OpenSSL about this cipher - cipherInfo = subprocess.check_output(["openssl", "ciphers", "-v", cipher]).decode('UTF-8').strip() - assert '\n' not in cipherInfo + cipherInfo = subprocess.check_output(["openssl", "ciphers", "-v", "-"+protocol, cipher]).decode('UTF-8').strip() + assert '\n' not in cipherInfo, "Cipher "+cipher+" produced unexpected output:\n"+cipherInfo cipherInfoFields = cipherInfo.split() # get # of bits encMatch = re.match(r'^Enc=([0-9A-Za-z]+)\(([0-9]+)\)$', cipherInfoFields[4]) @@ -143,7 +147,7 @@ class CipherPropsProvider: isLow = cipher in self.low isMedium = cipher in self.medium isHigh = cipher in self.high - assert isExp+isLow+isMedium+isHigh <= 1, "Cipher is more than one from EXP, LOW, MEDIUM, HIGH" + assert isExp+isLow+isMedium+isHigh <= 1, "Cipher "+cipher+" is more than one from EXP, LOW, MEDIUM, HIGH" if isExp: strength = CipherStrength.exp elif isLow: @@ -156,19 +160,12 @@ class CipherPropsProvider: strength = CipherStrength.unknown # done! return CipherProps(bits=bits, strength=strength, isPfs=isPfs) - - def getProps(self, cipher): - if cipher in self.props: - return self.props[cipher] - props = self.__getProps(cipher) - self.props[cipher] = props - return props # main program if __name__ == "__main__": parser = argparse.ArgumentParser(description='Check TLS ciphers supported by a host') parser.add_argument("--starttls", dest="starttls", - help="Use a STARTTLS variant to establish the TLS connection. Possible values include smpt, imap.") + help="Use a STARTTLS variant to establish the TLS connection. Possible values include smtp, imap.") parser.add_argument("--wait-time", "-t", dest="wait_time", default="10", help="Time (in ms) to wait between two connections to the server. Default is 10ms.") parser.add_argument("host", metavar='HOST[:PORT]', @@ -200,7 +197,7 @@ if __name__ == "__main__": else: for cipher, supported in ciphers.items(): if supported: - cipherProps = propsProvider.getProps(cipher) + cipherProps = propsProvider.getProps(protocol, cipher) 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))