Skip to content

Instantly share code, notes, and snippets.

@3v1n0
Last active September 7, 2023 17:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 3v1n0/287d02ca8e03936f1c7bba992173d47a to your computer and use it in GitHub Desktop.
Save 3v1n0/287d02ca8e03936f1c7bba992173d47a to your computer and use it in GitHub Desktop.
Some crazy automated tests to get Smartcard authentication with SSSD, simiulating various setups via software via softhsm2 and a test tool to verify usage with GDM
#!/usr/bin/env bash
# Copyright 2023 - Marco Trevisan
# Released under the GPLv3 terms
#
# A simple tool to simulate PAM authentication using GDM smartcard settings.
#
# This can also be used in interactive mode to test GDM login from the UI, by
# setting the environment variable `WAIT`, so that the script will restart the
# gdm service and will allow the user to login it using its name and a provided
# `PIN` (123456 by default).
#
# To be used with https://gist.github.com/3v1n0/287d02ca8e03936f1c7bba992173d47a
set -xe
required_tools=(
gdm3 # debian package: gdm3
pamtester # debian package: pamtester
softhsm2-util # debian package: softhsm2
sssd # debian package: sssd
)
if [[ ! -v OFFLINE_MODE ]]; then
required_tools+=(
wget # debian package: wget
)
fi
if [ "$(id -u)" != 0 ] || [ -z "$SUDO_USER" ]; then
echo "This tool requires sudo!"
exit 2
fi
for cmd in "${required_tools[@]}"; do
if ! command -v "$cmd" > /dev/null; then
echo "Tool $cmd missing"
exit 1
fi
done
PIN=${PIN:-123456}
GDM_USER=${GDM_USER:-gdm}
tmpdir=${TEST_TMPDIR:-$(mktemp -d -t "sssd-softhsm2-gdm-certs-XXXXXX")}
backupsdir=
alternative_pam_configs=(
/etc/pam.d/gdm-smartcard-sssd-exclusive
/etc/pam.d/gdm-smartcard-sssd-or-password
)
declare -a restore_paths
declare -a delete_paths
function restore_changes() {
for path in "${restore_paths[@]}"; do
local original_path
original_path="/$(realpath --strip --relative-base="$backupsdir" "$path")"
rm "$original_path" && mv "$path" "$original_path" || true
done
for path in "${delete_paths[@]}"; do
rm -f "$path"
#find "$(dirname "$path")" -empty -delete || true
done
update-alternatives --auto gdm-smartcard
if [ -e /etc/sssd/sssd.conf ]; then
chmod 600 /etc/sssd/sssd.conf || return 1
systemctl restart sssd || true
else
systemctl stop sssd || true
fi
if [ -e /etc/softhsm/softhsm2.conf ]; then
chmod 600 /etc/softhsm/softhsm2.conf || return 1
fi
rm -rf "$tmpdir"
}
function backup_file() {
if [ -z "$backupsdir" ]; then
backupsdir=$(mktemp -d -t "sssd-softhsm2-gdm-backups-XXXXXX")
fi
if [ -e "$1" ]; then
local back_dir="$backupsdir/$(dirname "$1")"
local back_path="$back_dir/$(basename "$1")"
[ ! -e "$back_path" ] || return 1
mkdir -p "$back_dir" || return 1
cp -a "$1" "$back_path" || return 1
restore_paths+=("$back_path")
else
delete_paths+=("$1")
fi
}
function handle_exit() {
exit_code=$?
restore_changes || return 1
if [ $exit_code = 0 ]; then
rm -rf "$backupsdir"
set +x
echo "Script completed successfully!"
else
set +x
echo "Script failed, check the log!"
echo " Backup preserved at $backupsdir"
echo " PAM Log: /var/log/auth.log"
echo " SSSD PAM Log: /var/log/sssd/sssd_pam.log"
echo " SSSD p11_child Log: /var/log/sssd/p11_child.log"
fi
}
trap 'handle_exit' EXIT
tester="$(dirname "$0")"/sssd-softhism2-certificates-tests.sh
if [ ! -e "$tester" ] && [[ ! -v OFFLINE_MODE ]]; then
echo "Required $tester missing, we're downloading it..."
tester="$tmpdir/sssd-softhism2-certificates-tests.sh"
wget -q -c https://gist.github.com/3v1n0/287d02ca8e03936f1c7bba992173d47a/raw/sssd-softhism2-certificates-tests.sh \
-O "$tester"
[ -e "$tester" ] || exit 1
elif [ ! -e "$tester" ] && [[ -v OFFLINE_MODE ]]; then
echo "Required $tester missing"
exit 1
fi
export PIN TEST_TMPDIR="$tmpdir" GENERATE_SMART_CARDS=1 KEEP_TEMPORARY_FILES=1 NO_SSSD_TESTS=1
bash "$tester"
find "$tmpdir" -type d -exec chmod 777 {} \;
find "$tmpdir" -type f -exec chmod 666 {} \;
backup_file /etc/sssd/sssd.conf
rm -f /etc/sssd/sssd.conf
user_home="$(runuser -u "$SUDO_USER" -- sh -c 'echo ~')"
mkdir -p "$user_home"
chown "$SUDO_USER:$SUDO_USER" "$user_home"
gdm_home="$(runuser -u "$GDM_USER" -- sh -c 'echo ~')"
mkdir -p "$gdm_home"
chown "$GDM_USER:$GDM_USER" "$gdm_home"
user_config="$(runuser -u "$SUDO_USER" -- sh -c 'echo ${XDG_CONFIG_HOME:-~/.config}')"
gdm_config="$(runuser -u "$GDM_USER" -- sh -c 'echo ${XDG_CONFIG_HOME:-~/.config}')"
system_config="/etc"
softhsm2_conf_paths=(
"$SUDO_USER:$user_config/softhsm2/softhsm2.conf"
"$GDM_USER:$gdm_config/softhsm2/softhsm2.conf"
"root:$system_config/softhsm/softhsm2.conf"
)
for path_pair in "${softhsm2_conf_paths[@]}"; do
IFS=":" read -r -a path <<< "${path_pair}"
path="${path[1]}"
backup_file "$path"
rm -f "$path"
done
function test_authentication() {
certificate_config="$1"
ca_db="$2"
verification_options="$3"
mkdir -p -m 700 /etc/sssd
echo "Using CA DB '$ca_db' with verification options: '$verification_options'"
cat <<EOF > /etc/sssd/sssd.conf || return 2
[sssd]
enable_files_domain = True
services = pam
#certificate_verification = $verification_options
[certmap/implicit_files/$SUDO_USER]
matchrule = <SUBJECT>.*Test Organization.*
[pam]
pam_cert_db_path = $ca_db
pam_cert_verification = $verification_options
pam_cert_auth = True
pam_verbosity = 10
debug_level = 10
EOF
chmod 600 /etc/sssd/sssd.conf || return 2
for path_pair in "${softhsm2_conf_paths[@]}"; do
IFS=":" read -r -a path <<< "${path_pair}"
user="${path[0]}"
path="${path[1]}"
runuser -u "$user" -- mkdir -p "$(dirname "$path")" || return 2
runuser -u "$user" -- ln -sf "$certificate_config" "$path" || return 2
runuser -u "$user" -- softhsm2-util --show-slots | grep "Test Organization" \
|| return 2
done
systemctl restart sssd || return 2
for alternative in "${alternative_pam_configs[@]}"; do
update-alternatives --set gdm-smartcard "$alternative" || return 2
echo -n -e "$PIN" | runuser -u "$SUDO_USER" -- \
pamtester -v gdm-smartcard "$SUDO_USER" authenticate || return 2
echo -n -e "$PIN" | runuser -u "$SUDO_USER" -- \
pamtester -v gdm-smartcard "" authenticate || return 2
if echo -n -e "wrong${PIN}" | runuser -u "$SUDO_USER" -- \
pamtester -v gdm-smartcard "$SUDO_USER" authenticate; then
echo "Unexpected pass!"
return 2
fi
if echo -n -e "wrong${PIN}" | runuser -u "$SUDO_USER" -- \
pamtester -v gdm-smartcard "" authenticate; then
echo "Unexpected pass!"
return 2
fi
if echo -n -e "$PIN" | pamtester -v gdm-smartcard root authenticate; then
echo "Unexpected pass!"
return 2
fi
if [[ -v WAIT ]]; then
echo "Press any key and enter to continue"
systemctl restart gdm3
read
fi
done
}
test_authentication \
"$tmpdir/softhsm2-test-root-CA-trusted-certificate-0001.conf" \
"$tmpdir/test-full-chain-CA.pem"
test_authentication \
"$tmpdir/softhsm2-test-sub-intermediate-CA-trusted-certificate-0001.conf" \
"$tmpdir/test-full-chain-CA.pem"
test_authentication \
"$tmpdir/softhsm2-test-sub-intermediate-CA-trusted-certificate-0001.conf" \
"$tmpdir/test-sub-intermediate-CA.pem" \
"partial_chain"
#!/usr/bin/env bash
# Copyright 2023 - Marco Trevisan
# Released under the GPLv3 terms
#
# A simple tool to generate CA certificates signed by both a root cert authority
# and by an intermediate one, to verify smartcard usage using softhism2.
# Used to verify p11_child usage in SSSD.
set -xe
required_tools=(
p11tool # debian package: gnutls-bin
openssl # debian package: openssl
softhsm2-util # debian package: softhsm2
)
for cmd in "${required_tools[@]}"; do
if ! command -v "$cmd" > /dev/null; then
echo "Tool $cmd missing"
exit 1
fi
done
PIN=${PIN:-053350}
SOFTHSM2_MODULE=${SOFTHSM2_MODULE:-$(realpath "$(find /usr/lib/*softhsm/libsofthsm2.so | head -n 1)")}
SSSD_P11_CHILD=${SSSD_P11_CHILD:-/usr/libexec/sssd/p11_child}
TOKEN_ID=${TOKEN_ID:-00112233445566778899FFAABBCCDDEEFF012345}
if [ ! -v NO_SSSD_TESTS ]; then
if [ ! -x "$SSSD_P11_CHILD" ]; then
if [ ! -e "$SSSD_P11_CHILD" ]; then
echo "Cannot find $SSSD_P11_CHILD"
else
echo "Cannot execute $SSSD_P11_CHILD, try using sudo..."
fi
exit 1
else
ca_db_arg="ca_db"
p11_child_help=$("$SSSD_P11_CHILD" --help &>/dev/stdout)
if echo "$p11_child_help" | grep nssdb -qs; then
ca_db_arg=nssdb
fi
echo "$p11_child_help" | grep -qs -- "--${ca_db_arg}"
fi
fi
if [ ! -e "$SOFTHSM2_MODULE" ]; then
echo "Cannot find softhsm2-module at $SOFTHSM2_MODULE"
exit 1
fi
tmpdir=${TEST_TMPDIR:-$(mktemp -d -t "sssd-softhsm2-XXXXXX")}
keys_size=1024
if [[ ! -v KEEP_TEMPORARY_FILES ]]; then
trap 'rm -rf "$tmpdir"' EXIT
fi
trap 'set +x; echo -e "\nUnexpected failure!!!"' ERR
echo -n 01 > "$tmpdir/serial"
touch "$tmpdir/index.txt"
mkdir -p "$tmpdir/new_certs"
function expect_fail() {
local cmd="$1"
shift
if "$cmd" "$@"; then
echo "Unexpected failure!"
exit 1
fi
}
## Root CA certificate generation
cat <<EOF > "$tmpdir/test-root-CA.config"
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = $tmpdir
database = \$dir/index.txt
new_certs_dir = \$dir/new_certs
certificate = \$dir/test-root-CA.pem
serial = \$dir/serial
private_key = \$dir/test-root-CA-key.pem
RANDFILE = \$dir/rand
default_days = 365
default_crl_days = 30
default_md = sha256
policy = policy_any
email_in_dn = no
name_opt = ca_default
cert_opt = ca_default
copy_extensions = copy
[ usr_cert ]
authorityKeyIdentifier = keyid, issuer
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ policy_any ]
organizationName = supplied
organizationalUnitName = supplied
commonName = supplied
emailAddress = optional
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Root CA
EOF
root_ca_key_pass="pass:random-root-CA-password-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-root-CA-key.pem" \
-passout "$root_ca_key_pass" \
"$keys_size"
openssl req -passin "$root_ca_key_pass" \
-batch -config "$tmpdir/test-root-CA.config" -x509 -new -nodes \
-key "$tmpdir/test-root-CA-key.pem" -sha256 -days 1024 -set_serial 0 \
-extensions v3_ca -out "$tmpdir/test-root-CA.pem"
openssl x509 -noout -in "$tmpdir/test-root-CA.pem"
## Intermediate CA certificate generation
cat <<EOF > "$tmpdir/test-intermediate-CA.config"
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = $tmpdir
database = \$dir/index.txt
new_certs_dir = \$dir/new_certs
certificate = \$dir/test-intermediate-CA.pem
serial = \$dir/serial
private_key = \$dir/test-intermediate-CA-key.pem
RANDFILE = \$dir/rand
default_days = 365
default_crl_days = 30
default_md = sha256
policy = policy_any
email_in_dn = no
name_opt = ca_default
cert_opt = ca_default
copy_extensions = copy
[ usr_cert ]
authorityKeyIdentifier = keyid, issuer
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ policy_any ]
organizationName = supplied
organizationalUnitName = supplied
commonName = supplied
emailAddress = optional
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Intermediate CA
EOF
intermediate_ca_key_pass="pass:random-intermediate-CA-password-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-intermediate-CA-key.pem" \
-passout "$intermediate_ca_key_pass" \
"$keys_size"
openssl req \
-batch -new -nodes \
-passin "$intermediate_ca_key_pass" \
-config "$tmpdir/test-intermediate-CA.config" \
-key "$tmpdir/test-intermediate-CA-key.pem" \
-passout "$root_ca_key_pass" \
-sha256 \
-extensions v3_ca \
-out "$tmpdir/test-intermediate-CA-certificate-request.pem"
openssl req -text -noout -in "$tmpdir/test-intermediate-CA-certificate-request.pem"
openssl ca \
-batch -notext \
-config "$tmpdir/test-root-CA.config" \
-passin "$root_ca_key_pass"\
-keyfile "$tmpdir/test-root-CA-key.pem" \
-in "$tmpdir/test-intermediate-CA-certificate-request.pem" \
-days 365 -extensions v3_intermediate_ca -out "$tmpdir/test-intermediate-CA.pem"
openssl x509 -noout -in "$tmpdir/test-intermediate-CA.pem"
openssl verify -CAfile "$tmpdir/test-root-CA.pem" "$tmpdir/test-intermediate-CA.pem"
## Sub-Intermediate CA certificate generation
cat <<EOF > "$tmpdir/test-sub-intermediate-CA.config"
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = $tmpdir
database = \$dir/index.txt
new_certs_dir = \$dir/new_certs
certificate = \$dir/test-sub-intermediate-CA.pem
serial = \$dir/serial
private_key = \$dir/test-sub-intermediate-CA-key.pem
RANDFILE = \$dir/rand
default_days = 365
default_crl_days = 30
default_md = sha256
policy = policy_any
email_in_dn = no
name_opt = ca_default
cert_opt = ca_default
copy_extensions = copy
[ usr_cert ]
authorityKeyIdentifier = keyid, issuer
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
basicConstraints = CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ policy_any ]
organizationName = supplied
organizationalUnitName = supplied
commonName = supplied
emailAddress = optional
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Sub Intermediate CA
EOF
sub_intermediate_ca_key_pass="pass:random-sub-intermediate-CA-password-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-sub-intermediate-CA-key.pem" \
-passout "$sub_intermediate_ca_key_pass" \
"$keys_size"
openssl req \
-batch -new -nodes \
-passin "$sub_intermediate_ca_key_pass" \
-config "$tmpdir/test-sub-intermediate-CA.config" \
-key "$tmpdir/test-sub-intermediate-CA-key.pem" \
-passout "$intermediate_ca_key_pass" \
-sha256 \
-extensions v3_ca \
-out "$tmpdir/test-sub-intermediate-CA-certificate-request.pem"
openssl req -text -noout -in "$tmpdir/test-sub-intermediate-CA-certificate-request.pem"
openssl ca \
-batch -notext \
-config "$tmpdir/test-intermediate-CA.config" \
-passin "$intermediate_ca_key_pass"\
-keyfile "$tmpdir/test-intermediate-CA-key.pem" \
-in "$tmpdir/test-sub-intermediate-CA-certificate-request.pem" \
-days 365 -extensions v3_intermediate_ca -out "$tmpdir/test-sub-intermediate-CA.pem"
openssl x509 -noout -in "$tmpdir/test-sub-intermediate-CA.pem"
openssl verify \
-partial_chain \
-CAfile "$tmpdir/test-intermediate-CA.pem" "$tmpdir/test-sub-intermediate-CA.pem"
expect_fail\
openssl verify \
-CAfile "$tmpdir/test-root-CA.pem" "$tmpdir/test-sub-intermediate-CA.pem"
## Root CA Trusted Certificate generation
cat <<"EOF" > "$tmpdir/test-root-CA-trusted-certificate-0001.config"
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Root Trusted Certificate 0001
[ req_exts ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "Test Organization Root CA trusted Certificate"
subjectKeyIdentifier = hash
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
subjectAltName = email:mail@3v1n0.net,URI:https://github.com/3v1n0/
EOF
root_ca_trusted_cert_0001_key_pass="pass:random-root-ca-trusted-cert-0001-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-root-CA-trusted-certificate-0001-key.pem" \
-passout "$root_ca_trusted_cert_0001_key_pass" \
"$keys_size"
openssl req \
-new -nodes \
-reqexts req_exts \
-passin "$root_ca_trusted_cert_0001_key_pass" \
-key "$tmpdir/test-root-CA-trusted-certificate-0001-key.pem" \
-config "$tmpdir/test-root-CA-trusted-certificate-0001.config" \
-out "$tmpdir/test-root-CA-trusted-certificate-0001-request.pem"
openssl req -text -noout \
-in "$tmpdir/test-root-CA-trusted-certificate-0001-request.pem"
openssl ca \
-batch -notext \
-config "$tmpdir/test-root-CA.config" \
-passin "$root_ca_key_pass" \
-keyfile "$tmpdir/test-root-CA-key.pem" \
-in "$tmpdir/test-root-CA-trusted-certificate-0001-request.pem" \
-days 365 -extensions usr_cert \
-out "$tmpdir/test-root-CA-trusted-certificate-0001.pem"
openssl x509 -noout \
-in "$tmpdir/test-root-CA-trusted-certificate-0001.pem"
openssl verify -CAfile \
"$tmpdir/test-root-CA.pem" \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem"
expect_fail \
openssl verify -CAfile \
"$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem"
## Intermediate CA Trusted Certificate generation
cat <<"EOF" > "$tmpdir/test-intermediate-CA-trusted-certificate-0001.config"
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Intermediate Trusted Certificate 0001
[ req_exts ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "Test Organization Intermediate CA trusted Certificate"
subjectKeyIdentifier = hash
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
subjectAltName = email:mail@3v1n0.net,URI:https://github.com/3v1n0/
EOF
intermediate_ca_trusted_cert_0001_key_pass="pass:random-intermediate-ca-trusted-cert-0001-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-intermediate-CA-trusted-certificate-0001-key.pem" \
-passout "$intermediate_ca_trusted_cert_0001_key_pass" \
"$keys_size"
openssl req \
-new -nodes \
-reqexts req_exts \
-passin "$intermediate_ca_trusted_cert_0001_key_pass" \
-key "$tmpdir/test-intermediate-CA-trusted-certificate-0001-key.pem" \
-config "$tmpdir/test-intermediate-CA-trusted-certificate-0001.config" \
-out "$tmpdir/test-intermediate-CA-trusted-certificate-0001-request.pem"
openssl req -text -noout \
-in "$tmpdir/test-intermediate-CA-trusted-certificate-0001-request.pem"
openssl ca \
-passin "$intermediate_ca_key_pass" \
-config "$tmpdir/test-intermediate-CA.config" -batch -notext \
-keyfile "$tmpdir/test-intermediate-CA-key.pem" \
-in "$tmpdir/test-intermediate-CA-trusted-certificate-0001-request.pem" \
-days 365 -extensions usr_cert \
-out "$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem"
openssl x509 -noout \
-in "$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem"
echo "This certificate should not be trusted fully"
expect_fail \
openssl verify \
-CAfile "$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem"
openssl verify -partial_chain \
-CAfile "$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem"
## Sub Intermediate CA Trusted Certificate generation
cat <<"EOF" > "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.config"
[ req ]
distinguished_name = req_distinguished_name
prompt = no
[ req_distinguished_name ]
O = Test Organization
OU = Test Organization Unit
CN = Test Organization Sub Intermediate Trusted Certificate 0001
[ req_exts ]
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "Test Organization Sub Intermediate CA trusted Certificate"
subjectKeyIdentifier = hash
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
subjectAltName = email:mail@3v1n0.net,URI:https://github.com/3v1n0/
EOF
sub_intermediate_ca_trusted_cert_0001_key_pass="pass:random-sub-intermediate-ca-trusted-cert-0001-${RANDOM}"
openssl genrsa -aes256 \
-out "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001-key.pem" \
-passout "$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$keys_size"
openssl req \
-new -nodes \
-reqexts req_exts \
-passin "$sub_intermediate_ca_trusted_cert_0001_key_pass" \
-key "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001-key.pem" \
-config "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.config" \
-out "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001-request.pem"
openssl req -text -noout \
-in "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001-request.pem"
openssl ca \
-passin "$sub_intermediate_ca_key_pass" \
-config "$tmpdir/test-sub-intermediate-CA.config" -batch -notext \
-keyfile "$tmpdir/test-sub-intermediate-CA-key.pem" \
-in "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001-request.pem" \
-days 365 -extensions usr_cert \
-out "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
openssl x509 -noout \
-in "$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
echo "This certificate should not be trusted fully"
expect_fail \
openssl verify \
-CAfile "$tmpdir/test-sub-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
expect_fail \
openssl verify \
-CAfile "$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
openssl verify -partial_chain \
-CAfile "$tmpdir/test-sub-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
expect_fail \
openssl verify -partial_chain \
-CAfile "$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
## Full chain verification tests
echo "Building a the full-chain CA file..."
cat \
"$tmpdir/test-root-CA.pem" \
"$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA.pem" \
> "$tmpdir/test-full-chain-CA.pem"
cat \
"$tmpdir/test-root-CA.pem" \
"$tmpdir/test-intermediate-CA.pem" \
> "$tmpdir/test-root-intermediate-chain-CA.pem"
cat \
"$tmpdir/test-intermediate-CA.pem" \
"$tmpdir/test-sub-intermediate-CA.pem" \
> "$tmpdir/test-intermediate-sub-chain-CA.pem"
openssl crl2pkcs7 \
-nocrl -certfile "$tmpdir/test-full-chain-CA.pem" \
| openssl pkcs7 -print_certs -noout
openssl verify \
-CAfile "$tmpdir/test-full-chain-CA.pem" \
"$tmpdir/test-intermediate-CA.pem"
openssl verify \
-CAfile "$tmpdir/test-full-chain-CA.pem" \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem"
openssl verify \
-CAfile "$tmpdir/test-full-chain-CA.pem" \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem"
openssl verify \
-CAfile "$tmpdir/test-full-chain-CA.pem" \
"$tmpdir/test-root-intermediate-chain-CA.pem"
openssl verify \
-CAfile "$tmpdir/test-full-chain-CA.pem" \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem"
echo "Certificates generation completed!"
function prepare_softhsm2_card() {
local certificate="$1"
local key_pass="$2"
local key_cn
local key_name
local tokens_dir
local output_cert_file
token_name=
key_name="$(basename "$certificate" .pem)"
key_cn="$(openssl x509 -noout -subject -nameopt multiline -in "$certificate" \
| sed -n 's/ *commonName *= //p')"
if [ -v SOFTHSM2_ISOLATED_CONFIGS ]; then
key_name+="-${RANDOM}"
fi
export SOFTHSM2_CONF="$tmpdir/softhsm2-${key_name}.conf"
tokens_dir="$tmpdir/$(basename "$SOFTHSM2_CONF" .conf)"
token_name="${key_cn:0:25} Token"
if [ ! -e "$SOFTHSM2_CONF" ] || [ ! -d "$tokens_dir" ]; then
local key_file
local decrypted_key
mkdir -p "$tokens_dir"
key_file="$tmpdir/${key_name}-key.pem"
decrypted_key="$tmpdir/${key_name}-key-decrypted.pem"
cat <<EOF > "$SOFTHSM2_CONF"
directories.tokendir = $tokens_dir
objectstore.backend = file
slots.removable = true
EOF
softhsm2-util --init-token \
--label "$token_name" \
--pin "$PIN" --so-pin "$PIN" --free || return 2
softhsm2-util --show-slots || return 2
p11tool \
--provider="$SOFTHSM2_MODULE" \
--write \
--no-mark-private \
--load-certificate="$certificate" \
--login --set-pin="$PIN" \
--label "$key_cn" \
--id "$TOKEN_ID" || return 2
openssl rsa \
-passin "$key_pass" \
-in "$key_file" \
-out "$decrypted_key" || return 2
p11tool \
--provider="$SOFTHSM2_MODULE" \
--write \
--load-privkey="$decrypted_key" \
--login --set-pin="$PIN" \
--label "$key_cn Key" \
--id "$TOKEN_ID" || return 2
rm "$decrypted_key"
p11tool \
--provider="$SOFTHSM2_MODULE" \
--list-all || return 2
fi
echo "$token_name"
}
function check_certificate() {
local certificate="$1"
local key_pass="$2"
local key_ring="$3"
local verify_option="$4"
prepare_softhsm2_card "$certificate" "$key_pass" || return 2
if [ -n "$verify_option" ]; then
local verify_arg="--verify=$verify_option"
fi
local output_base_name="SSSD-child-${RANDOM}"
local output_file="$tmpdir/$output_base_name.output"
output_cert_file="$tmpdir/$output_base_name.pem"
"$SSSD_P11_CHILD" \
--pre -d 10 \
--logger=stderr \
--debug-fd=2 \
--module_name="$SOFTHSM2_MODULE" \
"$verify_arg" \
--${ca_db_arg}="$key_ring" > "$output_file" || return 2
grep -qs "$TOKEN_ID" "$output_file" || return 2
echo "-----BEGIN CERTIFICATE-----" > "$output_cert_file"
tail -n1 "$output_file" >> "$output_cert_file"
echo "-----END CERTIFICATE-----" >> "$output_cert_file"
openssl x509 -text -noout -in "$output_cert_file" || return 2
local found_md5 expected_md5
expected_md5=$(openssl x509 -noout -modulus -in "$certificate")
found_md5=$(openssl x509 -noout -modulus -in "$output_cert_file")
if [ "$expected_md5" != "$found_md5" ]; then
echo "Unexpected certificate found: $found_md5"
return 3
fi
# Try to authorize now!
output_file="$tmpdir/${output_base_name}-auth.output"
output_cert_file="$tmpdir/$(basename "$output_file" .output).pem"
echo -n "$PIN" | "$SSSD_P11_CHILD" \
--auth -d 10 --debug-fd=2 \
--${ca_db_arg}="$key_ring" \
--pin \
--key_id "$TOKEN_ID" \
"$verify_arg" \
--token_name "$token_name" \
--module_name "$SOFTHSM2_MODULE" > "$output_file" || return 2
grep -qs "$TOKEN_ID" "$output_file" || return 2
echo "-----BEGIN CERTIFICATE-----" > "$output_cert_file"
tail -n1 "$output_file" >> "$output_cert_file"
echo "-----END CERTIFICATE-----" >> "$output_cert_file"
openssl x509 -text -noout -in "$output_cert_file" || return 2
found_md5=$(openssl x509 -noout -modulus -in "$output_cert_file")
if [ "$expected_md5" != "$found_md5" ]; then
echo "Unexpected certificate found: $found_md5"
return 3
fi
}
function valid_certificate() {
if ! check_certificate "$@"; then
echo "Unexpected failure!"
exit 2
fi
}
function invalid_certificate() {
if check_certificate "$@"; then
echo "Unexpected pass!"
exit 2
fi
}
if [[ -v NO_SSSD_TESTS ]]; then
if [[ -v GENERATE_SMART_CARDS ]]; then
prepare_softhsm2_card \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass"
prepare_softhsm2_card \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass"
prepare_softhsm2_card \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass"
fi
echo "Certificates generation completed!"
exit 0
fi
## Checking that Root CA Trusted certificate is accepted
invalid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
/dev/null
valid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
/dev/null \
"no_verification"
valid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem"
valid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem" \
"partial_chain"
valid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem"
valid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem" \
"partial_chain"
invalid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-intermediate-CA.pem"
invalid_certificate \
"$tmpdir/test-root-CA-trusted-certificate-0001.pem" \
"$root_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-intermediate-CA.pem" \
"partial_chain"
## Checking that Intermediate CA Trusted certificate is accepted
invalid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
/dev/null
valid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
/dev/null \
"no_verification"
invalid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem"
invalid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem" \
"partial_chain"
valid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem"
valid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem" \
"partial_chain"
invalid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-intermediate-CA.pem"
valid_certificate \
"$tmpdir/test-intermediate-CA-trusted-certificate-0001.pem" \
"$intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-intermediate-CA.pem" \
"partial_chain"
## Checking that Sub Intermediate CA Trusted certificate is accepted
invalid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem"
invalid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-CA.pem" \
"partial_chain"
valid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem"
valid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-full-chain-CA.pem" \
"partial_chain"
invalid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-sub-intermediate-CA.pem"
invalid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-root-intermediate-chain-CA.pem" \
"partial_chain"
valid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-sub-intermediate-CA.pem" \
"partial_chain"
valid_certificate \
"$tmpdir/test-sub-intermediate-CA-trusted-certificate-0001.pem" \
"$sub_intermediate_ca_trusted_cert_0001_key_pass" \
"$tmpdir/test-intermediate-sub-chain-CA.pem" \
"partial_chain"
set +x
echo
echo "Test completed, Root CA and intermediate issued certificates verified!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment