Changeset - e01ed30e9cca
[Not reviewed]
0 0 1
Branko Majic (branko) - 4 years ago 2020-06-29 04:17:09
branko@majic.rs
Added the initial LDAP CRL checker. Useful for verifying that CRLs are being published to the LDAP tree properly (when revoking certificates).
1 file changed with 239 insertions and 0 deletions:
0 comments (0 inline, 0 general)
x509/ldapcrl_checkserial.sh
Show inline comments
 
new file 100755
 
#!/bin/bash
 
#
 
# ldapcrl_checkserial.sh
 
#
 
# Copyright (C) 2013, PrimeKey Solutions AB
 
#
 
# 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/>.
 
#
 

	
 
program="ldapcrl_checkserial.sh"
 
version="0.1"
 

	
 
function usage() {
 
    cat <<EOF
 
$program $version, a semi-interactive utility for checking if a CRL in LDAP
 
contains a specific serial number.
 

	
 
Usage: $program [OPTIONS] issuer serial
 

	
 
$program is a semi-interactive utility for checking if a CRL in LDAP contains a
 
specific serial number. It is useful for verifying that new CRLs are being
 
published to the LDAP when revoking certificates. The utility is non-interactive
 
unless the user is required to provide credentials for the ldapsearch utility.
 

	
 
The script expects two positional arguments:
 

	
 
    issuer
 

	
 
    The issuer argument should be set to the issuer DN of the certification
 
    authority that has issued the CRL. This parameter will be used for locating
 
    the CRLs in the directory tree that have been issued by target CA.
 

	
 
    serial
 

	
 
    The serial argument should be set to the serial number of the certificate
 
    that has been revoked. The certificate should have been issued by the
 
    specified issuer. This serial number will be looked-up in the matching
 
    CRLs.
 

	
 
The script works by traversing the LDAP tree, looking for all entries that have
 
a CRL attribute. By default the script is expecting the CRLs to be located in
 
the attribute 'certificateRevocationList' (this can be overridden). Each CRL
 
will be checked for presence of the specified serial number.
 

	
 
Once the script is finished traversing the LDAP tree, it will output a summary
 
about the number of processed CRLs, and an informative message about whether the
 
check has failed or not. The script will return a non-zero error code if the
 
check has failed.
 

	
 
The check is considred as failed if one of the following conditions are met:
 

	
 
    - There was no CRL in the LDAP direcotry issued by the specified CA.
 
    - At least one CRL in the LDAP direcotry that was issued by the specified CA
 
      does not contain the specified serial number.
 

	
 
The check is considred as successful if and only if there was at least on CRL
 
issued by the specified CA in the LDAP directory, and all of the CRLs issued by
 
the specified CA in the LDAP directory contain the specified serial number.
 

	
 
The script relies on using the ldapsearch utility from OpenLDAP for traversing
 
the LDAP directory. Any configuration settings specified in the global or local
 
(user's) LDAP client configuration file will be applied during
 
search. Additional parameters can be passed to the ldapsearch utility as well by
 
using the -L flag.
 

	
 
$program accepts the following options:
 

	
 
    -L ldapop Pass additional option to the ldapsearch utility used for
 
              retrieving the CRL from the LDAP database. This option can be
 
              specified multiple times.
 

	
 
    -a attr   LDAP attribute that should contain the CRL. Default is
 
              'certificateRevocationList'.
 

	
 
    -v        show script version and licensing information
 
    -h        show usage help
 

	
 

	
 
Please report bugs and send feature requests to <branko.majic@primekey.se>.
 
EOF
 
}
 

	
 
function version() {
 
        cat <<EOF
 
$program, version $version
 

	
 
+-----------------------------------------------------------------------+
 
| Copyright (C) 2013, PrimeKey Solutions AB                             |
 
|                                                                       |
 
| 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/>. |
 
+-----------------------------------------------------------------------+
 

	
 
EOF
 
}
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z $1 ]]; then
 
    usage
 
    exit 0
 
fi
 

	
 
# Set-up default parameters
 
ldapOptions=()
 
crlAttribute="certificateRevocationList"
 

	
 
# Parse the arguments
 
