accept a password file

This commit is contained in:
Jérémy Lecour 2020-05-04 14:21:58 +02:00 committed by Jérémy Lecour
parent f4e53c374a
commit 921cba15b6

128
shellpki
View file

@ -154,35 +154,79 @@ ask_ca_password() {
} }
create() { create() {
from_csr=1 from_csr=0
with_pass=1 ask_user_pass=0
# Parse options
# based on https://gist.github.com/deshion/10d3cb5f88a21671e17a
while :; do while :; do
case "${1}" in case $1 in
-f|--file) -f|--file|--csr-file)
shift # csr-file option, with value separated by space
[ ! -f "${1}" ] && error "${1} must be a file" if [ -n "$2" ]; then
from_csr=0 from_csr=1
csr_file=$(readlink -f "${1}") csr_file=$(readlink -f -- "${2}")
shift;; shift
else
printf 'ERROR: "--csr-file" requires a non-empty option argument.\n' >&2
exit 1
fi
;;
--file=?*|--csr-file=?*)
from_csr=1
# csr-file option, with value separated by =
csr_file=$(readlink -f -- "${1#*=}")
;;
--file=|--csr-file=)
# csr-file options, without value
printf 'ERROR: "--csr-file" requires a non-empty option argument.\n' >&2
exit 1
;;
-p|--password) -p|--password)
with_pass=0 ask_pass=1
shift;; ;;
--password-file)
# password-file option, with value separated by space
if [ -n "$2" ]; then
password_file=$(readlink -f -- "${2}")
shift
else
printf 'ERROR: "--password-file" requires a non-empty option argument.\n' >&2
exit 1
fi
;;
--password-file=?*)
# password-file option, with value separated by =
password_file=$(readlink -f -- "${1#*=}")
;;
--password-file=)
# password-file options, without value
printf 'ERROR: "--password-file" requires a non-empty option argument.\n' >&2
exit 1
;;
--) --)
# End of all options.
shift shift
break;; break
;;
-?*) -?*)
warning "unknow option ${1} (ignored)" # ignore unknown options
shift;; printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
;;
*) *)
break;; # Default case: If no more options then break out of the loop.
break
;;
esac esac
shift
done done
cn="${1:-}" cn="${1:-}"
if [ "${from_csr}" -eq 0 ]; then if [ "${from_csr}" -eq 1 ]; then
[ "${with_pass}" -eq 0 ] && warning "Warning: -p made nothing with -f" [ "${ask_pass}" -eq 1 ] && warning "Warning: -p|--password is ignored with -f|--file|--crt-file"
[ -n "${password_file}" ] && warning "Warning: --password-file is ignored with -f|--file|--crt-file"
# ask for CA passphrase # ask for CA passphrase
ask_ca_password 0 ask_ca_password 0
@ -192,7 +236,7 @@ create() {
-noout -subject \ -noout -subject \
-in "${csr_file}" \ -in "${csr_file}" \
>/dev/null 2>&1 \ >/dev/null 2>&1 \
|| error "${csr_file} is not a valid CSR !" || error "${csr_file} is not a valid CSR !"
# check if csr_file contain a CN # check if csr_file contain a CN
"${OPENSSL}" req \ "${OPENSSL}" req \
@ -200,7 +244,7 @@ create() {
-in "${csr_file}" \ -in "${csr_file}" \
| grep -Eo "CN\s*=[^,/]*" \ | grep -Eo "CN\s*=[^,/]*" \
>/dev/null 2>&1 \ >/dev/null 2>&1 \
|| error "${csr_file} don't contain a CommonName !" || error "${csr_file} don't contain a CommonName !"
# get CN from CSR # get CN from CSR
cn=$("${OPENSSL}" req -noout -subject -in "${csr_file}"|grep -Eo "CN\s*=[^,/]*"|cut -d'=' -f2|xargs) cn=$("${OPENSSL}" req -noout -subject -in "${csr_file}"|grep -Eo "CN\s*=[^,/]*"|cut -d'=' -f2|xargs)
@ -225,18 +269,25 @@ create() {
# ask for CA passphrase # ask for CA passphrase
ask_ca_password 0 ask_ca_password 0
# ask for client key passphrase if [ -n "${password_file}" ] && [ -r "${password_file}" ]; then
if [ "${with_pass}" -eq 0 ]; then PASSWORD=$(head -n 1 "${password_file}" | tr -d '\n')
if [ -z "${PASSWORD}" ]; then
warning "Warning: empty password from file \`${password_file}'"
fi
elif [ "${ask_pass}" -eq 1 ]; then
trap 'unset PASSWORD' 0 trap 'unset PASSWORD' 0
stty -echo stty -echo
printf "Password for user key : " printf "Password for user key : "
read -r PASSWORD read -r PASSWORD
stty echo stty echo
printf "\n" printf "\n"
if [ -z "${PASSWORD}" ]; then
warning "Warning: empty password from input"
fi
fi fi
# generate private key # generate private key
if [ "${with_pass}" -eq 0 ]; then if [ -n "${PASSWORD}" ]; then
PASSWORD="${PASSWORD}" "$OPENSSL" genrsa \ PASSWORD="${PASSWORD}" "$OPENSSL" genrsa \
-aes256 -passout env:PASSWORD \ -aes256 -passout env:PASSWORD \
-out "${KEYDIR}/${cn}-${TIMESTAMP}.key" \ -out "${KEYDIR}/${cn}-${TIMESTAMP}.key" \
@ -247,7 +298,7 @@ create() {
2048 >/dev/null 2>&1 2048 >/dev/null 2>&1
fi fi
if [ "${with_pass}" -eq 0 ]; then if [ -n "${PASSWORD}" ]; then
# generate csr req # generate csr req
PASSWORD="${PASSWORD}" "$OPENSSL" req \ PASSWORD="${PASSWORD}" "$OPENSSL" req \
-batch -new \ -batch -new \
@ -280,9 +331,9 @@ EOF
# check if CRT is a valid # check if CRT is a valid
"${OPENSSL}" x509 \ "${OPENSSL}" x509 \
-noout -subject \ -noout -subject \
-in "${CRTDIR}/${cn}.crt" \ -in "${CRTDIR}/${cn}.crt" \
>/dev/null 2>&1 \ >/dev/null 2>&1 \
|| rm -f "${CRTDIR}/${cn}.crt" || rm -f "${CRTDIR}/${cn}.crt"
[ -f "${CRTDIR}/${cn}.crt" ] || error "Error in CSR creation" [ -f "${CRTDIR}/${cn}.crt" ] || error "Error in CSR creation"
@ -291,10 +342,23 @@ EOF
echo "The CRT file is available in ${CRTDIR}/${cn}.crt" echo "The CRT file is available in ${CRTDIR}/${cn}.crt"
# generate pkcs12 format # generate pkcs12 format
if [ "${with_pass}" -eq 0 ]; then if [ -n "${PASSWORD}" ]; then
PASSWORD="${PASSWORD}" "${OPENSSL}" pkcs12 -export -nodes -passin env:PASSWORD -passout env:PASSWORD -inkey "${KEYDIR}/${cn}-${TIMESTAMP}.key" -in "${CRTDIR}/${cn}.crt" -out "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12" PASSWORD="${PASSWORD}" "${OPENSSL}" pkcs12 \
-export \
-nodes \
-passin env:PASSWORD \
-passout env:PASSWORD \
-inkey "${KEYDIR}/${cn}-${TIMESTAMP}.key" \
-in "${CRTDIR}/${cn}.crt" \
-out "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12"
else else
"${OPENSSL}" pkcs12 -export -nodes -passout pass: -inkey "${KEYDIR}/${cn}-${TIMESTAMP}.key" -in "${CRTDIR}/${cn}.crt" -out "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12" "${OPENSSL}" pkcs12 \
-export \
-nodes \
-passout pass: \
-inkey "${KEYDIR}/${cn}-${TIMESTAMP}.key" \
-in "${CRTDIR}/${cn}.crt" \
-out "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12"
fi fi
chmod 640 "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12" chmod 640 "${PKCS12DIR}/${cn}-${TIMESTAMP}.p12"
@ -414,8 +478,12 @@ main() {
# default config # default config
# TODO : override with /etc/default/shellpki # TODO : override with /etc/default/shellpki
CONFFILE="/etc/shellpki/openssl.cnf" CONFFILE="/etc/shellpki/openssl.cnf"
PKIUSER="shellpki"
[ "$(uname)" = "OpenBSD" ] && PKIUSER="_shellpki" if [ "$(uname)" = "OpenBSD" ]; then
PKIUSER="_shellpki"
else
PKIUSER="shellpki"
fi
[ "${USER}" != "root" ] || [ "${USER}" != "${PKIUSER}" ] || error "Please become root before running ${0} !" [ "${USER}" != "root" ] || [ "${USER}" != "${PKIUSER}" ] || error "Please become root before running ${0} !"