summaryrefslogtreecommitdiff
path: root/tools/qmail-tls-check_certs
blob: 0d735961b256f050659ff73cf6aa0bee4fed186e (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 it marked as cert as "bad" (typically because it's
# expired), it will be renamed, a syslog event generated, and probably
# Qmail will STOP WORKING FOR NEW TLS SESSIONS.
#
# That may sound bad, but the alternative is that Qmail will stop working
# for new TLS sessions *anyway* - it's just that this script will tell
# you why...

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

dir=''
dirlist="/etc/qmail/control /var/qmail/control"
for trydir in $dirlist ; do
  if test -d $trydir ; then
    dir=$trydir
    break
  fi
done
if test -z "$dir" ; then
  1>&2 echo "Cannot find any control directory ($dirlist)"
  exit 1
fi

certlist=""
for arg in "$@" ; do
  case $arg in
    -server) certlist="$certlist servercert.pem" ;;
    -client) certlist="$certlist clientcert.pem" ;;
    *) 1>&2 echo "Unrecognized verbiage: '$arg'"
       exit 1
  esac 
done

if test -z "$certlist" ; then
  certlist="servercert.pem clientcert.pem"
fi

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

        #Now check it hasn't expired
        TEMP_DATE=$( openssl x509 -in $dir/$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 "$dir/$cert has EXPIRED. Disabling"
                    mv -f $dir/$cert $dir/EXPIRED-${cert}
                    $LOGGER "$dir/$cert has EXPIRED. Disabling"
                    continue
                fi
            fi
        fi

        if [ "`echo $cert|grep server`" != "" ] ; then
            if [ "_$( echo $TEMP_PURPOSE | \
                    egrep -i '(any purpose|server).* yes' )" = "_" ]; then
                echo "$dir/$cert is NOT a server cert. Disabled"
                mv -f $dir/$cert $dir/NOT-A-SERVER-CERT-${cert}
                $LOGGER "$dir/$cert is NOT a server cert. Disabled"
                continue
            fi
        fi
        if [ "`echo $cert|grep client`" != "" ] ; then
            if [ "_$( echo $TEMP_PURPOSE |
                   egrep -i '(any purpose|client).* yes' )" = "_" ]; then
                echo "$dir/$cert is NOT a client cert. Disabled"
                mv -f $dir/$cert $dir/NOT-A-CLIENT-CERT-${cert}
                $LOGGER "$dir/$cert is NOT a client cert. Disabled"
            fi
        fi
    fi

done