@@ 66,9 66,13 @@ def check_ocsp(domain, port, chain):
print(e)
-def get_tls_certificate(domain, port, timeout=5):
+def get_tls_certificate(domain, port, timeout=5, starttls=False):
ctx = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_2_METHOD)
conn = socket.create_connection((domain, port), timeout=timeout)
+ if starttls:
+ banner = conn.recv(1000)
+ conn.send(b'EHLO\nSTARTTLS\n')
+ leftover = conn.recv(1000)
sock = OpenSSL.SSL.Connection(ctx, conn)
sock.setblocking(True)
sock.set_connect_state()
@@ 78,11 82,13 @@ def get_tls_certificate(domain, port, timeout=5):
return chain
-def check_generic(domain, port, timeout=5):
+def check_generic(domain, port, timeout=5, starttls=False):
try:
- chain = get_tls_certificate(domain, port, timeout=timeout)
+ chain = get_tls_certificate(domain, port, timeout=timeout, starttls=starttls)
except TimeoutError:
return False, "Timeout"
+ except OpenSSL.SSL.Error as e:
+ return False, str(e)
x509 = chain[0]
components = x509.get_subject().get_components()
for component in components:
@@ 153,10 159,11 @@ def check_generic(domain, port, timeout=5):
def main():
parser = argparse.ArgumentParser("Certificate checker")
parser.add_argument('domain', nargs='+')
- parser.add_argument('--https', action=argparse.BooleanOptionalAction, default=True, help='Check http')
- parser.add_argument('--imaps', action=argparse.BooleanOptionalAction, default=False, help='Check imap')
- parser.add_argument('--pop3s', action=argparse.BooleanOptionalAction, default=False, help='Check pop3s')
- parser.add_argument('--smtps', action=argparse.BooleanOptionalAction, default=False, help='Check smtp')
+ parser.add_argument('--https', action=argparse.BooleanOptionalAction, default=True, help='Check http (443)')
+ parser.add_argument('--imaps', action=argparse.BooleanOptionalAction, default=False, help='Check imap (993)')
+ parser.add_argument('--pop3s', action=argparse.BooleanOptionalAction, default=False, help='Check pop3s (995)')
+ parser.add_argument('--smtps', action=argparse.BooleanOptionalAction, default=False, help='Check smtp (465)')
+ parser.add_argument('--submission', action=argparse.BooleanOptionalAction, default=False, help='Check smtp with starttls (587)')
parser.add_argument('--port', action="append", help="Check a specific port", default=[], type=int)
parser.add_argument('--timeout', '-t', default=5, help='Set the timeout in seconds for the TCP connection',
type=int)
@@ 173,6 180,8 @@ def main():
protolist.append('pop3s')
if args.smtps:
protolist.append('smtps')
+ if args.submission:
+ protolist.append('submission')
protolist.extend(args.port)
protocols = {
@@ 180,8 189,11 @@ def main():
'imaps': 993,
'pop3s': 995,
'smtps': 465,
+ 'submission': 587,
}
+ proto_len = len(max(protolist, key=lambda l: len(str(l))))
+
returncode = 0
for domain in args.domain:
print(domain.ljust(domain_len + 2), end='')
@@ 191,12 203,14 @@ def main():
if len(protolist) > 1:
if not first_proto:
print(' ' * (domain_len + 2), end='')
- print(f'{str(proto).ljust(5)} ', end='', flush=True)
+ print(f'{str(proto).ljust(proto_len)} ', end='', flush=True)
first_proto = False
if isinstance(proto, str):
proto = protocols[proto]
- result = check_generic(domain, proto, timeout=args.timeout)
+
+ starttls = proto == 587
+ result = check_generic(domain, proto, timeout=args.timeout, starttls=starttls)
if result[0] is True:
print(colorama.Fore.GREEN, result[1], colorama.Style.RESET_ALL)