From 23d1b29d381851e905b88e331fe3931aedf8cc36 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Thu, 12 Jun 2025 21:36:45 +0000 Subject: [PATCH] Add test case for pam_pkcs11 --- .github/scripts/pam-pkcs11-test.sh | 150 +++++++++++++++++++++++++++++ .github/workflows/pam_pkcs11.yml | 74 ++++++++++++++ 2 files changed, 224 insertions(+) create mode 100755 .github/scripts/pam-pkcs11-test.sh create mode 100644 .github/workflows/pam_pkcs11.yml diff --git a/.github/scripts/pam-pkcs11-test.sh b/.github/scripts/pam-pkcs11-test.sh new file mode 100755 index 00000000..c49e514a --- /dev/null +++ b/.github/scripts/pam-pkcs11-test.sh @@ -0,0 +1,150 @@ +#!/bin/bash +set -euo pipefail + +echo "[*] Setting up environment..." +SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")" +REPO_ROOT=$(git -C "$(dirname "$SCRIPT_PATH")" rev-parse --show-toplevel) +source $REPO_ROOT/scripts/env-setup || true + +if [[ -z "${OPENSSL_MODULES:-}" ]]; then + echo "Environment not set up: OPENSSL_MODULES is not defined or empty" + exit 1 +elif [[ ! -d "$OPENSSL_MODULES" ]]; then + echo "Could not find wolfProvider at $OPENSSL_MODULES" + echo "Please build it first..." + exit 1 +fi + +echo "[*] Installing build dependencies..." +apt-get update +DEBIAN_FRONTEND=noninteractive apt-get install -y \ + git \ + build-essential \ + autotools-dev \ + autoconf \ + libtool \ + pkg-config \ + libpam0g-dev \ + libnss3-dev \ + libpcsclite-dev \ + opensc \ + softhsm2 \ + pcscd \ + pcsc-tools \ + sudo \ + systemd \ + ssh \ + vim \ + gnupg \ + wget \ + curl + +echo "[*] Cloning pam_pkcs11..." +cd /opt +if [[ ! -d "pam_pkcs11" ]]; then + git clone https://github.com/OpenSC/pam_pkcs11.git +fi +cd pam_pkcs11 + +echo "[*] Building pam_pkcs11 from source..." +./bootstrap +./configure --prefix=/usr --sysconfdir=/etc --with-pam-dir=/lib/security --disable-nls +make -j"$(nproc)" +make install + +echo "[*] Creating test user..." +if ! id -u testuser &>/dev/null; then + useradd -m testuser + echo 'testuser:testpass' | chpasswd + echo "[*] Created user 'testuser'" +else + echo "[*] User 'testuser' already exists, skipping creation" +fi + +echo "[*] Configuring pam_pkcs11..." + +# Generate dummy CA cert if missing +if [ ! -f /test/certs/test-ca.crt ]; then + echo "[*] Generating dummy test-ca.crt..." + mkdir -p /test/certs + openssl req -x509 -newkey rsa:2048 -nodes \ + -keyout /test/certs/test-ca.key \ + -out /test/certs/test-ca.crt \ + -days 365 -subj "/CN=Test CA/O=Example" +fi + +mkdir -p /etc/pam_pkcs11/cacerts +cp /test/certs/test-ca.crt /etc/pam_pkcs11/cacerts/ +pkcs11_make_hash_link /etc/pam_pkcs11/cacerts/ + +# Generate test certificate and key if missing +if [ ! -f /test/certs/test-cert.pem ]; then + echo "[*] Generating test-cert.pem and key..." + mkdir -p /test/certs + openssl req -newkey rsa:2048 -nodes \ + -keyout /test/certs/test-key.pem \ + -x509 -days 365 -out /test/certs/test-cert.pem \ + -subj "/CN=Test User/OU=Testing/O=Example Corp/C=US" +fi + +# Extract cert subject in one-line format suitable for pam_pkcs11 +CERT_SUBJECT=$(openssl x509 -in /test/certs/test-cert.pem -noout -subject -nameopt oneline | sed 's/subject=//') + +echo "[*] Writing pkcs11_mapper.map with subject: $CERT_SUBJECT" + +echo "subject=$CERT_SUBJECT; uid=testuser" | tee /etc/pam_pkcs11/pkcs11_mapper.map > /dev/null + +# Backup and modify PAM config +cp /etc/pam.d/common-auth /etc/pam.d/common-auth.bak +echo "auth sufficient pam_pkcs11.so debug" | tee /etc/pam.d/common-auth > /dev/null +cat /etc/pam.d/common-auth.bak | tee -a /etc/pam.d/common-auth > /dev/null + +echo "[*] Initializing SoftHSM (simulated smartcard)..." +mkdir -p /var/lib/softhsm/tokens +softhsm2-util --init-token --free --label "testtoken" --pin 1234 --so-pin 123456 + +echo "[*] Importing test certificate into SoftHSM..." +pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so \ + --login --pin 1234 --write-object /test/certs/test-cert.pem --type cert --label "testcert" + +echo "[*] Starting pcscd..." +if ps aux | grep '[p]cscd' > /dev/null; then + echo "pcscd is already running" +else + echo "pcscd is not running, starting it now..." + pcscd & +fi + +echo "[*] Creating pam_pkcs11.conf..." +if [ -f "./etc/pam_pkcs11.conf.example" ]; then + cp ./etc/pam_pkcs11.conf.example /etc/pam_pkcs11/pam_pkcs11.conf +else + echo "ERROR: pam_pkcs11.conf.example not found in current directory" + exit 1 +fi + +echo "[*] Configuring pam_pkcs11.conf for SoftHSM module..." + +# Set correct module usage line +sed -i 's|^use_pkcs11_module.*|use_pkcs11_module = softhsm;|' /etc/pam_pkcs11/pam_pkcs11.conf + +# Set the SoftHSM module path +sed -i '/^pkcs11_module softhsm {/,/^}/ s|^\s*module\s*=.*| module = /usr/lib/softhsm/libsofthsm2.so;|' /etc/pam_pkcs11/pam_pkcs11.conf + +echo "[*] Checking SoftHSM PKCS#11 module dependencies..." +ldd /usr/lib/softhsm/libsofthsm2.so | tee /tmp/libsofthsm2.ldd +if grep -q "not found" /tmp/libsofthsm2.ldd; then + echo "ERROR: Missing dependencies for SoftHSM PKCS#11 module!" + exit 1 +fi + +echo "[*] Testing SoftHSM PKCS#11 module loadability with pkcs11-tool..." +if ! pkcs11-tool --module /usr/lib/softhsm/libsofthsm2.so -L; then + echo "ERROR: Failed to load SoftHSM PKCS#11 module" + exit 1 +fi + +echo "[*] Testing login via su..." +su testuser -c 'echo "✅ Logged in as testuser"' + +echo "[*] All done." diff --git a/.github/workflows/pam_pkcs11.yml b/.github/workflows/pam_pkcs11.yml new file mode 100644 index 00000000..5edf2f79 --- /dev/null +++ b/.github/workflows/pam_pkcs11.yml @@ -0,0 +1,74 @@ +name: pam_pkcs11 Tests + +# START OF COMMON SECTION +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + build_wolfprovider: + uses: ./.github/workflows/build-wolfprovider.yml + with: + wolfssl_ref: ${{ matrix.wolfssl_ref }} + openssl_ref: ${{ matrix.openssl_ref }} + strategy: + matrix: + wolfssl_ref: [ 'master', 'v5.8.0-stable' ] + openssl_ref: [ 'openssl-3.5.0' ] + + test_pam_pkcs11: + runs-on: ubuntu-22.04 + needs: build_wolfprovider + # This should be a safe limit for the tests to run. + timeout-minutes: 20 + strategy: + matrix: + pam_pkcs11_ref: [ 'master', 'pam_pkcs11-0.6.12' ] + wolfssl_ref: [ 'master', 'v5.8.0-stable' ] + openssl_ref: [ 'openssl-3.5.0' ] + force_fail: [ 'WOLFPROV_FORCE_FAIL=1', '' ] + exclude: + - curl_ref: 'master' + force_fail: 'WOLFPROV_FORCE_FAIL=1' + steps: + # Checkout the source so we can run the check-workflow-result script + - name: Checkout wolfProvider + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Retrieving wolfSSL/wolfProvider from cache + uses: actions/cache/restore@v4 + id: wolfprov-cache + with: + path: | + wolfssl-install + wolfprov-install + openssl-install/lib64 + openssl-install/include + openssl-install/bin + + key: wolfprov-${{ matrix.wolfssl_ref }}-${{ matrix.openssl_ref }}-${{ github.sha }} + fail-on-cache-miss: true + + - name: Run pam_pkcs11 tests + run: | + # Setup environment variables + source $GITHUB_WORKSPACE/scripts/env-setup + + # Run tests + if timeout 300 ${{ matrix.force_fail }} sudo bash -c $GITHUB_WORKSPACE/.github/scripts/pam-pkcs11-test.sh; then + TEST_RESULT=0 + else + TEST_RESULT=1 + fi + + # Capture result + $GITHUB_WORKSPACE/.github/scripts/check-workflow-result.sh $TEST_RESULT ${{ matrix.force_fail }} pam_pkcs11