[ini]
This commit is contained in:
commit
6b38521bea
78
source/helpers/certinfo.py
Normal file
78
source/helpers/certinfo.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import subprocess as _subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def get_certificate_info_raw(source):
|
||||||
|
p1 = _subprocess.Popen(
|
||||||
|
["openssl", "x509", "-outform", "pem"],
|
||||||
|
stdin = _subprocess.PIPE,
|
||||||
|
stdout = _subprocess.PIPE
|
||||||
|
)
|
||||||
|
(p1_stdout, p1_stderr, ) = p1.communicate(input = bytes(source, "utf-8"))
|
||||||
|
p2 = _subprocess.Popen(
|
||||||
|
["openssl", "x509", "-noout", "-text"],
|
||||||
|
stdin = _subprocess.PIPE,
|
||||||
|
stdout = _subprocess.PIPE
|
||||||
|
)
|
||||||
|
(p2_stdout, p2_stderr, ) = p2.communicate(input = p1_stdout)
|
||||||
|
return p2_stdout.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def get_certificate_info_from_file(path):
|
||||||
|
return get_certificate_info_raw(
|
||||||
|
_subprocess.check_output(
|
||||||
|
["cat", path],
|
||||||
|
text = True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_certificate_info_from_internet(domain):
|
||||||
|
return get_certificate_info_raw(
|
||||||
|
_subprocess.check_output(
|
||||||
|
["openssl", "s_client", "-connect", ("%s:443" % domain), "-showcerts"],
|
||||||
|
stdin = _subprocess.DEVNULL,
|
||||||
|
stderr = _subprocess.DEVNULL,
|
||||||
|
text = True
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_fingerprint(certificate_info):
|
||||||
|
state = {
|
||||||
|
"situation": 0,
|
||||||
|
"result": "",
|
||||||
|
}
|
||||||
|
for line in certificate_info.split("\n"):
|
||||||
|
if (state["situation"] == 0):
|
||||||
|
if (line.strip() == "Subject Public Key Info:"):
|
||||||
|
state = {
|
||||||
|
"situation": 1,
|
||||||
|
"result": state["result"],
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
elif (state["situation"] == 1):
|
||||||
|
if (line.strip() == "pub:"):
|
||||||
|
state = {
|
||||||
|
"situation": 2,
|
||||||
|
"result": state["result"],
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
elif (state["situation"] == 2):
|
||||||
|
if (line.startswith(" ")):
|
||||||
|
state = {
|
||||||
|
"situation": 2,
|
||||||
|
"result": (state["result"] + line.strip().replace(":", "")),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
state = {
|
||||||
|
"situation": 3,
|
||||||
|
"result": state["result"]
|
||||||
|
}
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
return state["result"]
|
||||||
|
|
||||||
|
|
||||||
7
source/helpers/string.py
Normal file
7
source/helpers/string.py
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
def coin(template, arguments):
|
||||||
|
result = template
|
||||||
|
for (key, value, ) in arguments.items():
|
||||||
|
result = result.replace("{{%s}}" % key, value)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
62
source/verify.py
Normal file
62
source/verify.py
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import sys as _sys
|
||||||
|
import argparse as _argparse
|
||||||
|
|
||||||
|
import helpers.string as _string
|
||||||
|
import helpers.certinfo as _certinfo
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
## args
|
||||||
|
argument_parser = _argparse.ArgumentParser(
|
||||||
|
prog = "tls-verify",
|
||||||
|
description = "compares the fingerprints of a TLS certificate on the machine with the one delivered through the internet for a given domain",
|
||||||
|
)
|
||||||
|
argument_parser.add_argument(
|
||||||
|
"domain",
|
||||||
|
type = str,
|
||||||
|
metavar = "<domain>",
|
||||||
|
)
|
||||||
|
argument_parser.add_argument(
|
||||||
|
"-d",
|
||||||
|
"--cert-directory",
|
||||||
|
type = str,
|
||||||
|
default = "/etc/ssl/fullchains",
|
||||||
|
metavar = "<cert-directory>",
|
||||||
|
)
|
||||||
|
argument_parser.add_argument(
|
||||||
|
"-e",
|
||||||
|
"--file-extension",
|
||||||
|
type = str,
|
||||||
|
default = "pem",
|
||||||
|
metavar = "<file-extension>",
|
||||||
|
)
|
||||||
|
args = argument_parser.parse_args()
|
||||||
|
|
||||||
|
## exec
|
||||||
|
fingerprint_shall = _certinfo.extract_fingerprint(
|
||||||
|
_certinfo.get_certificate_info_from_file(
|
||||||
|
_string.coin(
|
||||||
|
"{{directory}}/{{domain}}.{{extension}}",
|
||||||
|
{
|
||||||
|
"directory": args.cert_directory,
|
||||||
|
"domain": args.domain,
|
||||||
|
"extension": args.file_extension
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
fingerprint_is = _certinfo.extract_fingerprint(
|
||||||
|
_certinfo.get_certificate_info_from_internet(
|
||||||
|
args.domain
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if (fingerprint_shall == fingerprint_is):
|
||||||
|
_sys.stdout.write("ok\n")
|
||||||
|
_sys.exit(0)
|
||||||
|
else:
|
||||||
|
_sys.stderr.write("!MISMATCH!\n")
|
||||||
|
_sys.stderr.write("[shall] %s\n" % fingerprint_shall)
|
||||||
|
_sys.stderr.write("[is ] %s\n" % fingerprint_is)
|
||||||
|
_sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
36
tools/build
Executable file
36
tools/build
Executable file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
## consts
|
||||||
|
|
||||||
|
dir_source="source"
|
||||||
|
dir_temp="/tmp/tls-utils-temp"
|
||||||
|
dir_build="/tmp/tls-utils"
|
||||||
|
|
||||||
|
|
||||||
|
## vars
|
||||||
|
|
||||||
|
path_verify=${dir_build}/tls-verify
|
||||||
|
|
||||||
|
|
||||||
|
## exec
|
||||||
|
|
||||||
|
### exec:verify
|
||||||
|
|
||||||
|
rm ${dir_temp} --force --recursive
|
||||||
|
mkdir ${dir_temp} --parents
|
||||||
|
cp ${dir_source}/. ${dir_temp}/ --recursive --update --verbose
|
||||||
|
for dir in $(find ${dir_temp} -mindepth 1 -type d) ; do touch ${dir}/__init__.py ; done
|
||||||
|
echo '' > ${dir_temp}/__main__.py
|
||||||
|
echo 'from verify import *' >> ${dir_temp}/__main__.py
|
||||||
|
echo 'if __name__ == "__main__": main()' >> ${dir_temp}/__main__.py
|
||||||
|
|
||||||
|
mkdir ${dir_build} --parents
|
||||||
|
# rm ${path_verify}.zip --force
|
||||||
|
cd ${dir_temp}
|
||||||
|
python3 -m zipfile -c ${path_verify}.zip .
|
||||||
|
cd -
|
||||||
|
echo '#!/usr/bin/env python3' > ${path_verify}
|
||||||
|
cat ${path_verify}.zip >> ${path_verify}
|
||||||
|
rm ${path_verify}.zip
|
||||||
|
chmod +x ${path_verify}
|
||||||
|
|
||||||
Loading…
Reference in a new issue