You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
5.2 KiB
151 lines
5.2 KiB
#!/bin/bash |
|
# |
|
# kmodgenca - Helper script to create CA/Keypair to sign modules. |
|
# Copyright (c) 2017 Stanislas Leduc <stanislas.leduc@balinor.net> |
|
# Copyright (c) 2018-2019 Nicolas Viéville <nicolas.vieville@uphf.fr> |
|
# |
|
# Permission is hereby granted, free of charge, to any person obtaining |
|
# a copy of this software and associated documentation files (the |
|
# "Software"), to deal in the Software without restriction, including |
|
# without limitation the rights to use, copy, modify, merge, publish, |
|
# distribute, sublicense, and/or sell copies of the Software, and to |
|
# permit persons to whom the Software is furnished to do so, subject to |
|
# the following conditions: |
|
# |
|
# The above copyright notice and this permission notice shall be |
|
# included in all copies or substantial portions of the Software. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
# |
|
MYPROG="kmodgenca" |
|
MYVER="0.5.7" |
|
FORCE_BUILD=0 |
|
AUTOMATIC_BUILD=0 |
|
AUTOMATIC_BUILD_OPTION="" |
|
|
|
myprog_help () |
|
{ |
|
echo "Build CA/Keypair to sign modules" |
|
echo $'\n'"Usage: ${MYPROG} [OPTIONS]" |
|
echo $'\n'"Options:" |
|
echo " -a, --auto -- generate default values for cacert.config file without prompt" |
|
echo " -f, --force -- build CA/Keypair even if there is already ones" |
|
echo " -h, --help -- print usage" |
|
echo " -V, --version -- show version" |
|
} |
|
|
|
|
|
# Parse command line options. |
|
# |
|
while [ "${1}" ] ; do |
|
case "${1}" in |
|
-a|--auto) |
|
AUTOMATIC_BUILD=1 |
|
shift |
|
;; |
|
-f|--force) |
|
FORCE_BUILD=1 |
|
shift |
|
;; |
|
-h|--help) |
|
myprog_help |
|
exit 0 |
|
;; |
|
-V|--version) |
|
echo "${MYPROG} ${MYVER}" |
|
exit 0 |
|
;; |
|
*) |
|
echo "Error: Unknown option '${1}'." >&2 |
|
myprog_help >&2 |
|
exit 2 |
|
;; |
|
esac |
|
done |
|
|
|
# Exit early if cert and private key already exist and if FORCE_BUILD |
|
# is not equal to 1. |
|
# |
|
if $(readlink -e /etc/pki/akmods/certs/public_key.der &>/dev/null) && \ |
|
$(readlink -e /etc/pki/akmods/private/private_key.priv &>/dev/null) && \ |
|
[ ${FORCE_BUILD} -eq 0 ] ; then |
|
exit 0 |
|
fi |
|
|
|
CACERT_CONFIG="/etc/pki/akmods/cacert.config" |
|
KEYNAME="$(hostname)"-"$(od -vAn -N4 -tu4 < /dev/urandom | awk '{print $1}')" |
|
|
|
# Create cacert.config file with local values if AUTOMATIC_BUILD is set |
|
# or ask for values manually. |
|
# |
|
echo "Update cacert.config..." |
|
if [ ${AUTOMATIC_BUILD} -eq 1 ] ; then |
|
# Set OpenSSL fields values, comment default values and min/max ones. |
|
sed -e "s#\(0.organizationName *= \).*#\1$(hostname)#" \ |
|
-e "s#\(organizationalUnitName *= \).*#\1$(hostname)#" \ |
|
-e "s#\(emailAddress *= \).*#\1akmods@$(hostname)#" \ |
|
-e "s#\(localityName *= \).*#\1None#" \ |
|
-e "s#\(stateOrProvinceName *= \).*#\1None#" \ |
|
-e "s#\(countryName *= \).*#\1$(locale country_ab2)#" \ |
|
-e "s#\(commonName *= \).*#\1$(hostname)"-"$(od -vAn -N4 -tu4 < /dev/urandom | awk '{print $1}')#" \ |
|
-e "s/^[^#]*_default *= /#&/" \ |
|
-e "s/^[^#]*_min/#&/" \ |
|
-e "s/^[^#]*_max/#&/" ${CACERT_CONFIG}.in > ${CACERT_CONFIG} |
|
AUTOMATIC_BUILD_OPTION=" -batch" |
|
else |
|
# Activate prompt directive. |
|
sed -e "s#\(prompt *= \).*#\1yes#" ${CACERT_CONFIG}.in > ${CACERT_CONFIG} |
|
fi |
|
KEY_SUFF="$(date "+%F_%T_%N")" |
|
# If cert and private key files names already exists, do not overwrite |
|
# them but save them. |
|
# |
|
if [[ -e /etc/pki/akmods/certs/${KEYNAME}.der ]] ; then |
|
# If the cert has already been loaded in MOK, add "already_enrolled" |
|
# to the suffix of the backup file. |
|
# `mokutil --help` fails if EFI variables are not supported on the |
|
# system. It is therefore impossible to test the presence of the key |
|
# in MOK, and then do not add special suffix to the backup file. |
|
# |
|
if $(which mokutil &> /dev/null) && $(mokutil --help &> /dev/null) && $(mokutil --test-key /etc/pki/akmods/certs/${KEYNAME}.der &> /dev/null) ; then |
|
KEY_SUFF="${KEY_SUFF}_already_enrolled" |
|
fi |
|
mv /etc/pki/akmods/certs/${KEYNAME}.der /etc/pki/akmods/certs/${KEYNAME}.der.${KEY_SUFF}.bak |
|
if [[ -e /etc/pki/akmods/private/${KEYNAME}.priv ]] ; then |
|
mv /etc/pki/akmods/private/${KEYNAME}.priv /etc/pki/akmods/private/${KEYNAME}.priv.${KEY_SUFF}.bak |
|
fi |
|
fi |
|
|
|
echo "Generate new keypair..." |
|
sg akmods -c " |
|
umask 037 |
|
openssl req -x509 -new -nodes -utf8 -sha256 -days 3650${AUTOMATIC_BUILD_OPTION} \ |
|
-config ${CACERT_CONFIG} -outform DER \ |
|
-out /etc/pki/akmods/certs/${KEYNAME}.der \ |
|
-keyout /etc/pki/akmods/private/${KEYNAME}.priv |
|
" |
|
|
|
# Ensure that akmods group can read keys. |
|
# |
|
chmod g+r /etc/pki/akmods/certs/${KEYNAME}.* |
|
chmod g+r /etc/pki/akmods/private/${KEYNAME}.* |
|
|
|
# Sanitize permissions. |
|
# |
|
if [[ -x /usr/sbin/restorecon ]] ; then |
|
/usr/sbin/restorecon /etc/pki/akmods/certs/${KEYNAME}.der |
|
/usr/sbin/restorecon /etc/pki/akmods/private/${KEYNAME}.priv |
|
fi |
|
|
|
# Update symlink to use new keypair. |
|
# |
|
ln -nsf /etc/pki/akmods/certs/${KEYNAME}.der /etc/pki/akmods/certs/public_key.der |
|
ln -nsf /etc/pki/akmods/private/${KEYNAME}.priv /etc/pki/akmods/private/private_key.priv |
|
|
|
exit 0
|
|
|