scripts/utils/check_cert.py

123 lines
3.4 KiB
Python
Executable file

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# check_cert.py -- Petit mail de vérification du certificat d'un serveur
# ce script vérifie principalement la date d'expiration et envoie un mail
# d'avertissement si celle-ci est proche (paramétrable)
#
# Copyright (c) 2013 Daniel STAN
# Authors: Daniel STAN <daniel.stan@crans.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from M2Crypto import SSL
from M2Crypto import X509
import ssl
import socket
import time
import datetime
import sys
# Envoyer des mails
from email.mime.text import MIMEText
import smtplib
#
# Config !
#
host = 'localhost'
port = 443
filename = False # if True, port ignored and host is in fact a path
# afficher la sortie plutôt que l'envoyer:
verb = False
# delai d'avertissement
delay = datetime.timedelta(days=15)
# infos mails
mail_src = 'root@crans.org'
mail_dest = "roots@crans.org"
mail_host = 'localhost'
#
# Argument parsing !
#
# TODO argparse + doc
for arg in sys.argv[1:]:
if arg == '-v':
verb = True
continue
if arg == '--filename':
filename = True
try:
port = int(arg)
except ValueError:
host = arg
#
# Getting cert !
#
if filename:
cert = X509.load_cert(host)
elif port != 25:
conn = SSL.Connection(SSL.Context())
try:
conn.connect((host, port))
except SSL.Checker.WrongHost:
if host != 'localhost':
raise
cert = conn.get_peer_cert()
conn.close()
expire_date = cert.get_not_after().get_datetime()
subject = cert.get_subject.as_text()
try:
altname = "(alt: %s)" % cert.get_ext('subjectAltName').get_value()
except LookupError:
altname = ""
else:
smtp = socket.socket()
smtp.connect((host, port))
resp = smtp.recv(4096)
smtp.send("EHLO localhost\n")
resp = smtp.recv(4096)
smtp.send("STARTTLS\n")
resp = smtp.recv(4096)
smtp = ssl.wrap_socket(smtp, cert_reqs=ssl.CERT_REQUIRED, ca_certs="/etc/ssl/certs/ca-certificates.crt")
cert = smtp.getpeercert()
# DROOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOGUES
expire_date = datetime.datetime.fromtimestamp(time.mktime(time.strptime(cert['notAfter'], "%b %d %H:%M:%S %Y %Z")))
subject = cert["subject"][0][0][1].decode("UTF-8")
altname = ""
#
# Real computation (woah !)
#
now = datetime.datetime.now(expire_date.tzinfo)
if now + delay > expire_date or verb:
short_sub = subject
subject += altname
msg = MIMEText(u"""Attention, le certificat suivant arrive bientôt à expiration :\n%s\n
Temps avant expiration: %s""" % (subject,(expire_date - now)), _charset="utf-8")
msg['From'] = mail_src
msg['To'] = mail_dest
msg['Subject'] = u"Expiration imminente du certificat %s" % short_sub
if not verb:
conn = smtplib.SMTP(mail_host)
conn.sendmail(mail_src, mail_dest, msg.as_string())
conn.quit()
else:
print msg.get_payload(decode=True)