From 24f0b4ca2d565cdbb4fe7839ff28320706bf2386 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Wed, 16 Apr 2025 19:13:41 -0700 Subject: pam-krb5: Import/add pam-krb5 from eyeire.org From https://www.eyrie.org/~eagle/software/pam-krb5/: pam-krb5 provides a Kerberos PAM module that supports authentication, user ticket cache handling, simple authorization (via .k5login or checking Kerberos principals against local usernames), and password changing. It can be configured through either options in the PAM configuration itself or through entries in the system krb5.conf file, and it tries to work around PAM implementation flaws in commonly-used PAM-enabled applications such as OpenSSH and xdm. It supports both PKINIT and FAST to the extent that the underlying Kerberos libraries support these features. The reason for this import is to provide an MIT KRB5 compatible pam_krb5 PAM module. The existing pam_krb5 in FreeBS only works with Heimdal. Sponsored by: The FreeBSD Foundation --- ci/README.md | 13 +++++ ci/files/heimdal/heimdal-kdc | 9 ++++ ci/files/heimdal/kadmind.acl | 1 + ci/files/heimdal/kdc.conf | 30 ++++++++++++ ci/files/heimdal/krb5.conf | 19 ++++++++ ci/files/heimdal/pki-mapping | 1 + ci/files/mit/extensions.client | 19 ++++++++ ci/files/mit/extensions.kdc | 20 ++++++++ ci/files/mit/kadm5.acl | 1 + ci/files/mit/kdc.conf | 19 ++++++++ ci/files/mit/krb5.conf | 19 ++++++++ ci/install | 18 +++++++ ci/kdc-setup-heimdal | 105 +++++++++++++++++++++++++++++++++++++++++ ci/kdc-setup-mit | 102 +++++++++++++++++++++++++++++++++++++++ ci/test | 44 +++++++++++++++++ 15 files changed, 420 insertions(+) create mode 100644 ci/README.md create mode 100644 ci/files/heimdal/heimdal-kdc create mode 100644 ci/files/heimdal/kadmind.acl create mode 100644 ci/files/heimdal/kdc.conf create mode 100644 ci/files/heimdal/krb5.conf create mode 100644 ci/files/heimdal/pki-mapping create mode 100644 ci/files/mit/extensions.client create mode 100644 ci/files/mit/extensions.kdc create mode 100644 ci/files/mit/kadm5.acl create mode 100644 ci/files/mit/kdc.conf create mode 100644 ci/files/mit/krb5.conf create mode 100755 ci/install create mode 100755 ci/kdc-setup-heimdal create mode 100755 ci/kdc-setup-mit create mode 100755 ci/test (limited to 'ci') diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 000000000000..fedd0d57fd08 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,13 @@ +# Continuous Integration + +The files in this directory are used for continuous integration testing. +`ci/install` installs the prerequisite packages (run as root on a Debian +derivative), and `ci/test` runs the tests. + +Most tests will be skipped without a Kerberos configuration. The scripts +`ci/kdc-setup-heimdal` and `ci/kdc-setup-mit` will (when run as root on a +Debian derivative) set up a Heimdal or MIT Kerberos KDC, respectively, and +generate the files required to run the complete test suite. + +Tests are run automatically via GitHub Actions workflows using these +scripts and the configuration in the `.github/workflows` directory. diff --git a/ci/files/heimdal/heimdal-kdc b/ci/files/heimdal/heimdal-kdc new file mode 100644 index 000000000000..d7814631746d --- /dev/null +++ b/ci/files/heimdal/heimdal-kdc @@ -0,0 +1,9 @@ +# Heimdal KDC init script setup. -*- sh -*- + +# KDC configuration. +KDC_ENABLED=yes +KDC_PARAMS='--config-file=/etc/heimdal-kdc/kdc.conf' + +# kpasswdd configuration. +KPASSWDD_ENABLED=yes +KPASSWDD_PARAMS='-r HEIMDAL.TEST' diff --git a/ci/files/heimdal/kadmind.acl b/ci/files/heimdal/kadmind.acl new file mode 100644 index 000000000000..ae74ad5598ad --- /dev/null +++ b/ci/files/heimdal/kadmind.acl @@ -0,0 +1 @@ +test/admin@HEIMDAL.TEST all testuser@HEIMDAL.TEST diff --git a/ci/files/heimdal/kdc.conf b/ci/files/heimdal/kdc.conf new file mode 100644 index 000000000000..29ac52ebb947 --- /dev/null +++ b/ci/files/heimdal/kdc.conf @@ -0,0 +1,30 @@ +# Heimdal KDC configuration. -*- conf -*- + +[kadmin] + default_keys = aes256-cts-hmac-sha1-96:pw-salt + +[kdc] + acl_file = /etc/heimdal-kdc/kadmind.acl + check-ticket-addresses = false + logging = SYSLOG:NOTICE + ports = 88 + + # PKINIT configuration. + enable-pkinit = yes + pkinit_identity = FILE:/etc/heimdal-kdc/kdc.pem + pkinit_anchors = FILE:/etc/heimdal-kdc/ca/ca.pem + pkinit_mappings_file = /etc/heimdal-kdc/pki-mapping + pkinit_allow_proxy_certificate = no + pkinit_principal_in_certificate = no + +[libdefaults] + default_realm = HEIMDAL.TEST + dns_lookup_kdc = false + dns_lookup_realm = false + +[realms] + HEIMDAL.TEST.EYRIE.ORG = { + kdc = 127.0.0.1 + master_kdc = 127.0.0.1 + admin_server = 127.0.0.1 + } diff --git a/ci/files/heimdal/krb5.conf b/ci/files/heimdal/krb5.conf new file mode 100644 index 000000000000..a2b22c2d54cd --- /dev/null +++ b/ci/files/heimdal/krb5.conf @@ -0,0 +1,19 @@ +[libdefaults] + default_realm = HEIMDAL.TEST + dns_lookup_kdc = false + dns_lookup_realm = false + rdns = false + renew_lifetime = 7d + ticket_lifetime = 25h + +[realms] + HEIMDAL.TEST = { + kdc = 127.0.0.1 + master_kdc = 127.0.0.1 + admin_server = 127.0.0.1 + pkinit_anchors = FILE:/etc/heimdal-kdc/ca/ca.pem + } + +[logging] + kdc = SYSLOG:NOTICE + default = SYSLOG:NOTICE diff --git a/ci/files/heimdal/pki-mapping b/ci/files/heimdal/pki-mapping new file mode 100644 index 000000000000..76dd6b87edb6 --- /dev/null +++ b/ci/files/heimdal/pki-mapping @@ -0,0 +1 @@ +testuser@HEIMDAL.TEST:UID=testuser,DC=HEIMDAL,DC=TEST diff --git a/ci/files/mit/extensions.client b/ci/files/mit/extensions.client new file mode 100644 index 000000000000..5a1bbc29bdec --- /dev/null +++ b/ci/files/mit/extensions.client @@ -0,0 +1,19 @@ +[client_cert] +basicConstraints=CA:FALSE +keyUsage=digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage=1.3.6.1.5.2.3.4 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer +issuerAltName=issuer:copy +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name + +[princ_name] +realm=EXP:0,GeneralString:${ENV::REALM} +principal_name=EXP:1,SEQUENCE:principal_seq + +[principal_seq] +name_type=EXP:0,INTEGER:1 +name_string=EXP:1,SEQUENCE:principals + +[principals] +princ1=GeneralString:${ENV::CLIENT} diff --git a/ci/files/mit/extensions.kdc b/ci/files/mit/extensions.kdc new file mode 100644 index 000000000000..cbff73bef1ed --- /dev/null +++ b/ci/files/mit/extensions.kdc @@ -0,0 +1,20 @@ +[kdc_cert] +basicConstraints=CA:FALSE +keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage=1.3.6.1.5.2.3.5 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer +issuerAltName=issuer:copy +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name + +[kdc_princ_name] +realm=EXP:0,GeneralString:${ENV::REALM} +principal_name=EXP:1,SEQUENCE:kdc_principal_seq + +[kdc_principal_seq] +name_type=EXP:0,INTEGER:1 +name_string=EXP:1,SEQUENCE:kdc_principals + +[kdc_principals] +princ1=GeneralString:krbtgt +princ2=GeneralString:${ENV::REALM} diff --git a/ci/files/mit/kadm5.acl b/ci/files/mit/kadm5.acl new file mode 100644 index 000000000000..652bbecb84b2 --- /dev/null +++ b/ci/files/mit/kadm5.acl @@ -0,0 +1 @@ +test/admin@MIT.TEST mci testuser@MIT.TEST diff --git a/ci/files/mit/kdc.conf b/ci/files/mit/kdc.conf new file mode 100644 index 000000000000..7bf4e6a06e95 --- /dev/null +++ b/ci/files/mit/kdc.conf @@ -0,0 +1,19 @@ +[kdcdefaults] + kdc_ports = 88 + kdc_tcp_ports = 88 + restrict_anonymous_to_tgt = true + +[realms] + MIT.TEST = { + database_name = /var/lib/krb5kdc/principal + admin_keytab = /var/lib/krb5kdc/kadm5.keytab + acl_file = /etc/krb5kdc/kadm5.acl + key_stash_file = /var/lib/krb5kdc/stash + max_life = 1d 1h 0m 0s + max_renewable_life = 7d 0h 0m 0s + master_key_type = aes256-cts + supported_enctypes = aes256-cts:normal + default_principal_flags = +preauth + pkinit_identity = FILE:/var/lib/krb5kdc/kdc.pem,/var/lib/krb5kdc/kdckey.pem + pkinit_anchors = FILE:/etc/krb5kdc/cacert.pem + } diff --git a/ci/files/mit/krb5.conf b/ci/files/mit/krb5.conf new file mode 100644 index 000000000000..9b0d5ab9dbdf --- /dev/null +++ b/ci/files/mit/krb5.conf @@ -0,0 +1,19 @@ +[libdefaults] + default_realm = MIT.TEST + dns_lookup_kdc = false + dns_lookup_realm = false + rdns = false + renew_lifetime = 7d + ticket_lifetime = 25h + +[realms] + MIT.TEST = { + kdc = 127.0.0.1 + master_kdc = 127.0.0.1 + admin_server = 127.0.0.1 + pkinit_anchors = FILE:/etc/krb5kdc/cacert.pem + } + +[logging] + kdc = SYSLOG:NOTICE + default = SYSLOG:NOTICE diff --git a/ci/install b/ci/install new file mode 100755 index 000000000000..b53ac2957546 --- /dev/null +++ b/ci/install @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Install packages for integration tests. +# +# This script is normally run via sudo in a test container or VM, such as via +# GitHub Actions. +# +# Copyright 2015-2021 Russ Allbery +# +# SPDX-License-Identifier: MIT + +set -eux + +# Install distribution packages. +apt-get update -qq +apt-get install aspell autoconf automake cppcheck heimdal-multidev \ + krb5-config libkrb5-dev libpam0g-dev libtest-pod-perl \ + libtest-spelling-perl libtool perl valgrind diff --git a/ci/kdc-setup-heimdal b/ci/kdc-setup-heimdal new file mode 100755 index 000000000000..9d15b1a4a6de --- /dev/null +++ b/ci/kdc-setup-heimdal @@ -0,0 +1,105 @@ +#!/bin/sh +# +# Build a Kerberos test realm for Heimdal. +# +# This script automates the process of setting up a Kerberos test realm from +# scratch suitable for testing pam-krb5. It is primarily intended to be run +# from inside CI in a VM or container from the top of the pam-krb5 source +# tree, and must be run as root. It expects to be operating on the Debian +# Heimdal package. +# +# Copyright 2014, 2020 Russ Allbery +# +# SPDX-License-Identifier: MIT + +set -eux + +# Install the KDC. +apt-get install heimdal-kdc + +# Install its configuration files. +cp ci/files/heimdal/heimdal-kdc /etc/default/heimdal-kdc +cp ci/files/heimdal/kadmind.acl /etc/heimdal-kdc/kadmind.acl +cp ci/files/heimdal/kdc.conf /etc/heimdal-kdc/kdc.conf +cp ci/files/heimdal/krb5.conf /etc/krb5.conf +cp ci/files/heimdal/pki-mapping /etc/heimdal-kdc/pki-mapping + +# Some versions of heimdal-kdc require this. +ln -s /etc/heimdal-kdc/kadmind.acl /var/lib/heimdal-kdc/kadmind.acl + +# Add domain-realm mappings for the local host, since otherwise Heimdal and +# MIT Kerberos may attempt to discover the realm of the local domain, and the +# DNS server for GitHub Actions has a habit of just not responding and causing +# the test to hang. +cat <>/etc/krb5.conf +[domain_realm] + $(hostname -f) = HEIMDAL.TEST +EOF +cat <>/etc/heimdal-kdc/kdc.conf +[domain_realm] + $(hostname -f) = HEIMDAL.TEST +EOF + +# Create the basic KDC. +kstash --random-key +kadmin -l init --realm-max-ticket-life='1 day 1 hour' \ + --realm-max-renewable-life='1 week' HEIMDAL.TEST + +# Set default principal policies. +kadmin -l modify --attributes=requires-pre-auth,disallow-svr \ + default@HEIMDAL.TEST + +# Create and store the keytabs. +kadmin -l add -r --use-defaults --attributes=requires-pre-auth \ + test/admin@HEIMDAL.TEST +kadmin -l ext_keytab -k tests/config/admin-keytab test/admin@HEIMDAL.TEST +kadmin -l add -r --use-defaults --attributes=requires-pre-auth \ + test/keytab@HEIMDAL.TEST +kadmin -l ext_keytab -k tests/config/keytab test/keytab@HEIMDAL.TEST + +# Create a user principal with a known password. +password="iceedKaicVevjunwiwyd" +kadmin -l add --use-defaults --password="$password" testuser@HEIMDAL.TEST +echo 'testuser@HEIMDAL.TEST' >tests/config/password +echo "$password" >>tests/config/password + +# Create the root CA for PKINIT. +mkdir -p /etc/heimdal-kdc/ca +hxtool issue-certificate --self-signed --issue-ca --generate-key=rsa \ + --subject=CN=CA,DC=HEIMDAL,DC=TEST --lifetime=10years \ + --certificate=FILE:/etc/heimdal-kdc/ca/ca.pem +chmod 644 /etc/heimdal-kdc/ca/ca.pem + +# Create the certificate for the Heimdal Kerberos KDC. +hxtool issue-certificate --ca-certificate=FILE:/etc/heimdal-kdc/ca/ca.pem \ + --generate-key=rsa --type=pkinit-kdc \ + --pk-init-principal=krbtgt/HEIMDAL.TEST@HEIMDAL.TEST \ + --subject=uid=kdc,DC=HEIMDAL,DC=TEST \ + --certificate=FILE:/etc/heimdal-kdc/kdc.pem +chmod 644 /etc/heimdal-kdc/kdc.pem + +# Create the certificate for the Heimdal client. +hxtool issue-certificate --ca-certificate=FILE:/etc/heimdal-kdc/ca/ca.pem \ + --generate-key=rsa --type=pkinit-client \ + --pk-init-principal=testuser@HEIMDAL.TEST \ + --subject=UID=testuser,DC=HEIMDAL,DC=TEST \ + --certificate=FILE:tests/config/pkinit-cert +echo 'testuser@HEIMDAL.TEST' >tests/config/pkinit-principal + +# Fix permissions on all the newly-created files. +chmod 644 tests/config/* + +# Restart the Heimdal KDC and services. +systemctl stop heimdal-kdc +systemctl start heimdal-kdc + +# Ensure that the KDC is running. +for n in $(seq 1 5); do + if echo "$password" \ + | kinit --password-file=STDIN testuser@HEIMDAL.TEST; then + break + fi + sleep 1 +done +klist +kdestroy diff --git a/ci/kdc-setup-mit b/ci/kdc-setup-mit new file mode 100755 index 000000000000..0b3dfb60b64b --- /dev/null +++ b/ci/kdc-setup-mit @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Build a Kerberos test realm for MIT Kerberos +# +# This script automates the process of setting up a Kerberos test realm from +# scratch suitable for testing pam-krb5. It is primarily intended to be run +# from inside CI in a VM or container from the top of the pam-krb5 source +# tree, and must be run as root. It expects to be operating on the Debian +# MIT Kerberos package. +# +# Copyright 2014, 2020 Russ Allbery +# +# SPDX-License-Identifier: MIT + +set -eux + +# Install the KDC and the OpenSSL command line tool. +apt-get install krb5-admin-server krb5-kdc krb5-pkinit openssl + +# Install its configuration files. +cp ci/files/mit/extensions.client /etc/krb5kdc/extensions.client +cp ci/files/mit/extensions.kdc /etc/krb5kdc/extensions.kdc +cp ci/files/mit/kadm5.acl /etc/krb5kdc/kadm5.acl +cp ci/files/mit/kdc.conf /etc/krb5kdc/kdc.conf +cp ci/files/mit/krb5.conf /etc/krb5.conf + +# Add domain-realm mappings for the local host, since otherwise Heimdal and +# MIT Kerberos may attempt to discover the realm of the local domain, and the +# DNS server for GitHub Actions has a habit of just not responding and causing +# the test to hang. +cat <>/etc/krb5.conf +[domain_realm] + $(hostname -f) = MIT.TEST +EOF + +# Create the basic KDC. +kdb5_util create -s -P 'this is a test master database password' + +# Create and store the keytabs. +kadmin.local -q 'add_principal +requires_preauth -randkey test/admin@MIT.TEST' +kadmin.local -q 'ktadd -k tests/config/admin-keytab test/admin@MIT.TEST' +kadmin.local -q 'add_principal +requires_preauth -randkey test/keytab@MIT.TEST' +kadmin.local -q 'ktadd -k tests/config/keytab test/keytab@MIT.TEST' + +# Enable anonymous PKINIT. +kadmin.local -q 'addprinc -randkey WELLKNOWN/ANONYMOUS' + +# Create a user principal with a known password. +password="iceedKaicVevjunwiwyd" +kadmin.local -q \ + "add_principal +requires_preauth -pw $password testuser@MIT.TEST" +echo 'testuser@MIT.TEST' >tests/config/password +echo "$password" >>tests/config/password + +# Create the root CA for PKINIT. +openssl genrsa -out /etc/krb5kdc/cakey.pem 2048 +openssl req -key /etc/krb5kdc/cakey.pem -new -x509 \ + -out /etc/krb5kdc/cacert.pem -subj "/CN=MIT.TEST CA" -days 3650 +chmod 755 /etc/krb5kdc +chmod 644 /etc/krb5kdc/cacert.pem + +# Create the certificate for the MIT Kerberos KDC. +openssl genrsa -out /var/lib/krb5kdc/kdckey.pem 2048 +openssl req -new -out /var/lib/krb5kdc/kdc.req \ + -key /var/lib/krb5kdc/kdckey.pem -subj "/CN=MIT.TEST" +REALM=MIT.TEST openssl x509 -req -in /var/lib/krb5kdc/kdc.req \ + -CAkey /etc/krb5kdc/cakey.pem -CA /etc/krb5kdc/cacert.pem \ + -out /var/lib/krb5kdc/kdc.pem -days 365 \ + -extfile /etc/krb5kdc/extensions.kdc -extensions kdc_cert \ + -CAcreateserial +rm /var/lib/krb5kdc/kdc.req + +# Create the certificate for the MIT Kerberos client. +openssl genrsa -out clientkey.pem 2048 +openssl req -new -key clientkey.pem -out client.req \ + -subj "/CN=testuser@MIT.TEST" +REALM="MIT.TEST" CLIENT="testuser" openssl x509 \ + -CAkey /etc/krb5kdc/cakey.pem -CA /etc/krb5kdc/cacert.pem -req \ + -in client.req -extensions client_cert \ + -extfile /etc/krb5kdc/extensions.client -days 365 -out client.pem +cat client.pem clientkey.pem >tests/config/pkinit-cert +rm clientkey.pem client.pem client.req +echo 'testuser@MIT.TEST' >tests/config/pkinit-principal + +# Fix permissions on all the newly-created files. +chmod 644 tests/config/* + +# Restart the MIT Kerberos KDC and services. +systemctl stop krb5-kdc krb5-admin-server +systemctl start krb5-kdc krb5-admin-server + +# Ensure that the KDC is running. +for n in $(seq 1 5); do + if echo "$password" | kinit testuser@MIT.TEST; then + break + fi + sleep 1 +done +klist +kdestroy +kinit -n @MIT.TEST +kinit -X X509_user_identity=FILE:tests/config/pkinit-cert testuser@MIT.TEST diff --git a/ci/test b/ci/test new file mode 100755 index 000000000000..b7844bdd75fe --- /dev/null +++ b/ci/test @@ -0,0 +1,44 @@ +#!/bin/sh +# +# Run tests for continuous integration. +# +# This script is normally run in a test container or VM, such as via GitHub +# Actions. +# +# Copyright 2015-2021 Russ Allbery +# +# SPDX-License-Identifier: MIT + +set -eux + +# Normally, KERBEROS is set based on the CI matrix, but provide a default in +# case someone runs this test by hand. +KERBEROS="${KERBEROS:-mit}" + +# Generate Autotools files. +./bootstrap + +# Build everything with Clang first, with warnings enabled. +if [ "$KERBEROS" = 'heimdal' ]; then + ./configure CC=clang PATH_KRB5_CONFIG=/usr/bin/krb5-config.heimdal +else + ./configure CC=clang +fi +make warnings + +# Then rebuild everything with GCC with warnings enabled. +make distclean +if [ "$KERBEROS" = 'heimdal' ]; then + ./configure CC=gcc PATH_KRB5_CONFIG=/usr/bin/krb5-config.heimdal +else + ./configure CC=gcc +fi +make warnings + +# Run the tests with valgrind. +make check-valgrind + +# Run additional style tests, but only in the MIT build. +if [ "$KERBEROS" = "mit" ]; then + make check-cppcheck +fi -- cgit v1.2.3