|
new file 100755
|
|
|
#!/bin/bash
|
|
|
#
|
|
|
# crlpublisher.sh
|
|
|
#
|
|
|
# Copyright (C) 2012, Branko Majic <branko@majic.rs>
|
|
|
#
|
|
|
# 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="crlpublisher.sh"
|
|
|
version="0.1.1"
|
|
|
|
|
|
function usage() {
|
|
|
cat <<EOF
|
|
|
$program $version, a non-interactive utility for publishing CRL's.
|
|
|
|
|
|
Usage: $program [OPTIONS] crl_file
|
|
|
|
|
|
$program is a non-interactive utility for publishing CRL's. It takes a single
|
|
|
argument pointing to the CRL file which should be published. The CRL file should
|
|
|
be provided either in DER or PEM encoding.
|
|
|
|
|
|
The script is written to support several types of publishers. Currently
|
|
|
supported publishers are:
|
|
|
|
|
|
- scp - Publishes to a remote server using public-key authentication through
|
|
|
SSH's scp command.
|
|
|
|
|
|
Publishing options are kept within configuration files. Configuration files
|
|
|
should be placed in one of the following directories:
|
|
|
|
|
|
- /etc/crlpublisher/
|
|
|
- ~/.crlpublisher/
|
|
|
|
|
|
Configuration files must end with a .conf extension. All other files will be
|
|
|
ignored. Each configuraiton file should contain information for a single
|
|
|
publisher matching a single issuer DN.
|
|
|
|
|
|
Common configuration options
|
|
|
|
|
|
issuerDn (mandatory) - Specifies the distinguished name of the issuer of CRL
|
|
|
which should be matched for the particular configuration.
|
|
|
|
|
|
publisher (mandatory) - Type of publisher this configuration refers to.
|
|
|
|
|
|
|
|
|
Configuration options for 'scp' publisher:
|
|
|
|
|
|
remoteHost (mandatory) - Remote IP or resolvable hostname/FQDN of the target
|
|
|
server to which the CRL will be published.
|
|
|
|
|
|
remoteLocation (mandatory) - Full path on the remote server to the directory
|
|
|
location to which the CRL will be published.
|
|
|
|
|
|
remoteUser (optional) - Name of the remote user which will be used for
|
|
|
logging-in. Default is the user executing the script.
|
|
|
|
|
|
privateKey (optional) - Path to the private key which should be used for
|
|
|
logging-in onto remote server. Default is ~/.ssh/id_rsa.
|
|
|
|
|
|
remotePort (optional) - Remote port that should be used for connecting to
|
|
|
the SSH server on remote host. Default is to use port 22.
|
|
|
|
|
|
|
|
|
$program accepts the following options:
|
|
|
|
|
|
-v show script version and licensing information
|
|
|
-h show usage help
|
|
|
|
|
|
|
|
|
Please report bugs and send feature requests to <branko@majic.rs>.
|
|
|
EOF
|
|
|
}
|
|
|
|
|
|
function version() {
|
|
|
cat <<EOF
|
|
|
$program, version $version
|
|
|
|
|
|
+-----------------------------------------------------------------------+
|
|
|
| Copyright (C) 2012, Branko Majic <branko@majic.rs> |
|
|
|
| |
|
|
|
| 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
|
|
|
}
|
|
|
|
|
|
#
|
|
|
# Helper function that parses a CRL.
|
|
|
#
|
|
|
# Sets:
|
|
|
# crlIssuerDn - to the value of the CRL issuer's distinguished name.
|
|
|
#
|
|
|
function readCrlInfo() {
|
|
|
local crlFile="$1"
|
|
|
unset crlIssuerDn
|
|
|
|
|
|
# Assume that the CRL is in DER format
|
|
|
if ! crlIssuerDn="$(openssl crl -issuer -inform DER -noout -in "$crlFile")"; then
|
|
|
if ! crlIssuerDn="$(openssl crl -issuer -inform PEM -noout -in "$crlFile")"; then
|
|
|
echo "Invalid CRL file '$crlFile'" >&2
|
|
|
return 1
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
crlIssuerDn="$(echo "$crlIssuerDn" | sed -e 's#^issuer=/##;s#/#,#g')"
|
|
|
|
|
|
return 0
|
|
|
}
|
|
|
|
|
|
#
|
|
|
# Helper function for clearing the common parameters. This function output
|
|
|
# commands that should be executed in order to clear the parameters (by using
|
|
|
# the "echo" command for example).
|
|
|
#
|
|
|
function clearCommonParameters() {
|
|
|
echo "local issuerDn publisher"
|
|
|
}
|
|
|
|
|
|
#
|
|
|
# Helper function for verifying the common parameters
|
|
|
#
|
|
|
function verifyCommonParameters() {
|
|
|
if [[ -z "$issuerDn" ]]; then
|
|
|
echo "Publisher ($configFile): missing issuer DN" >&2
|
|
|
return 1
|
|
|
fi
|
|
|
if [[ -z "$publisher" ]]; then
|
|
|
echo "Publisher ($configFile): missing publisher type." >&2
|
|
|
return 1
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
#
|
|
|
# Implementation of scp-based publisher.
|
|
|
#
|
|
|
function publish_through_scp() {
|
|
|
local configFile="$1" crlFile="$2"
|
|
|
local remoteUser="$USER" remoteHost remoteLocation privateKey="$HOME/.ssh/id_rsa" remotePort="22"
|
|
|
|
|
|
$(clearCommonParameters)
|
|
|
|
|
|
. "$configFile"
|
|
|
|
|
|
verifyCommonParameters || return 1
|
|
|
|
|
|
if ! [[ -f $privateKey ]]; then
|
|
|
echo "SCP publisher ($configFile): invalid private key - '$privateKey'." >&2
|
|
|
return 1
|
|
|
elif [[ -z $remoteHost ]]; then
|
|
|
echo "SCP publisher ($configFile): missing 'remoteHost' option." >&2
|
|
|
return 1
|
|
|
elif [[ -z $remoteLocation ]]; then
|
|
|
echo "SCP publisher ($configFile): missing 'remoteLocation' option." >&2
|
|
|
return 1
|
|
|
elif [[ -z "$remotePort" ]]; then
|
|
|
echo "SCP publisher ($configFile): missing 'remotePort' option." >&2
|
|
|
return 1
|
|
|
elif [[ ! $remotePort =~ ^[[:digit:]]+$ ]]; then
|
|
|
echo "SCP publisher ($configFile): invalid remote port - '$remotePort'." >&2
|
|
|
return 1
|
|
|
fi
|
|
|
|
|
|
if [[ $issuerDn == $crlIssuerDn ]]; then
|
|
|
if ! scp -P "$remotePort" -i "$privateKey" "$crlFile" "$remoteUser"@"$remoteHost":"$remoteLocation"; then
|
|
|
echo "SCP publisher ($configFile): failed to publish CRL for '$crlIssuerDn'." >&2
|
|
|
return 2
|
|
|
fi
|
|
|
fi
|
|
|
}
|
|
|
|
|
|
# If no arguments were given, just show usage help.
|
|
|
if [[ -z $1 ]]; then
|
|
|
usage
|
|
|
exit 0
|
|
|
fi
|
|
|
|
|
|
# Parse the arguments
|
|
|
while getopts "vh" opt; do
|
|
|
case "$opt" in
|
|
|
v) version
|
|
|
exit 0;;
|
|
|
h) usage
|
|
|
exit 0;;
|
|
|
*) usage
|
|
|
exit 1;;
|
|
|
esac
|
|
|
done
|
|
|
i=$OPTIND
|
|
|
shift $(($i-1))
|
|
|
|
|
|
# Determine the configuration directory to be used
|
|
|
configDir="/etc/crlpublisher"
|
|
|
|
|
|
[[ ! -d $configDir ]] && configDir="$HOME/.crlpublisher"
|
|
|
|
|
|
if [[ ! -d $configDir ]]; then
|
|
|
cat <<EOF >&2
|
|
|
No configuration directory could be found. Please create configuration directory
|
|
|
and the necessary configuration files in one of the following locations:
|
|
|
|
|
|
- /etc/crlpublisher/
|
|
|
- $HOME/crlpublisher/
|
|
|
EOF
|
|
|
exit 2
|
|
|
fi
|
|
|
|
|
|
# The first argument should be a CRL file
|
|
|
crlFile="$1"
|
|
|
|
|
|
# Obtain the issuer's DN first
|
|
|
readCrlInfo "$crlFile" || exit $?
|
|
|
|
|
|
# Assume that the operation suceeds unless the publisher fails for any reason.
|
|
|
operationResult=0
|
|
|
|
|
|
# Process each configuration file
|
|
|
while read configFile; do
|
|
|
unset publisher
|
|
|
eval "$(grep "^publisher=" "$configFile")"
|
|
|
# Execute operation and if it failed, that's the status the script will
|
|
|
# return.
|
|
|
"publish_through_$publisher" "$configFile" "$crlFile" || operationResult="$?"
|
|
|
done < <(find "$configDir" -name "*.conf")
|
|
|
|
|
|
exit "$operationResult"
|
|
|
|