#===================== # * (C) 2006 James Westby # * All rights reserved. # * Redistribution and use in source and binary forms, with or without # * modification, are permitted provided that the following conditions are met: # * # * * Redistributions of source code must retain the above copyright # * notice, this list of conditions and the following disclaimer. # * * Redistributions in binary form must reproduce the above copyright # * notice, this list of conditions and the following disclaimer in the # * documentation and/or other materials provided with the distribution. # * * Neither the name of the author nor the names of its contributors # * may be used to endorse or promote products derived from this # * software without specific prior written permission. # * # * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY # * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR # * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # * SERVICES; # * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #Start of ssl-cert2-lib #===== #Global vars, location of files etc. LIB_DIR="/var/lib/ssl-cert2/" CERTS_DIR="/etc/ssl/certs/" KEYS_DIR="/etc/ssl/private/" PACKAGES_DIR="${LIB_DIR}packages/" PACKAGES_LIST="${PACKAGES_DIR}list" SITEWIDE_PEM="${CERTS_DIR}ssl-cert2-sitewide.pem" SITEWIDE_PEM_LINK="${LIB_DIR}sitewide.link" SITEWIDE_KEY_PEM="${KEYS_DIR}ssl-cert2-sitewide.pem" SITEWIDE_KEY_PEM_LINK="${LIB_DIR}sitewide-key.link" SNAKEOIL_PEM="${CERTS_DIR}ssl-cert2-snakeoil.pem" SNAKEOIL_KEY_PEM="${KEYS_DIR}ssl-cert2-snakeoil.pem" HASHLINK_FILE="${LIB_DIR}hash_link" MANAGE_FILE="${LIB_DIR}manage_certs" COUNTRY_FILE="${LIB_DIR}country" STATE_FILE="${LIB_DIR}state" LOCALITY_FILE="${LIB_DIR}locality" ORGANISATION_FILE="${LIB_DIR}organisation" UNIT_FILE="${LIB_DIR}unit" CN_FILE="${LIB_DIR}cn" EMAIL_FILE="${LIB_DIR}email" REVISION="0.1" AUTHOR="James Westby " COPYRIGHT="(C) 2006 $AUTHOR" #Lib functions message() { echo "$*" >&2 } maintainer_error() { if [ -z "$1" ] || [ -z "$2" ]; then message "The maintainer made an error" else message "The maintainer made an error, $1 must be called with $2 arguments" fi exit 1 } create_certificate() { if [ ! -f "$SNAKEOIL_PEM" ]; then hostname="$(hostname)" country="$(cat "$COUNTRY_FILE")" state="$(cat "$STATE_FILE")" locality="$(cat "$LOCALITY_FILE")" org="$(cat "$ORGANISATION_FILE")" ou="$(cat "$UNIT_FILE")" cn="$(cat "$CN_FILE")" if [ -z "$cn" ]; then cn="$hostname" fi email="$(cat "$EMAIL_FILE")" if [ -z "$email" ]; then email="root@${hostname}" fi cnf="/usr/share/ssl-cert2/openssl.cnf" cd /etc/ssl/certs PATH=$PATH:/usr/bin/ssl (openssl req -new -x509 -days 365 -nodes -out "$SNAKEOIL_PEM" -keyout "$SNAKEOIL_KEY_PEM" -config $cnf > /dev/null 2>/dev/null <<+ $country $state $locality $org $ou $cn $email + ) if [ $? -gt 0 ];then message "Could not create key file correctly use should create $SNAKEOIL_PEM and $SNAKEOIL_KEY_PEM yourself" ( [ -f "$SNAKEOIL_PEM" ] && rm -f "$SNAKEOIL_PEM" ) || true ( [ -f "$SNAKEOIL_KEY_PEM" ] && rm -f "$SNAKEOIL_KEY_PEM" ) || true fi if [ -f $SNAKEOIL_KEY_PEM ] && [ -f $SNAKEOIL_PEM ]; then hash=$(openssl x509 -hash -noout -in "$SNAKEOIL_PEM") suffix=0 hash_link="${hash}.${suffix}" while ( [ -h "$hash_link" ] || [ -e "$hash_link" ] ) && [ $suffix -le 19 ]; do suffix=$(expr $suffix + 1) hash_link="${hash}.${suffix}" done if [ -h "$hash_link" ] || [ -e "$hash_link" ]; then message "Unable to create hash link. Try running c_rehash /etc/ssl/certs as root" else ln -s "$SNAKEOIL_PEM" "$hash_link" echo "$hash_link" > "$HASHLINK_FILE" fi chown root:ssl-cert "$SNAKEOIL_PEM" chmod 0644 "$SNAKEOIL_PEM" chown root:ssl-cert "$SNAKEOIL_KEY_PEM" chmod 0640 "$SNAKEOIL_KEY_PEM" fi fi } #Pass it a link and a file containing the readlink from when it was created #and t will return a value indicating whether it has been changed # 0 - indicates the link doesn't exist # 1 - indicated the link exists and has not beed modified # 2 - the link does not exist and no record of it exists # 3 - indicates the link is not a link (i.e. a regular file etc. # 4 - indivated that the readlink file doesn't exists, yet the link dies. # 5 - link exists and has been modified # 6 - something else (hopefully we never see this check_link() { if [ -z "$1" ] || [ -z "$2" ]; then maintainer_error check_link 2 fi link="$1" file="$2" if [ -e "$link" ] && [ ! -h "$link" ]; then return 3 fi if [ ! -e "$file" ] && [ -h "$link" ]; then return 4 fi if [ ! -h "$link" ]; then return 0 fi if [ ! -e "$file" ] && [ ! -h "$link" ]; then return 2 fi if [ -h "$link" ] && [ "$(readlink "$link")" = "$(cat "$file")" ]; then return 1 fi if [ -h "$link" ] && [ "$(readlink "$link")" != "$(cat "$file")" ]; then return 5 fi return 6 } #Updates a symlink ($2) to point to a target ($1), readlinks in to file ($3)m all from a dir ($4) update_symlink() { if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then maintainer_error update_symlink 4 fi target="$1" link="$2" file="$3" dir="$4" cd "$dir" ln -sf "$target" "$link" readlink "$link" > "$file" message "Linking $link to $target" } update_links() { if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] || \ [ -z "$5" ] || [ -z "$6" ]; then maintainer_error update_links 6 fi cert="$1" cert_file="$2" key="$3" key_file="$4" cert_target="$5" key_target="$6" set +e check_link "$cert" "$cert_file" if [ $? -le 2 ]; then check_link "$key" "$key_file" if [ $? -le 2 ]; then #Force update the symlinks as they don't exist, or are unchanged set -e update_symlink "$(basename "$cert_target")" "$(basename "$cert")" "$cert_file" "$CERTS_DIR" update_symlink "$(basename "$key_target")" "$(basename "$key")" "$key_file" "$KEYS_DIR" else set -e message "$key has been modified, so leaving it and $cert alone" fi else set -e message "$cert has been modified, so leaving it and $key alone" fi #Just for good measure set -e } remove_links() { if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ]; then maintainer_error remove_links 4 fi cert="$1" cert_file="$2" key="$3" key_file="$4" set +e check_link "$cert" "$cert_file" if [ $? -le 2 ]; then check_link "$key" "$key_file" if [ $? -le 2 ]; then #Force update the symlinks as they don't exist, or are unchanged set -e rm -f $cert rm -f $key message "Removing $cert and $key" else set -e message "Not deleting $key or $cert, as the former has been modified" fi else set -e message "Not deleting $cert or $key, as the former has been modified" fi #Just for good measure set -e } make_sitewide_link () { update_links "$SITEWIDE_PEM" "$SITEWIDE_PEM_LINK" "$SITEWIDE_KEY_PEM" "$SITEWIDE_KEY_PEM_LINK" "$SNAKEOIL_PEM" "$SNAKEOIL_KEY_PEM" } list_packages() { ( [ -f "$PACKAGES_LIST" ] && cat "$PACKAGES_LIST" ) || true } remove_package_links() { for package in $(list_packages); do certlink_file="${PACKAGES_DIR}${package}/cert_link" keylink_file="${PACKAGES_DIR}${package}/key_link" certlink="${CERTS_DIR}${package}.pem" keylink="${KEYS_DIR}${package}.pem" remove_links "$certlink" "$certlink_file" "$keylink" "$keylink_file" done } make_package_links() { for package in $(cat "$PACKAGES_LIST"); do certlink_file="${PACKAGE_DIR}${package}/cert_link" keylink_file="${PACKAGE_DIR}${package}/key_link" certlink="${CERTS_DIR}${package}.pem" keylink="${KEYS_DIR}${package}.pem" update_links "$certlink" "$certlink_file" "$keylink" "$keylink_file" "$SITEWIDE_PEM" "$SITEWIDE_KEY_PEM" done } #Purges the snakeoil cert and key from the system purge_snakeoil() { rm -f "$SNAKEOIL_PEM" rm -f "$SNAKEOIL_KEY_PEM" ( [ -f "$HASHLINK_FILE" ] && cd /etc/ssl/certs && rm -f $(cat "$HASHLINK_FILE") ) || true } #Removes the sitewide links if they have not been modified remove_sitewide_links() { remove_links "$SITEWIDE_PEM" "$SITEWIDE_PEM_LINK" "$SITEWIDE_KEY_PEM" "$SITEWIDE_KEY_PEM_LINK" } #Purges the links for the packages. WARNING: will cause ssl-cert2 to forget #which packages it is supposed to manage certs for. purge_package_links() { remove_package_links rm -rf ${PACKAGES_DIR}/* } #Purges the sitewide links and the knowledge about them purge_sitewide_links() { remove_sitewide_links rm -rf "$SITEWIDE_PEM_LINK" "$SITEWIDE_KEY_PEM_LINK" } #Purges all of the configuration. ssl-cert2 probably wont function very #well after this until it is reconfigured purge_config() { rm -f "$HASHLINK_FILE" rm -f "$MANAGE_FILE" rm -f "$COUNTRY_FILE" rm -f "$STATE_FILE" rm -f "$LOCALITY_FILE" rm -f "$ORGANISATION_FILE" rm -f "$UNIT_FILE" rm -f "$CN_FILE" rm -f "$EMAIL_FILE" } manage_certs() { if [ ! -f "$MANAGE_FILE" ] || [ "$(cat "$MANAGE_FILE")" = "true" ]; then echo "true" else echo "false" fi } set_manage_certs() { if [ -z "$1" ]; then message "Maintainer made an error, set_manage_certs must be called with one argument" exit 1 fi echo "$1" > "$MANAGE_FILE" } snakeoil_exists() { if [ -e "$SNAKEOIL_PEM" ] || [ -e "$SNAKEOIL_KEY_PEM" ] || [ -h "$SNAKEOIL_KEY_PEM" ] || [ -h "$SNAKEOIL_KEY_PEM" ]; then return 0 fi return 1 } get_value() { if [ -z "$1" ]; then maintainer_error get_value 1 fi if [ -f "$1" ]; then cat "$1" fi } set_value() { if [ -z "$1" ]; then maintainer_error set_value 1 fi echo "$2" > "$1" } get_country() { get_value "$COUNTRY_FILE" } set_country() { set_value "$COUNTRY_FILE" "$1" } get_state() { get_value "$STATE_FILE" } set_state() { set_value "$STATE_FILE" "$1" } get_locality() { get_value "$LOCALITY_FILE" } set_locality() { set_value "$LOCALITY_FILE" "$1" } get_organisation() { get_value "$ORGANISATIOn_FILE" } set_organisation() { set_value "$ORGANISATION_FILE" "$1" } get_unit() { get_value "$UNIT_FILE" } set_unit() { set_value "$UNIT_FILE" "$1" } get_common_name() { get_value "$CN_FILE" } set_common_name() { set_value "$CN_FILE" "$1" } get_email() { get_value "$EMAIL_FILE" } set_email() { set_value "$EMAIL_FILE" "$1" } set_package_value() { if [ -z "$1" ] || [ -z "$2" ]; then maintainer_error set_package_value 2 fi file="${PACKAGES_DIR}${1}/${2}" set_value $file $3 } set_package_cert_file() { set_package_value $1 "cert_file" $2 } set_package_key_file() { set_package_value $1 "key_file" $2 } set_package_key_owner() { set_package_value $1 "key_owner" $2 } set_package_key_group() { set_package_value $1 "key_group" $2 } set_package_key_perms() { set_package_value $1 "key_perms" $2 } #Adds a package to the list of packages that ssl-cert2 is to control #Doesn't create any links. add_package() { if [ -z "$1" ]; then maintainer_error add_package 1 fi mkdir -p "$PACKAGES_DIR$package" ( [ -f $PACKAGES_LIST ] && ( grep -q "^$package\$" $PACKAGES_LIST || echo $package > $PACKAGES_LIST ) ) || true } # Purge all of the information ssl-cert2 has about a package # also remove the record that the package needs a cert purge_package() { if [ -z $1 ]; then maintainer_error purge_package 1 fi rm -rf "$PACKAGES_DIR$package" ( [ -f $PACKAGES_LIST ] && sed -i -e "/^$package\$/d" "$PACKAGES_LIST" ) || true } #End of ssl-cert2-lib #================= # vim: set ft=sh : # ~