diff -Nru gdm3-42.0/debian/changelog gdm3-42.0/debian/changelog --- gdm3-42.0/debian/changelog 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/changelog 2023-01-31 04:24:48.000000000 +0000 @@ -1,3 +1,19 @@ +gdm3 (42.0-1ubuntu7.22.04.1) jammy; urgency=medium + + * debian: Update vcs references to ubuntu/jammy branch + * debian/gdm3-gdm-smartcard*: Do not fail if pam_succeed_if suceeded. + We were not handling the success case in pam_succeed_if.so, and so even + if other modules were successful, gdm-smartcard was failing with a + permission denied error, because the pam_succeed_if default was bad, and + this was applied to the success case too. + Alternatively we could even just use success=ignore here, but it's + better to be consistent with other usages. (LP: #1999884) + * debian/tests: Add autopkg tests testing gdm smartcard authentication. + Create fake certificates from fake CA's and verify they can be used with + from a virtual smartcard. + + -- Marco Trevisan (TreviƱo) Tue, 31 Jan 2023 05:24:48 +0100 + gdm3 (42.0-1ubuntu7) jammy; urgency=medium [ Alberto Milone ] diff -Nru gdm3-42.0/debian/control gdm3-42.0/debian/control --- gdm3-42.0/debian/control 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/control 2023-01-31 04:24:48.000000000 +0000 @@ -45,8 +45,8 @@ Standards-Version: 4.6.0 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/gdm -Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git -b ubuntu/master -Vcs-Browser: https://salsa.debian.org/gnome-team/gdm/tree/ubuntu/master +Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git -b ubuntu/jammy +Vcs-Browser: https://salsa.debian.org/gnome-team/gdm/tree/ubuntu/jammy Rules-Requires-Root: no Homepage: https://wiki.gnome.org/Projects/GDM/ diff -Nru gdm3-42.0/debian/control.in gdm3-42.0/debian/control.in --- gdm3-42.0/debian/control.in 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/control.in 2023-01-31 04:24:48.000000000 +0000 @@ -41,8 +41,8 @@ Standards-Version: 4.6.0 XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/gdm -Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git -b ubuntu/master -Vcs-Browser: https://salsa.debian.org/gnome-team/gdm/tree/ubuntu/master +Vcs-Git: https://salsa.debian.org/gnome-team/gdm.git -b ubuntu/jammy +Vcs-Browser: https://salsa.debian.org/gnome-team/gdm/tree/ubuntu/jammy Rules-Requires-Root: no Homepage: https://wiki.gnome.org/Projects/GDM/ diff -Nru gdm3-42.0/debian/gbp.conf gdm3-42.0/debian/gbp.conf --- gdm3-42.0/debian/gbp.conf 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/gbp.conf 2023-01-31 04:24:48.000000000 +0000 @@ -1,6 +1,6 @@ [DEFAULT] pristine-tar = True -debian-branch=ubuntu/master +debian-branch=ubuntu/jammy upstream-branch = upstream/latest upstream-vcs-tag = %(version%~%.)s debian-tag = ubuntu/%(version)s diff -Nru gdm3-42.0/debian/gdm3.gdm-smartcard-pkcs11-exclusive.pam gdm3-42.0/debian/gdm3.gdm-smartcard-pkcs11-exclusive.pam --- gdm3-42.0/debian/gdm3.gdm-smartcard-pkcs11-exclusive.pam 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/gdm3.gdm-smartcard-pkcs11-exclusive.pam 2023-01-31 04:24:48.000000000 +0000 @@ -1,5 +1,5 @@ #%PAM-1.0 -auth [user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success +auth [success=ok user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success auth required pam_pkcs11.so auth required pam_succeed_if.so user != root quiet_success auth requisite pam_nologin.so diff -Nru gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-exclusive.pam gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-exclusive.pam --- gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-exclusive.pam 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-exclusive.pam 2023-01-31 04:24:48.000000000 +0000 @@ -1,5 +1,5 @@ #%PAM-1.0 -auth [user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success +auth [success=ok user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success auth required pam_sss.so allow_missing_name require_cert_auth auth requisite pam_nologin.so auth optional pam_gnome_keyring.so diff -Nru gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-or-password.pam gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-or-password.pam --- gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-or-password.pam 2022-04-21 10:32:09.000000000 +0000 +++ gdm3-42.0/debian/gdm3.gdm-smartcard-sssd-or-password.pam 2023-01-31 04:24:48.000000000 +0000 @@ -1,5 +1,5 @@ #%PAM-1.0 -auth [user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success +auth [success=ok user_unknown=ignore default=bad] pam_succeed_if.so user != root quiet_success auth sufficient pam_sss.so allow_missing_name try_cert_auth auth requisite pam_nologin.so @include common-auth diff -Nru gdm3-42.0/debian/tests/control gdm3-42.0/debian/tests/control --- gdm3-42.0/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ gdm3-42.0/debian/tests/control 2023-01-31 04:24:48.000000000 +0000 @@ -0,0 +1,23 @@ +Test-Command: env + OFFLINE_MODE=1 + GDM_USER=gdm + bash debian/tests/sssd-gdm-smartcard-pam-auth-tester-env.sh +Features: test-name=sssd-gdm-smartcard-auth-test +Classes: desktop +Depends: adduser, + bash, + gdm3, + gnutls-bin, + libpam-sss, + openssl, + pamtester, + passwd, + softhsm2, + sssd, + sudo, + util-linux +Restrictions: breaks-testbed, + isolation-container, + needs-root, + allow-stderr + diff -Nru gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester-env.sh gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester-env.sh --- gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester-env.sh 1970-01-01 00:00:00.000000000 +0000 +++ gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester-env.sh 2023-01-31 04:24:48.000000000 +0000 @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +if adduser --disabled-password --gecos "" tester; then + usermod -a -G sudo tester + echo "tester ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers +fi + +runuser -u tester -- sudo -E bash \ + debian/tests/sssd-gdm-smartcard-pam-auth-tester.sh diff -Nru gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester.sh gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester.sh --- gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester.sh 1970-01-01 00:00:00.000000000 +0000 +++ gdm3-42.0/debian/tests/sssd-gdm-smartcard-pam-auth-tester.sh 2023-01-31 04:24:48.000000000 +0000 @@ -0,0 +1,252 @@ +#!/usr/bin/env bash +# Copyright 2023 - Marco Trevisan +# Released under the GPLv3 terms +# +# A simple tool to simulate PAM authentication using GDM smartcard settings +# +# 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" ]; 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 +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/passwd +backup_file /etc/shadow + +# Ensure that the test user has a non-trivial password. If it had a blank +# password, then /etc/pam.d/gdm-smartcard-sssd-or-password would always +# authenticate successfully +if pamtester -v gdm-password "$SUDO_USER" authenticate /etc/sssd/sssd.conf || return 2 +[sssd] +enable_files_domain = True +services = pam +#certificate_verification = $verification_options + +[certmap/implicit_files/$SUDO_USER] +matchrule = .*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 + sudo update-alternatives --set gdm-smartcard "$alternative" + + 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" diff -Nru gdm3-42.0/debian/tests/sssd-softhism2-certificates-tests.sh gdm3-42.0/debian/tests/sssd-softhism2-certificates-tests.sh --- gdm3-42.0/debian/tests/sssd-softhism2-certificates-tests.sh 1970-01-01 00:00:00.000000000 +0000 +++ gdm3-42.0/debian/tests/sssd-softhism2-certificates-tests.sh 2023-01-31 04:24:48.000000000 +0000 @@ -0,0 +1,896 @@ +#!/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 < "$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 < "$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 < "$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 < "$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 \ + "$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!"