summaryrefslogtreecommitdiff
path: root/tools/qmail-tls-check_certs
blob: a3793994f1235edc2ff646ef8148c1f6104b7931 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/bin/sh
#
# Author: Jason Haar <jhaar@users.sourceforge.net>
# Date: 09-Nov-2004
# Version: 1.0
# Copyright: GPL
#
# This script simply checks the status of the certificates used by
# Qmail with Frederik Vermeulen's TLS patch - to ensure they are
# valid, non-expired certs with the appropriate KeyUsage extensions
# required to get their jobs done.
# This script can be run on a nightly basis to check the cert status.
# Note that when a cert is "bad" (typically because it's
# expired), we send a warning via syslog.
# If the cert is bad, Qmail will STOP WORKING FOR NEW TLS SESSIONS.
#
# The point of this script is to tell you *why* qmail is not working.

LOGGER="logger -i -t qmail-tls-check_certs"

dirlist="/etc/qmail/control /var/qmail/control"
for trydir in $dirlist ; do
  if test -d $trydir ; then
    dir=$trydir
    break
  fi
done

certlist=""
for arg in "$@" ; do
  case $arg in
    -stunnel) certlist=/etc/stunnel/stunnel.pem ;;
    -starttls) 
      if test -z "$dir" ; then
        1>&2 echo "Sorry, can't find the control directory ($dirlist)"
        exit1
      fi
      certlist="$dir/servercert.pem $dir/clientcert.pem"
      ;;
    *) 1>&2 echo "Unrecognized verbiage: '$arg'"
       exit 1
  esac 
done

if test -z "$certlist" ; then
  if test -z "$dir" ; then
    1>&2 echo "Cannot find any control directory ($dirlist)"
    exit 1
  fi
  certlist="$dir/servercert.pem $dir/clientcert.pem"
fi

for cert in $certlist ; do
    if ! test -f "$cert"; then
        echo "Certificate missing: $cert"
    else
        #First, check that it's a valid cert for the task
        TEMP_PURPOSE=`openssl x509 -in $cert -noout -purpose 2>/dev/null`
        if [ "$?" != "0" ]; then
                echo "$cert is a broken cert."
                $LOGGER "$cert is a broken cert."
                continue
        fi

        #Now check it hasn't expired
        TEMP_DATE=$( openssl x509 -in $cert -noout -dates 2>/dev/null | \
                grep -i after|cut -d= -f2 )
        EXPIRE_IN_SECS=`date +%s --date $TEMP_DATE 2>/dev/null`
        if [ "`echo $EXPIRE_IN_SECS|egrep '^[0-9]+$'`" != "" ]; then
            NOW_IN_SECS=`date +%s 2>/dev/null`
            if [ "`echo $NOW_IN_SECS|egrep '^[0-9]+$'`" != "" ]; then
                if [ $NOW_IN_SECS -gt $EXPIRE_IN_SECS ]; then
                    echo "$cert has EXPIRED."
                    $LOGGER "$cert has EXPIRED."
                    continue
                fi
            fi
        fi

        if [ "`echo $cert|grep server`" != "" ] ; then
            if [ "_$( echo $TEMP_PURPOSE | \
                    egrep -i '(any purpose|server).* yes' )" = "_" ]; then
                echo    "$cert is NOT a server cert."
                $LOGGER "$cert is NOT a server cert."
                continue
            fi
        fi
        if [ "`echo $cert|grep client`" != "" ] ; then
            if [ "_$( echo $TEMP_PURPOSE |
                   egrep -i '(any purpose|client).* yes' )" = "_" ]; then
                echo "   $cert is NOT a client cert."
                $LOGGER "$cert is NOT a client cert."
                continue
            fi
        fi
    fi

done