while getopts "L:a:vh" opt; do
 
    case "$opt" in
 
        L) ldapOptions+=("$OPTARG");;
 
        a) crlAttribute="$OPTARG";;
 
        v) version
 
           exit 0;;
 
        h) usage
 
           exit 0;;
 
        *) usage
 
           exit 1;;
 
    esac
 
done
 
i=$OPTIND
 
shift $(($i-1))
 

	
 
# Read the positional arguments.
 
issuer="$1"
 
serial="$2"
 

	
 
# Verify the arguments.
 
if [[ -z $issuer ]]; then
 
    echo "Issuer was not specified." >&2
 
    exit 3
 
fi
 
if [[ -z $serial ]]; then
 
    echo "Serial number was not specified." >&2
 
    exit 3
 
fi
 
if [[ ! $serial =~ ^[0123456789abcdefABCDEF]+$ ]]; then
 
    echo "Invalid serial number specified: '$serial'" >&2
 
    echo "Serial number may contain the following characters: 0123456789abcdefABCDEF" >&2
 
    exit 3
 
fi
 

	
 
# Start assembling the ldapsearch command. Remove the cruft from output
 
# (comments etc), and also disable wrapping of long line.x
 
command=("ldapsearch" "-LLL" "-oldif-wrap=no")
 
# Pass the user-provided options.
 
command+=("${ldapOptions[@]}")
 
# Look only for entities that have the request CRL attribute, and return only
 
# that attribute.
 
command+=("(${crlAttribute}=*)")
 
command+=("${crlAttribute}")
 

	
 
# Perform the ldap search. Store the result. Bail-out if an error has happened.
 
if ! searchResult=$("${command[@]}"); then
 
    echo "Failed to perform ldapsearch with the provided options." >&2
 
    exit 10
 
fi
 

	
 
# Keep track of how many CRLs from the issuer have been processed, how many of
 
# those did contain (matched) the serial number, and how many of those did _not_
 
# contain the serial number (non-matches).
 
processed=0
 
matches=0
 
nonMatches=0
 

	
 
# Output a useful begin message.
 
echo "CRL Issuer:    $issuer"
 
echo "Serial number: $serial"
 
echo
 

	
 
# Parse the LDAP search result.
 
while read line; do
 
    # Have we encountered the DN attribute?
 
    if [[ $line =~ ^dn: ]]; then
 
        dn="${line#*: }"
 
    # Have we encountered the CRL?    
 
    elif [[ $line =~ ^$crlAttribute ]]; then
 
        crl="${line#*:: }"
 
    # If we have reached a blank line, that means we can process our DN and CRL now.
 
    elif [[ $line =~ ^$ && dn != "" && crl != "" ]]; then
 
        # Get the CRL issuer from the list.
 
        crlIssuer=$(echo $crl | base64 --decode | openssl crl -noout -inform DER -issuer | sed -e 's#^issuer=/##;s#/#,#g')
 

	
 
        # If the CRL was issued by requested issuer, process it.
 
        if [[ $crlIssuer == $issuer ]]; then
 
            echo "Located CRL for issuer under DN '$dn'."
 
            let processed++
 

	
 
            # Check if the requested serial number is present in the CRL.
 
            if echo "$crl" | base64 --decode| openssl crl -inform DER -noout -text | grep 'Serial Number' \
 
                | sed -e 's/[[:blank:]]*Serial Number: //' | grep -q -i "^${serial}$"; then
 
                echo "Serial number present."
 
                let matches++
 
            else
 
                echo "Serial number not present."
 
                let nonMatches++
 
            fi
 
        fi
 

	
 
        # Reset the parameters used for parsing.
 
        unset dn crl
 
    fi
 
done < <(echo -e "${searchResult}\n")
 
echo
 
echo "Total number of CRLs with designated issuer in LDAP:     $processed"
 
echo "Number of CRLs that did contain the serial number:       $matches"
 
echo "Number of CRLs that did not contain the serial number:   $nonMatches"
 
echo
 
if [[ $processed == 0 ]]; then
 
    echo "No CRL was found in LDAP directory with the specified issuer DN."
 
    exit 11
 
elif [[ $matches != $processed ]]; then
 
    echo "Not all CRLs have passed the test."
 
    exit 12
 
else
 
    echo "All CRLs have passed the test."
 
    exit 0
 
fi
 

	
0 comments (0 inline, 0 general)